UNPKG

@push.rocks/smartdata

Version:

An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.

260 lines 24.4 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import * as plugins from './smartdata.plugins.js'; import { SmartdataDb } from './smartdata.classes.db.js'; import { managed, setDefaultManagerForDoc } from './smartdata.classes.collection.js'; import { SmartDataDbDoc, svDb, unI } from './smartdata.classes.doc.js'; import { SmartdataDbWatcher } from './smartdata.classes.watcher.js'; export let DistributedClass = class DistributedClass extends SmartDataDbDoc { }; __decorate([ unI(), __metadata("design:type", String) ], DistributedClass.prototype, "id", void 0); __decorate([ svDb(), __metadata("design:type", Object) ], DistributedClass.prototype, "data", void 0); DistributedClass = __decorate([ managed() ], DistributedClass); /** * This file implements a distributed coordinator according to the @pushrocks/taskbuffer standard. * you should not set up this yourself. Instead, there is a factory on the SmartdataDb class * that will take care of setting this up. */ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distributedCoordination .AbstractDistributedCoordinator { constructor(dbArg) { super(); this.asyncExecutionStack = new plugins.lik.AsyncExecutionStack(); this.id = plugins.smartunique.uni('distributedInstance'); this.startHeartbeat = async () => { while (this.ownInstance.data.status !== 'stopped') { await this.sendHeartbeat(); await plugins.smartdelay.delayForRandom(5000, 10000); } }; this.db = dbArg; setDefaultManagerForDoc(this, DistributedClass); this.readyPromise = this.db.statusConnectedDeferred.promise; } // smartdata specific stuff async start() { await this.init(); } async stop() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (this.distributedWatcher) { await this.distributedWatcher.close(); } if (this.ownInstance?.data.elected) { this.ownInstance.data.elected = false; } if (this.ownInstance?.data.status === 'stopped') { console.log(`stopping a distributed instance that has not been started yet.`); } this.ownInstance.data.status = 'stopped'; await this.ownInstance.save(); console.log(`stopped ${this.ownInstance.id}`); }); } async sendHeartbeat() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (this.ownInstance.data.status === 'stopped') { console.log(`aborted sending heartbeat because status is stopped`); return; } await this.ownInstance.updateFromDb(); this.ownInstance.data.lastUpdated = Date.now(); await this.ownInstance.save(); console.log(`sent heartbeat for ${this.ownInstance.id}`); const allInstances = DistributedClass.getInstances({}); }); if (this.ownInstance.data.status === 'stopped') { console.log(`aborted sending heartbeat because status is stopped`); return; } const eligibleLeader = await this.getEligibleLeader(); // not awaiting here because we don't want to block the heartbeat this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (!eligibleLeader && this.ownInstance.data.status === 'settled') { this.checkAndMaybeLead(); } }); } async init() { await this.readyPromise; if (!this.ownInstance) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { this.ownInstance = new DistributedClass(); this.ownInstance.id = this.id; this.ownInstance.data = { elected: false, lastUpdated: Date.now(), status: 'initializing', taskRequests: [], taskRequestResults: [], }; await this.ownInstance.save(); }); } else { console.warn(`distributed instance already initialized`); } // lets enable the heartbeat this.startHeartbeat(); // lets do a leader check await this.checkAndMaybeLead(); return this.ownInstance; } async getEligibleLeader() { return this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const allInstances = await DistributedClass.getInstances({}); let leaders = allInstances.filter((instanceArg) => instanceArg.data.elected === true); const eligibleLeader = leaders.find((leader) => leader.data.lastUpdated >= Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 20 })); return eligibleLeader; }); } // --> leader election async checkAndMaybeLead() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { this.ownInstance.data.status = 'initializing'; this.ownInstance.save(); }); if (await this.getEligibleLeader()) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); console.log(`${this.ownInstance.id} settled as follower`); }); return; } else if ((await DistributedClass.getInstances({})).find((instanceArg) => { instanceArg.data.status === 'bidding' && instanceArg.data.biddingStartTime <= Date.now() - 4000 && instanceArg.data.biddingStartTime >= Date.now() - 30000; })) { console.log('too late to the bidding party... waiting for next round.'); return; } else { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'bidding'; this.ownInstance.data.biddingStartTime = Date.now(); this.ownInstance.data.biddingShortcode = plugins.smartunique.shortId(); await this.ownInstance.save(); console.log('bidding code stored.'); }); console.log(`bidding for leadership...`); await plugins.smartdelay.delayFor(plugins.smarttime.getMilliSecondsFromUnits({ seconds: 5 })); await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { let biddingInstances = await DistributedClass.getInstances({}); biddingInstances = biddingInstances.filter((instanceArg) => instanceArg.data.status === 'bidding' && instanceArg.data.lastUpdated >= Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 10 })); console.log(`found ${biddingInstances.length} bidding instances...`); this.ownInstance.data.elected = true; for (const biddingInstance of biddingInstances) { if (biddingInstance.data.biddingShortcode < this.ownInstance.data.biddingShortcode) { this.ownInstance.data.elected = false; } } await plugins.smartdelay.delayFor(5000); console.log(`settling with status elected = ${this.ownInstance.data.elected}`); this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); }); if (this.ownInstance.data.elected) { this.leadFunction(); } } } /** * when it has been determined * that this instance is leading * the leading is implemented here */ async leadFunction() { this.distributedWatcher = await DistributedClass.watch({}); const currentTaskRequests = []; this.distributedWatcher.changeSubject.subscribe({ next: async (distributedDoc) => { if (!distributedDoc) { console.log(`registered deletion of instance...`); return; } console.log(distributedDoc); console.log(`registered change for ${distributedDoc.id}`); distributedDoc; }, }); while (this.ownInstance.data.status !== 'stopped' && this.ownInstance.data.elected) { const allInstances = await DistributedClass.getInstances({}); for (const instance of allInstances) { if (instance.data.status === 'stopped') { await instance.delete(); } ; } await plugins.smartdelay.delayFor(10000); } } // abstract implemented methods async fireDistributedTaskRequest(taskRequestArg) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (!this.ownInstance) { console.error('instance need to be started first...'); return; } await this.ownInstance.updateFromDb(); this.ownInstance.data.taskRequests.push(taskRequestArg); await this.ownInstance.save(); }); await plugins.smartdelay.delayFor(10000); const result = await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); const taskRequestResult = this.ownInstance.data.taskRequestResults.find((resultItem) => { return resultItem.requestResponseId === taskRequestArg.requestResponseId; }); return taskRequestResult; }); if (!result) { console.warn('no result found for task request...'); return null; } return result; } async updateDistributedTaskRequest(infoBasisArg) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const existingInfoBasis = this.ownInstance.data.taskRequests.find((infoBasisItem) => { return (infoBasisItem.taskName === infoBasisArg.taskName && infoBasisItem.taskExecutionTime === infoBasisArg.taskExecutionTime); }); if (!existingInfoBasis) { console.warn('trying to update a non existing task request... aborting!'); return; } Object.assign(existingInfoBasis, infoBasisArg); await this.ownInstance.save(); plugins.smartdelay.delayFor(60000).then(() => { this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const indexToRemove = this.ownInstance.data.taskRequests.indexOf(existingInfoBasis); this.ownInstance.data.taskRequests.splice(indexToRemove, indexToRemove); await this.ownInstance.save(); }); }); }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGlzdHJpYnV0ZWRjb29yZGluYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0ZGF0YS5jbGFzc2VzLmRpc3RyaWJ1dGVkY29vcmRpbmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JGLE9BQU8sRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRzdELFdBQU0sZ0JBQWdCLEdBQXRCLE1BQU0sZ0JBQWlCLFNBQVEsY0FBa0Q7Q0FzQnZGLENBQUE7QUFuQlE7SUFETixHQUFHLEVBQUU7OzRDQUNZO0FBR1g7SUFETixJQUFJLEVBQUU7OzhDQWdCTDtBQXJCUyxnQkFBZ0I7SUFENUIsT0FBTyxFQUFFO0dBQ0csZ0JBQWdCLENBc0I1QjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sK0JBQWdDLFNBQVEsT0FBTyxDQUFDLFVBQVUsQ0FBQyx1QkFBdUI7S0FDNUYsOEJBQThCO0lBTy9CLFlBQVksS0FBa0I7UUFDNUIsS0FBSyxFQUFFLENBQUM7UUFMRix3QkFBbUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQWlDN0QsT0FBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFFbkQsbUJBQWMsR0FBRyxLQUFLLElBQUksRUFBRTtZQUNsQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1B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