( organizationId: string, )
| 129 | * defect. |
| 130 | */ |
| 131 | const organizationFromDatabase = ( |
| 132 | organizationId: string, |
| 133 | ): Effect.Effect< |
| 134 | { readonly id: string; readonly name: string; readonly slug?: string }, |
| 135 | McpSessionMetaUnavailableError | OrganizationNotFoundError, |
| 136 | UserStoreService | WorkOSClient |
| 137 | > => |
| 138 | Effect.gen(function* () { |
| 139 | let attempts = 0; |
| 140 | // `Effect.retry` retries every failure it sees, so definitive failures are |
| 141 | // lifted OUT of the error channel before the schedule ever runs and only |
| 142 | // the retryable ones are left in it. |
| 143 | const attempt = Effect.suspend(() => { |
| 144 | attempts += 1; |
| 145 | return resolveOrganization(organizationId).pipe( |
| 146 | Effect.result, |
| 147 | Effect.flatMap((outcome) => |
| 148 | Result.isFailure(outcome) && isRetryableOrganizationLookupFailure(outcome.failure) |
| 149 | ? Effect.fail(outcome.failure) |
| 150 | : Effect.succeed(outcome), |
| 151 | ), |
| 152 | ); |
| 153 | }); |
| 154 | |
| 155 | // Two nested Results: the outer one is "the retries ran out", the inner one |
| 156 | // is "the lookup failed definitively on the first look". Both mean the same |
| 157 | // thing to the caller. |
| 158 | const retried = yield* attempt.pipe(Effect.retry(RETRY_SCHEDULE), Effect.result); |
| 159 | const outcome = Result.isFailure(retried) ? Result.fail(retried.failure) : retried.success; |
| 160 | |
| 161 | if (Result.isFailure(outcome)) { |
| 162 | return yield* new McpSessionMetaUnavailableError({ |
| 163 | reason: failureReason(outcome.failure), |
| 164 | attempts, |
| 165 | }); |
| 166 | } |
| 167 | const organization = outcome.success; |
| 168 | if (!organization) return yield* new OrganizationNotFoundError({ organizationId }); |
| 169 | return organization; |
| 170 | }).pipe( |
| 171 | Effect.withSpan("mcp.session.resolve_organization", { |
| 172 | attributes: { "mcp.auth.organization_id": organizationId }, |
| 173 | }), |
| 174 | ); |
| 175 | |
| 176 | /** |
| 177 | * Build the session meta for an init, preferring the org identity the request |
no test coverage detected