UNPKG

zamza

Version:

Apache Kafka discovery, indexing, searches, storage, hooks and HTTP gateway

127 lines (126 loc) 3.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Debug = require("debug"); const debug = Debug("zamza:model:lockmodel"); const uuid = require("uuid"); const moment = require("moment"); class LockModel { constructor(zamza) { this.metrics = zamza.metrics; this.name = "lock"; this.model = null; this.instanceId = uuid.v4(); debug("Generated instance id", this.instanceId); } registerModel(mongoose, schemaConstructor) { const schemaDefinition = { name: String, instanceId: String, timestamp: Number, }; const schema = new schemaConstructor(schemaDefinition); // single index schema.index({ name: 1 }, { unique: true }); // compound index schema.index({ name: 1, timestamp: 1 }, { unique: false }); schema.index({ name: 1, timestamp: 1, instanceId: 1 }, { unique: false }); this.model = mongoose.model(this.name, schema); this.model.on("index", (error) => { if (error) { debug("Index creation failed", error.message); } else { debug("Index creation successfull."); } }); debug("Registered model with schema."); } async getLock(name, timeout = 25000) { let lock; try { lock = await this.model.findOneAndUpdate({ name, timestamp: { $lte: moment().valueOf() }, }, { instanceId: this.instanceId, timestamp: moment().valueOf() + timeout, }, { upsert: true, new: true, }); } catch (error) { // duplicated key, happens when multiple clients access resource at the same time if (error.code === 11000) { this.metrics.inc("mongo_lock_miss"); return false; } // other error throw error; } if (lock && lock.instanceId === this.instanceId) { this.metrics.inc("mongo_lock_hit"); return true; } else { this.metrics.inc("mongo_lock_miss"); return false; } } async extendLock(name, extendFor = 25000) { let lock; try { lock = await this.model.findOneAndUpdate({ name, timestamp: { $gte: moment().valueOf() }, instanceId: this.instanceId, }, { $inc: { timestamp: extendFor, }, }, { new: true, }); } catch (error) { // duplicated key, happens when multiple clients access resource at the same time if (error.code === 11000) { this.metrics.inc("mongo_lock_extend_miss"); return false; } // other error throw error; } if (lock) { this.metrics.inc("mongo_lock_extend_hit"); return true; } else { this.metrics.inc("mongo_lock_extend_miss"); return false; } } async removeLock(name) { const { n } = await this.model.deleteOne({ name, instanceId: this.instanceId, timestamp: { $gte: moment().valueOf() }, }); if (n === 1) { this.metrics.inc("mongo_lock_removed"); return true; } else { this.metrics.inc("mongo_lock_remove_failed"); return false; } } delete(name) { return this.model.deleteMany({ name }).exec(); } truncateCollection() { debug("Truncating collection"); return this.model.deleteMany({}).exec(); } } exports.LockModel = LockModel;