Implementing a 'use' Pattern for MongoDB in Effect: Challenges and Considerations

I saw a post earlier about "lifting" the tryPromise out of regular usage using a "use" pattern in Effect for Prisma, and was wondering if anyone had any experience doing something similar with Mongo. Because Mongo needs to be setup with a db and a collection to access any of its query APIs (and, because you may want to handle multiple dbs and collections within one application) it's not quite as straight forward as the prisma example. For example, I'm practically guaranteed to have two repositories that pull from different collections, so I probably want to capture that in the maker of my repository, and reference it in my exposed APIs. What I have now is

export const makeMongoDatabaseProviderAcq = Effect.gen(function* () {
    const config = yield* ConfigService;
    // Acquire a releasable handle on the MongoClient, and specify cleanup behavior for the client
    // TODO: Write a test verifying that the cleanup is called when the scope is discarded
    const client = yield* Effect.acquireRelease(
        Effect.sync(() => new Mongo.MongoClient(config.get().mongoDBURI)).pipe(
            Effect.andThen((c) =>
                Effect.tryPromise({
                    try: () => c.connect(),
                    catch: (e) => new GenericMongoDbException(e),
                }),
            ),
        ),
        (c, _exit) => Effect.promise(() => c.close()),
    );

    const use = <T extends Document>(
        database: string,
        collection: string,
        options?: {
            dbOptions?: Mongo.DbOptions;
            collectionOptions: Mongo.CollectionOptions;
        },
    ) =>
        Effect.try({
            try: () =>
                client
                    .db(database, options?.dbOptions)
                    .collection<T>(collection, options?.collectionOptions),
            catch: (e) => new GenericMongoDbException(e),
        });

    return MongoDatabaseProvider.of({ use });
});
Was this page helpful?