Skip to main content

RateLimiter resolver factory classes

RateLimiterFactoryResolver​

The RateLimiterFactoryResolver class provides a flexible way to configure and switch between different rate-limiter adapters at runtime.

Initial configuration​

To begin using the RateLimiterFactoryResolver, You will need to register all required adapters during initialization.

./samples/rate-limiter-factory-resolver-initial-config.ts
import { RateLimiterFactoryResolver } from "eridu-tech/rate-limiter";
import { MemoryRateLimiterStorageAdapter } from "eridu-tech/rate-limiter/memory-rate-limiter-storage-adapter";
import { DatabaseRateLimiterAdapter } from "eridu-tech/rate-limiter/database-rate-limiter-adapter";
import { RedisRateLimiterAdapter } from "eridu-tech/rate-limiter/redis-rate-limiter-adapter";
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import { Redis } from "ioredis";

const serde = new Serde(new SuperJsonSerdeAdapter());
export const rateLimiterFactoryResolver = new RateLimiterFactoryResolver({
serde,
adapters: {
memory: new DatabaseRateLimiterAdapter({
adapter: new MemoryRateLimiterStorageAdapter(),
}),
redis: new RedisRateLimiterAdapter({
database: new Redis("YOUR_REDIS_CONNECTION"),
}),
},
defaultAdapter: "memory",
});

Usage​

1. Using the default adapter​

./samples/rate-limiter-factory-resolver-default-adapter.ts
import { rateLimiterFactoryResolver } from "./rate-limiter-factory-resolver-initial-config.js";

// Will apply rate-limiter logic the default adapter which is MemoryRateLimiterStorageAdapter
await rateLimiterFactoryResolver
.use()
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
danger

Note that if you dont set a default adapter, an error will be thrown.

2. Specifying an adapter explicitly​

./samples/rate-limiter-factory-resolver-specific-adapter.ts
import { rateLimiterFactoryResolver } from "./rate-limiter-factory-resolver-initial-config.js";

// Will apply rate-limiter logic using the redis adapter
await rateLimiterFactoryResolver
.use("redis")
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
danger

Note that if you specify a non-existent adapter, an error will be thrown.

3. Overriding default settings​

./samples/rate-limiter-factory-resolver-override-settings.ts
import { rateLimiterFactoryResolver } from "./rate-limiter-factory-resolver-initial-config.js";

await rateLimiterFactoryResolver
.use("redis")
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
info

Note that the RateLimiterFactoryResolver is immutable, meaning any configuration override returns a new instance rather than modifying the existing one.

DatabaseRateLimiterFactoryResolver​

The DatabaseRateLimiterFactoryResolver class provides a flexible way to configure and switch between different rate-limiter-storage adapters at runtime.

Initial configuration​

To begin using the DatabaseRateLimiterFactoryResolver, You will need to register all required adapters during initialization.

./samples/database-rate-limiter-factory-resolver-initial-config.ts
import { DatabaseRateLimiterFactoryResolver } from "eridu-tech/rate-limiter";
import { MemoryRateLimiterStorageAdapter } from "eridu-tech/rate-limiter/memory-rate-limiter-storage-adapter";
import { KyselyRateLimiterStorageAdapter } from "eridu-tech/rate-limiter/kysely-rate-limiter-storage-adapter";
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import Sqlite from "better-sqlite3";
import { Kysely, SqliteDialect } from "kysely";
import { KyselyTransactionAdapter } from "eridu-tech/transaction-context/kysely-transaction-adapter";
import { ExecutionContext } from "eridu-tech/execution-context";
import { AlsExecutionContextAdapter } from "eridu-tech/execution-context/als-execution-context-adapter";
import { TransactionContext } from "eridu-tech/transaction-context";
import { contextToken } from "eridu-tech/execution-context/contracts";

const serde = new Serde(new SuperJsonSerdeAdapter());
const kysely = new Kysely<any>({
dialect: new SqliteDialect({
database: new Sqlite("local.db"),
}),
});
const kyselyTransactionAdapter = new KyselyTransactionAdapter({
database: kysely,
});
const executionContext = new ExecutionContext(new AlsExecutionContextAdapter());
const transactionContext = new TransactionContext<Kysely<any>>({
token: contextToken("kysely"),
executionContext,
adapter: kyselyTransactionAdapter,
});

export const rateLimiterFactoryResolver =
new DatabaseRateLimiterFactoryResolver({
serde,
adapters: {
memory: new MemoryRateLimiterStorageAdapter(),
sqlite: new KyselyRateLimiterStorageAdapter({
transactionContext,
serde,
}),
},
defaultAdapter: "memory",
});

Usage​

1. Using the default adapter​

./samples/database-rate-limiter-factory-resolver-default-adapter.ts
import { rateLimiterFactoryResolver } from "./database-rate-limiter-factory-resolver-initial-config.js";

// Will apply rate-limiter logic the default adapter which is MemoryRateLimiterStorageAdapter
await rateLimiterFactoryResolver
.use()
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
danger

Note that if you dont set a default adapter, an error will be thrown.

2. Specifying an adapter explicitly​

./samples/database-rate-limiter-factory-resolver-specific-adapter.ts
import { rateLimiterFactoryResolver } from "./database-rate-limiter-factory-resolver-initial-config.js";

// Will apply rate-limiter logic using the sqlite adapter
await rateLimiterFactoryResolver
.use("sqlite")
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
danger

Note that if you specify a non-existent adapter, an error will be thrown.

3. Overriding default settings​

./samples/database-rate-limiter-factory-resolver-override-settings.ts
import { SlidingWindowLimiter } from "eridu-tech/rate-limiter/policies";
import { constantBackoff } from "eridu-tech/backoff-policies";
import { rateLimiterFactoryResolver } from "./database-rate-limiter-factory-resolver-initial-config.js";

await rateLimiterFactoryResolver
.setBackoffPolicy(constantBackoff())
.setRateLimiterPolicy(new SlidingWindowLimiter())
.use("sqlite")
.create("a", {
limit: 10,
})
.runOrFail(async () => {
// ... code to apply rate-limiter logic
});
info

Note that the DatabaseRateLimiterFactoryResolver is immutable, meaning any configuration override returns a new instance rather than modifying the existing one.

Further information​

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