@daiso-tech/core
Version:
The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.
156 lines • 4.75 kB
JavaScript
/**
* @module Lock
*/
import {} from "../../../../utilities/_module-exports.js";
import { UnexpectedLockError } from "../../../../lock/contracts/_module-exports.js";
import { ObjectId } from "mongodb";
/**
* To utilize the `MongodbLockAdapter`, you must install the `"mongodb"` package.
*
* Note in order to use `MongodbLockAdapter` correctly, ensure you use a single, consistent database across all server instances.
*
* IMPORT_PATH: `"@daiso-tech/core/lock/adapters"`
* @group Adapters
*/
export class MongodbLockAdapter {
database;
collection;
collectionName;
/**
* @example
* ```ts
* import { MongodbLockAdapter } from "@daiso-tech/core/lock/adapters";
* import { MongoClient } from "mongodb";
*
* const client = await MongoClient.connect("YOUR_MONGODB_CONNECTION_STRING");
* const database = client.db("database");
* const lockAdapter = new MongodbLockAdapter({
* database
* });
* // You need initialize the adapter once before using it.
* await lockAdapter.init()
* ```
*/
constructor({ collectionName = "lock", collectionSettings, database, }) {
this.collectionName = collectionName;
this.database = database;
this.collection = database.collection(collectionName, collectionSettings);
}
async removeExpiredKeys() {
await this.collection.deleteMany({
expiresAt: {
$lte: new Date(),
},
});
}
/**
* Creates all related indexes.
* Note the `init` method needs to be called before using the adapter.
*/
async init() {
await this.collection.createIndex({
key: 1,
}, {
unique: true,
});
await this.collection.createIndex("expiresAt", {
expireAfterSeconds: 0,
});
}
/**
* Removes the collection where the lock keys are stored and all it's related indexes.
* Note all lock data will be removed.
*/
async deInit() {
await this.collection.dropIndexes();
await this.database.dropCollection(this.collectionName);
}
async insert(key, owner, expiration) {
const insertResult = await this.collection.insertOne({
_id: new ObjectId(),
key,
owner,
expiresAt: expiration,
});
if (!insertResult.acknowledged) {
throw new UnexpectedLockError("Mongodb insertion was not acknowledged");
}
}
async update(key, owner, expiration) {
const updateResult = await this.collection.updateOne({
key,
$and: [
{
expiresAt: {
$ne: null,
},
},
{
expiresAt: {
$lte: new Date(),
},
},
],
}, {
$set: {
owner,
expiresAt: expiration,
},
});
if (!updateResult.acknowledged) {
throw new UnexpectedLockError("Mongodb update was not acknowledged");
}
return updateResult.modifiedCount; // > 0;
}
async remove(key, owner) {
if (owner === null) {
const deleteResult = await this.collection.deleteOne({
key,
});
if (!deleteResult.acknowledged) {
throw new UnexpectedLockError("Mongodb deletion was not acknowledged");
}
return;
}
const deleteResult = await this.collection.deleteOne({
key,
owner,
});
if (!deleteResult.acknowledged) {
throw new UnexpectedLockError("Mongodb deletion was not acknowledged");
}
}
async refresh(key, owner, expiration) {
const updateResult = await this.collection.updateOne({
key,
owner,
}, {
$set: {
expiresAt: expiration,
},
});
if (!updateResult.acknowledged) {
throw new UnexpectedLockError("Mongodb update was not acknowledged");
}
return updateResult.modifiedCount; // > 0;
}
async find(key) {
const document = await this.collection.findOne({
key: key,
}, {
projection: {
_id: 0,
owner: 1,
expiresAt: 1,
},
});
if (document === null) {
return null;
}
return {
owner: document.owner,
expiration: document.expiresAt,
};
}
}
//# sourceMappingURL=mongodb-lock-adapter.js.map