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.6 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 './plugins.js'; import { SmartdataDb } from './classes.db.js'; import { managed, setDefaultManagerForDoc } from './classes.collection.js'; import { SmartDataDbDoc, svDb, unI } from './classes.doc.js'; import { SmartdataDbWatcher } from './classes.watcher.js'; 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); export { 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kaXN0cmlidXRlZGNvb3JkaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5kaXN0cmlidXRlZGNvb3JkaW5hdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDM0UsT0FBTyxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHbkQsSUFBTSxnQkFBZ0IsR0FBdEIsTUFBTSxnQkFBaUIsU0FBUSxjQUFrRDtDQXNCdkYsQ0FBQTtBQW5CUTtJQUROLEdBQUcsRUFBRTs7NENBQ1k7QUFHWDtJQUROLElBQUksRUFBRTs7OENBZ0JMO0FBckJTLGdCQUFnQjtJQUQ1QixPQUFPLEVBQUU7R0FDRyxnQkFBZ0IsQ0FzQjVCOztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sK0JBQWdDLFNBQVEsT0FBTyxDQUFDLFVBQVUsQ0FBQyx1QkFBdUI7S0FDNUYsOEJBQThCO0lBTy9CLFlBQVksS0FBa0I7UUFDNUIsS0FBSyxFQUFFLENBQUM7UUFMRix3QkFBbUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQWlDN0QsT0FBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFFbkQsbUJBQWMsR0FBRyxLQUFLLElBQUksRUFBRTtZQUNsQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FB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