Skip to main content

TransactionContextResolver

The TransactionContextResolver creates a transaction context for each configured adapter. Use it to run work with a default transaction adapter or select a specific adapter at runtime.

Initial configuration​

Set up the SQLite and MongoDB databases and their transaction adapters, then register them with the resolver and call init(). Initialization creates a transaction context for each configured adapter.

1. Set up the SQLite database​

./samples/sqlite-database.ts
import Sqlite from "better-sqlite3";
import { Kysely, SqliteDialect } from "kysely";

export const sqliteDatabase = new Kysely<any>({
dialect: new SqliteDialect({ database: new Sqlite(":memory:") }),
});

2. Create the SQLite transaction adapter​

./samples/sqlite-transaction-adapter.ts
import { KyselyTransactionAdapter } from "eridu-tech/transaction-context/kysely-transaction-adapter";
import { sqliteDatabase } from "./sqlite-database.js";

export const sqliteTransactionAdapter = new KyselyTransactionAdapter({
database: sqliteDatabase,
});

3. Set up the MongoDB database​

./samples/mongodb-database.ts
import { MongoClient } from "mongodb";

export const mongoClient = new MongoClient("mongodb://localhost:27017");
export const mongoDatabase = mongoClient.db("DATABASE_NAME");

4. Create the MongoDB transaction adapter​

./samples/mongodb-transaction-adapter.ts
import { MongodbTransactionAdapter } from "eridu-tech/transaction-context/mongodb-transaction-adapter";
import { mongoClient, mongoDatabase } from "./mongodb-database.js";

export const mongodbTransactionAdapter = new MongodbTransactionAdapter({
client: mongoClient,
database: mongoDatabase,
});

5. Configure the transaction context resolver​

./samples/transaction-context-resolver-initial-config.ts
import { ExecutionContext } from "eridu-tech/execution-context";
import { AlsExecutionContextAdapter } from "eridu-tech/execution-context/als-execution-context-adapter";
import { TransactionContextResolver } from "eridu-tech/transaction-context";
import { mongodbTransactionAdapter } from "./mongodb-transaction-adapter.js";
import { sqliteTransactionAdapter } from "./sqlite-transaction-adapter.js";

type Adapters = "mongodb" | "sqlite";

const executionContext = new ExecutionContext(new AlsExecutionContextAdapter());

export const transactionContextResolver =
new TransactionContextResolver<Adapters>({
adapters: {
mongodb: mongodbTransactionAdapter,
sqlite: sqliteTransactionAdapter,
},
defaultAdapter: "mongodb",
executionContext,
});

await transactionContextResolver.init();

Usage​

1. Using the default adapter​

./samples/transaction-context-resolver-default-adapter.ts
import { transactionContextResolver } from "./transaction-context-resolver-initial-config.js";

await transactionContextResolver.use().run(async () => {
// Perform work using the default (mongodb) adapter's transaction.
await transactionContextResolver.afterCommit(async () => {
console.log("Transaction committed");
});
});
danger

If no default adapter is configured and none is specified in use(), an error is thrown.

2. Specifying an adapter explicitly​

./samples/transaction-context-resolver-specific-adapter.ts
import { transactionContextResolver } from "./transaction-context-resolver-initial-config.js";

await transactionContextResolver.use("sqlite").run(async () => {
// Perform work using the SQLite adapter's transaction.
});
danger

If you specify an adapter that is not configured, an error is thrown. Call init() before use(); otherwise, no configured adapter is available yet.

Registering after-commit hooks​

The resolver's afterCommit() registers a callback with the configured transaction contexts. If none has an active transaction, the callback runs immediately by default. Otherwise, it is scheduled with each active transaction context and runs after that context commits. Use runIfNoTransaction: false to discard the callback when no transaction is active.

Further information​

For further information refer to eridu-tech/transaction-context API docs.