Prisma Transaction Rollback with Effects

Hello I've created a little code snippet to wrap an effect so that if it returns failure, it rollback the sql transaction using prisma :

class DatabaseTransactionService extends Context.Tag(
  "DatabaseTransactionService",
)<
  DatabaseTransactionService,
  {
    readonly tx: Omit<
      PrismaClient<Prisma.PrismaClientOptions, never>,
      "$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
    >;
  }
>() {}

const WithDatabaseTransaction = <T, Err>(
  toWrap: Effect.Effect<T, Err, DatabaseTransactionService>,
) => {
  return Effect.tryPromise({
    try: () =>
      db.$transaction(async (tx) => {
        const either = await Effect.runPromise(
          Effect.either(
            toWrap.pipe(
              Effect.provide(Layer.succeed(DatabaseTransactionService, { tx })),
            ),
          ),
        );

        return Either.match(either, {
          onLeft: (err) => {
            throw err;
          },
          onRight: (val) => val,
        });

      }),
    catch(error: unknown) {
      return error as Err;
    },
  });
};
`

And use like
    const effect = Effect.gen(function* () {
      const { tx } = yield* DatabaseTransactionService;

      yield* Effect.promise(() =>
        tx.entity.create({
          data: {
            id: "fK_1234,
            firstname: "should not be created",
            lastname: "should not be created",
          },
        }),
      );

      return yield* Effect.fail("Should rollback");
    });
Was this page helpful?