Drivers

Drivers

Verrou supports multiple drivers to store the locks. No matter which driver you use, the API will always be the same.

Redis

You will need to install ioredis to use this driver.

The Redis driver can be used with many different providers:

  • Upstash
  • Vercel KV
  • DragonFly
  • Redis Cluster

The driver uses the ioredis library under the hood. So all possible ioredis configurations are assignable when creating the driver. Feel free to look at their documentation for more details.

import { Redis } from 'ioredis'
import { Verrou } from '@verrou/core'
import { redisStore } from '@verrou/core/drivers/redis'
const redis = new Redis({ host: 'localhost', port: 6379 })
const verrou = new Verrou({
default: 'redis',
drivers: {
redis: {
driver: redisStore({ connection: redis }),
},
},
})

Options

OptionDescriptionDefault
connectionAn instance of ioredisN/A

Implementation details

Note that the Redis store does not use the redlock algorithm. It uses a simple setnx as described in the Redis documentation. We may introduce a redlock strategy in the future.

Memory

The memory store is a simple in-memory store, so don't use it in a multi-server environment.

Use async-mutex under the hood.

import { Verrou } from '@verrou/core'
import { memoryStore } from '@verrou/core/drivers/memory'
const verrou = new Verrou({
default: 'memory',
drivers: {
memory: { driver: memoryStore() },
},
})

DynamoDB

DynamoDB is also supported by Verrou. You will need to install @aws-sdk/client-dynamodb to use this driver.

import { Verrou } from '@verrou/core'
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { dynamodbStore } from '@verrou/core/drivers/dynamodb'
const dynamoClient = new DynamoDBClient(/* ... */)
const verrou = new Verrou({
default: 'dynamo',
stores: {
dynamo: {
driver: dynamodbStore({
connection: dynamoClient,
// Name of the table where the locks will be stored
table: { name: 'locks' },
}),
},
},
})

The DynamoDB table will be automatically created if it does not exists. Otherwise, you can create it manually and specify the name of the table in the options.

Options

OptionDescriptionDefault
table.nameThe name of the table that will be used to store the cache.cache
connectionAn instance of DynamoDBClientN/A

Databases

We offer several drivers to use a database as the locks store. The database store should use an adapter for your database. Out of the box, we support Knex and Kysely to interact with the database. Knex and Kysely support many databases : SQLite, MySQL, PostgreSQL, MSSQL, Oracle, and more.

Note that you can easily create your own adapter by implementing the DatabaseAdapter interface if you are using another library not supported by Verrou. See the documentation for more details.

All Database drivers accept the following common options:

OptionDescriptionDefault
tableNameThe name of the table that will be used to store the locks.verrou
autoCreateTableIf the table should be automatically created if it does not exist.true

Knex

You must provide a Knex instance to use the Knex driver. Feel free to check the Knex documentation for more details about the configuration. Knex support many databases : SQLite, MySQL, PostgreSQL, MSSQL, Oracle, and more.

import knex from 'knex'
import { Verrou } from '@verrou/core'
import { knexStore } from '@verrou/core/drivers/knex'
const db = knex({ client: 'mysql2', connection: MYSQL_CREDENTIALS })
const verrou = new Verrou({
default: 'sqlite',
stores: {
sqlite: { driver: knexStore({ connection: db }) },
},
})

Kysely

You must provide a Kysely instance to use the Kysely driver. Feel free to check the Kysely documentation for more details about the configuration. Kysely support the following databases : SQLite, MySQL, PostgreSQL and MSSQL.

import { Kysely } from 'kysely'
import { Verrou } from '@verrou/core'
import { kyselyStore } from '@verrou/core/drivers/kysely'
const db = new Kysely<Database>({ dialect })
const verrou = new Verrou({
default: 'kysely',
stores: {
kysely: { driver: kyselyStore({ connection: db }) },
},
})

Implementation details

The database drivers use the same strategy as Laravel's Locks. The strategy is fairly simple : Just insert a row and rely on the database primary key constraint to prevent duplicates. If the insert fails, it means the lock already exists. This is briefly explained by Aaron Francis in this article.