MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeFumaClient

Function makeFumaClient

packages/core/sdk/src/fuma-runtime.ts:174–222  ·  view source on GitHub ↗
(db: FumaDb, options: MakeFumaClientOptions = {})

Source from the content-addressed store, hash-verified

172};
173
174export const makeFumaClient = (db: FumaDb, options: MakeFumaClientOptions = {}): IFumaClient => {
175 const use: IFumaClient["use"] = (label, fn) =>
176 Effect.flatMap(Effect.service(activeFumaDbRef), (active) =>
177 fumaEffect(label, () => fn(makeSafeFumaQuery(active ?? db, options))),
178 ).pipe(Effect.withSpan(`fumadb.${label}`));
179
180 const transaction = <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | StorageFailure> =>
181 Effect.flatMap(Effect.service(activeFumaDbRef), (active) => {
182 if (active) return effect as Effect.Effect<unknown, unknown>;
183
184 // The outermost transaction owns the post-commit hook queue; hooks
185 // queued anywhere inside (including nested pass-through transactions)
186 // run only after THIS commit, and are discarded on rollback.
187 const commitHooks: Array<Effect.Effect<void>> = [];
188 return Effect.tryPromise({
189 try: () =>
190 db.transaction(async (transactionDb) => {
191 const exit = await Effect.runPromiseExit(
192 effect.pipe(
193 Effect.provideService(activeFumaDbRef, transactionDb),
194 Effect.provideService(pendingCommitHooksRef, commitHooks),
195 ),
196 );
197 if (Exit.isSuccess(exit)) return exit.value;
198
199 const failure = exit.cause.reasons.find(Cause.isFailReason);
200 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: FumaDB transactions roll back when the callback rejects
201 if (failure) throw new TransactionEffectFailure(failure.error);
202 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: FumaDB transactions roll back when the callback rejects
203 throw new TransactionEffectDefect(exit.cause);
204 }),
205 catch: (cause): E | StorageFailure => {
206 if (cause instanceof TransactionEffectFailure) return cause.error as E;
207 if (cause instanceof TransactionEffectDefect) {
208 return fumaFailureFromCause("transaction", cause.cause);
209 }
210 return fumaFailureFromCause("transaction", cause);
211 },
212 }).pipe(
213 Effect.tap(() =>
214 Effect.forEach(commitHooks, (hook) => hook.pipe(Effect.ignoreCause({ log: false })), {
215 discard: true,
216 }),
217 ),
218 );
219 }).pipe(Effect.withSpan("fumadb.transaction")) as Effect.Effect<A, E | StorageFailure>;
220
221 return { use, transaction };
222};
223
224export class FumaClient extends Context.Service<FumaClient, IFumaClient>()("executor/FumaClient") {
225 static layer = (db: FumaDb) => Layer.succeed(this)(makeFumaClient(db));

Callers 4

touchSubjectFunction · 0.90
createExecutorFunction · 0.90
makeAdminFunction · 0.90
FumaClientClass · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected