Skip to main content

Configuring Cache adapters

MemoryCacheAdapter​

To use the MemoryCacheAdapter you only need to create instance of it:

./samples/memory-cache-adapter.ts
import { MemoryCacheAdapter } from "eridu-tech/cache/memory-cache-adapter";

export const memoryCacheAdapter = new MemoryCacheAdapter();

You can also provide an Map that will be used for storing the data in memory:

./samples/memory-cache-adapter-with-map.ts
import { MemoryCacheAdapter } from "eridu-tech/cache/memory-cache-adapter";

const map = new Map<any, any>();
const memoryCacheAdapter = new MemoryCacheAdapter(map);
info

MemoryCacheAdapter lets you test your app without external dependencies like Redis, ideal for local development, unit tests, integration tests and fast E2E test for the backend application.

Settings​

To clean up expired cache keys, call removeAllExpired at a regular interval (for example, using a cron job):

./samples/memory-cache-remove-all-expired.ts
import { MemoryCacheAdapter } from "eridu-tech/cache/memory-cache-adapter";

const memoryCacheAdapter = new MemoryCacheAdapter();

// Remove all expired cache keys manually.
await memoryCacheAdapter.removeAllExpired();
info

Note removeAllExpired must be called to remove expired data that is no longer being used.

info

To remove the cache map and all stored cache data, use deInit method:

./samples/memory-cache-adapter-deinit.ts
import { memoryCacheAdapter } from "./memory-cache-adapter.js";

await memoryCacheAdapter.deInit();

MongodbCacheAdapter​

To use the MongodbCacheAdapter, you'll need to:

  1. Install the required dependency: mongodb package.
  2. Provide a string serializer (ISerde). We recommend using SuperJsonSerdeAdapter for this purpose.

Setup​

Connect to MongoDB and create the string serializer:

./samples/mongodb-cache-adapter-setup.ts
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import { MongoClient } from "mongodb";

export const serde = new Serde(new SuperJsonSerdeAdapter());

const client = await MongoClient.connect("YOUR_MONGODB_CONNECTION_STRING");
export const database = client.db("database");
info

The database setting also accepts a TransactionContext, which makes the adapter transaction aware. Adapters given the same instance share the same transaction when available.

Usage​

Create the adapter:

./samples/mongodb-cache-adapter-init.ts
import { MongodbCacheAdapter } from "eridu-tech/cache/mongodb-cache-adapter";
import { database, serde } from "./mongodb-cache-adapter-setup.js";

export const mongodbCacheAdapter = new MongodbCacheAdapter({
database,
serde,
});

// You need initialize the adapter once before using it.
// During the initialization the indexes will be created
await mongodbCacheAdapter.init();

You can change the collection name:

./samples/mongodb-cache-collection-name.ts
import { MongodbCacheAdapter } from "eridu-tech/cache/mongodb-cache-adapter";
import { database, serde } from "./mongodb-cache-adapter-setup.js";

const mongodbCacheAdapter = new MongodbCacheAdapter({
database,
serde,
// By default "cache" is used as collection name
collectionName: "my-cache",
});

await mongodbCacheAdapter.init();

You can change the collection settings:

./samples/mongodb-cache-collection-settings.ts
import { MongodbCacheAdapter } from "eridu-tech/cache/mongodb-cache-adapter";
import { database, serde } from "./mongodb-cache-adapter-setup.js";

const mongodbCacheAdapter = new MongodbCacheAdapter({
database,
serde,
// You configure additional collection settings
collectionSettings: {},
});

await mongodbCacheAdapter.init();
info

To remove the cache collection and all stored cache data, use deInit method:

./samples/mongodb-cache-adapter-deinit.ts
import { mongodbCacheAdapter } from "./mongodb-cache-adapter-init.js";

await mongodbCacheAdapter.deInit();

RedisCacheAdapter​

To use the RedisCacheAdapter, you'll need to:

  1. Install the required dependency: ioredis package.
  2. Provide a string serializer (ISerde). We recommend using SuperJsonSerdeAdapter for this purpose.

Setup​

Connect to Redis and create the string serializer:

./samples/redis-cache-adapter-setup.ts
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import { Redis } from "ioredis";

export const serde = new Serde(new SuperJsonSerdeAdapter());

export const database = new Redis("YOUR_REDIS_CONNECTION_STRING");

Usage​

Create the adapter:

./samples/redis-cache-adapter.ts
import { RedisCacheAdapter } from "eridu-tech/cache/redis-cache-adapter";
import { database, serde } from "./redis-cache-adapter-setup.js";

const redisCacheAdapter = new RedisCacheAdapter({
database,
serde,
});

KyselyCacheAdapter​

To use the KyselyCacheAdapter, you'll need to:

  1. Install the required dependency: kysely package.
  2. Provide a string serializer (ISerde). We recommend using SuperJsonSerdeAdapter for this purpose.
  3. Provide a TransactionContext that wraps the Kysely instance. The adapter is transaction aware: every cache operation runs through the context's current client, so cache reads and writes join the transaction of the current scope.

Setup​

Create the string serializer (ISerde) and a function that creates the TransactionContext by wrapping a Kysely instance in a KyselyTransactionAdapter:

./samples/kysely-cache-adapter-setup.ts
import { ExecutionContext } from "eridu-tech/execution-context";
import { AlsExecutionContextAdapter } from "eridu-tech/execution-context/als-execution-context-adapter";
import { contextToken } from "eridu-tech/execution-context/contracts";
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import { TransactionContext } from "eridu-tech/transaction-context";
import { KyselyTransactionAdapter } from "eridu-tech/transaction-context/kysely-transaction-adapter";
import type { ITransactionContext } from "eridu-tech/transaction-context/contracts";
import type { Kysely } from "kysely";

export const serde = new Serde(new SuperJsonSerdeAdapter());

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

// `KyselyCacheAdapter` is transaction aware: it runs every cache operation
// through the `current` client of this context, which is the transaction-scoped
// client while a transaction is active and the base client otherwise.
export function createTransactionContext(
kysely: Kysely<any>,
): ITransactionContext<Kysely<any>> {
return new TransactionContext<Kysely<any>>({
token: contextToken("kysely"),
adapter: new KyselyTransactionAdapter({
database: kysely,
}),
executionContext,
});
}
info

The transactionContext setting makes the adapter transaction aware. Adapters given the same instance share the same transaction when available.

Usage with Sqlite​

You will need to install better-sqlite3 package:

./samples/kysely-cache-sqlite.ts
import { KyselyCacheAdapter } from "eridu-tech/cache/kysely-cache-adapter";
import Sqlite from "better-sqlite3";
import { Kysely, SqliteDialect } from "kysely";
import {
createTransactionContext,
serde,
} from "./kysely-cache-adapter-setup.js";

const database = new Sqlite("DATABASE_NAME.db");
const kysely = new Kysely<any>({
dialect: new SqliteDialect({
database,
}),
});
const transactionContext = createTransactionContext(kysely);
export const kyselyCacheAdapter = new KyselyCacheAdapter({
transactionContext,
serde,
});

// You need initialize the adapter once before using it.
// During the initialization the schema will be created
await kyselyCacheAdapter.init();

Usage with Postgres​

You will need to install pg package:

./samples/kysely-cache-postgres.ts
import { KyselyCacheAdapter } from "eridu-tech/cache/kysely-cache-adapter";
import { Pool } from "pg";
import { Kysely, PostgresDialect } from "kysely";
import {
createTransactionContext,
serde,
} from "./kysely-cache-adapter-setup.js";

const database = new Pool({
database: "DATABASE_NAME",
host: "DATABASE_HOST",
user: "DATABASE_USER",
// DATABASE port
port: 5432,
password: "DATABASE_PASSWORD",
max: 10,
});
const kysely = new Kysely<any>({
dialect: new PostgresDialect({
pool: database,
}),
});
const transactionContext = createTransactionContext(kysely);
const kyselyCacheAdapter = new KyselyCacheAdapter({
transactionContext,
serde,
});

// You need initialize the adapter once before using it.
// During the initialization the schema will be created
await kyselyCacheAdapter.init();

Usage with Mysql​

You will need to install mysql2 package:

./samples/kysely-cache-mysql.ts
import { KyselyCacheAdapter } from "eridu-tech/cache/kysely-cache-adapter";
import { createPool } from "mysql2";
import { Kysely, MysqlDialect } from "kysely";
import {
createTransactionContext,
serde,
} from "./kysely-cache-adapter-setup.js";

const database = createPool({
host: "DATABASE_HOST",
// Database port
port: 3306,
database: "DATABASE_NAME",
user: "DATABASE_USER",
password: "DATABASE_PASSWORD",
connectionLimit: 10,
});
const kysely = new Kysely<any>({
dialect: new MysqlDialect({
pool: database,
}),
});
const transactionContext = createTransactionContext(kysely);
const kyselyCacheAdapter = new KyselyCacheAdapter({
transactionContext,
serde,
});

// You need initialize the adapter once before using it.
// During the initialization the schema will be created
await kyselyCacheAdapter.init();

Usage with Libsql​

You will need to install @libsql/kysely-libsql package:

./samples/kysely-cache-libsql.ts
import { KyselyCacheAdapter } from "eridu-tech/cache/kysely-cache-adapter";
import { LibsqlDialect } from "@libsql/kysely-libsql";
import { Kysely } from "kysely";
import {
createTransactionContext,
serde,
} from "./kysely-cache-adapter-setup.js";

const kysely = new Kysely<any>({
dialect: new LibsqlDialect({
url: "DATABASE_URL",
}),
});
const transactionContext = createTransactionContext(kysely);
const kyselyCacheAdapter = new KyselyCacheAdapter({
transactionContext,
serde,
});

// You need initialize the adapter once before using it.
// During the initialization the schema will be created
await kyselyCacheAdapter.init();

Usage with other databases​

Note kysely has support for multiple databases.

danger

Before choosing a database, ensure it supports transactions, because KyselyCacheAdapter runs all of its operations through the TransactionContext. Without transaction support, starting a transaction fails and you won't be able to use the put and increment methods.

Settings​

To clean up expired cache keys, call removeAllExpired at a regular interval (for example, using a cron job):

./samples/kysely-cache-remove-all-expired.ts
import { kyselyCacheAdapter } from "./kysely-cache-sqlite.js";

// Remove all expired cache keys manually.
await kyselyCacheAdapter.removeAllExpired();
info

To remove the cache table and all stored cache data, use deInit method:

./samples/kysely-cache-adapter-deinit.ts
import { kyselyCacheAdapter } from "./kysely-cache-sqlite.js";

await kyselyCacheAdapter.deInit();

NoOpCacheAdapter​

The NoOpCacheAdapter is a no-operation implementation, it performs no actions when called:

./samples/no-op-cache-adapter.ts
import { NoOpCacheAdapter } from "eridu-tech/cache/no-op-cache-adapter";

const noOpCacheAdapter = new NoOpCacheAdapter();
info

The NoOpCacheAdapter is useful when you want to mock out or disable your Cache class instance.

info

Note NoOpCacheAdapter returns always null when retrieving items and return true when adding, updating, and removing items.

Further information​

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