Compare commits

..

22 Commits

Author SHA1 Message Date
30d81581cf 5.0.41 2024-03-27 17:32:02 +01:00
5e9db12955 fix(core): update 2024-03-27 17:32:01 +01:00
ad2f422c86 5.0.40 2024-03-27 17:30:51 +01:00
17ce14bcb9 fix(core): update 2024-03-27 17:30:50 +01:00
32319e6e77 5.0.39 2024-03-27 17:30:15 +01:00
4cd284eaa9 fix(core): update 2024-03-27 17:30:14 +01:00
00ec2e57c2 5.0.38 2024-03-27 16:24:58 +01:00
765356ce3d fix(core): update 2024-03-27 16:24:57 +01:00
56b8581d2b 5.0.37 2024-03-26 13:22:34 +01:00
37a9df9086 fix(core): update 2024-03-26 13:22:33 +01:00
090fb668cd 5.0.36 2024-03-26 13:21:37 +01:00
a1c807261c fix(core): update 2024-03-26 13:21:36 +01:00
a2ccf15f69 5.0.35 2024-03-26 00:25:06 +01:00
84d48f1914 fix(core): update 2024-03-26 00:25:06 +01:00
1e258e5ffb 5.0.34 2024-03-22 18:36:35 +01:00
19d5f553b9 fix(core): update 2024-03-22 18:36:34 +01:00
7a257ea925 5.0.33 2023-08-21 12:39:49 +02:00
2fa1e89f34 fix(core): update 2023-08-21 12:39:48 +02:00
d6b3896dd3 5.0.32 2023-08-16 13:16:40 +02:00
49b11b17ce fix(core): update 2023-08-16 13:16:39 +02:00
4ac8a4c0cd 5.0.31 2023-08-16 12:08:28 +02:00
7f9983382a fix(core): update 2023-08-16 12:08:27 +02:00
10 changed files with 1680 additions and 1915 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@push.rocks/smartdata", "name": "@push.rocks/smartdata",
"version": "5.0.30", "version": "5.0.41",
"private": false, "private": false,
"description": "do more with data", "description": "do more with data",
"main": "dist_ts/index.js", "main": "dist_ts/index.js",
@ -22,27 +22,26 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartdata#README", "homepage": "https://gitlab.com/pushrocks/smartdata#README",
"dependencies": { "dependencies": {
"@push.rocks/lik": "^6.0.5", "@push.rocks/lik": "^6.0.14",
"@push.rocks/smartdelay": "^3.0.1", "@push.rocks/smartdelay": "^3.0.1",
"@push.rocks/smartlog": "^3.0.2", "@push.rocks/smartlog": "^3.0.2",
"@push.rocks/smartmongo": "^2.0.10", "@push.rocks/smartmongo": "^2.0.10",
"@push.rocks/smartpromise": "^4.0.2", "@push.rocks/smartpromise": "^4.0.2",
"@push.rocks/smartrx": "^3.0.6", "@push.rocks/smartrx": "^3.0.7",
"@push.rocks/smartstring": "^4.0.7", "@push.rocks/smartstring": "^4.0.15",
"@push.rocks/smarttime": "^4.0.5", "@push.rocks/smarttime": "^4.0.6",
"@push.rocks/smartunique": "^3.0.6", "@push.rocks/smartunique": "^3.0.8",
"@push.rocks/taskbuffer": "^3.1.5", "@push.rocks/taskbuffer": "^3.1.7",
"@tsclass/tsclass": "^4.0.42", "@tsclass/tsclass": "^4.0.52",
"mongodb": "^5.7.0" "mongodb": "^6.5.0"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.1.66", "@gitzone/tsbuild": "^2.1.66",
"@gitzone/tsrun": "^1.2.44", "@gitzone/tsrun": "^1.2.44",
"@gitzone/tstest": "^1.0.77", "@gitzone/tstest": "^1.0.77",
"@push.rocks/qenv": "^6.0.2", "@push.rocks/qenv": "^6.0.5",
"@push.rocks/tapbundle": "^5.0.15", "@push.rocks/tapbundle": "^5.0.22",
"@types/node": "^20.5.0", "@types/node": "^20.11.30"
"@types/shortid": "0.0.29"
}, },
"files": [ "files": [
"ts/**/*", "ts/**/*",

3469
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@ tap.test('SmartdataDistributedCoordinator should handle distributed task request
const mockTaskRequest: taskbuffer.distributedCoordination.IDistributedTaskRequest = { const mockTaskRequest: taskbuffer.distributedCoordination.IDistributedTaskRequest = {
submitterId: "mockSubmitter12345", // Some unique mock submitter ID submitterId: "mockSubmitter12345", // Some unique mock submitter ID
requestResponseId: 'uni879873462hjhfkjhsdf', // Some unique ID for the request-response
taskName: "SampleTask", taskName: "SampleTask",
taskVersion: "1.0.0", // Assuming it's a version string taskVersion: "1.0.0", // Assuming it's a version string
taskExecutionTime: Date.now(), taskExecutionTime: Date.now(),
@ -105,7 +106,7 @@ tap.test('should elect only one leader amongst multiple instances', async (tools
tap.test('should clean up', async () => { tap.test('should clean up', async () => {
await smartmongoInstance.stopAndDumpToDir(`.nogit/testdata/`); await smartmongoInstance.stopAndDumpToDir(`.nogit/testdata/`);
setTimeout(() => process.exit(0), 1000); setTimeout(() => process.exit(), 2000);
}) })
tap.start({ throwOnError: true }); tap.start({ throwOnError: true });

View File

@ -72,6 +72,11 @@ class Car extends smartdata.SmartDataDbDoc<Car, Car> {
} }
} }
tap.test('should create a new id', async () => {
const newid = await Car.getNewId();
console.log(newid);
})
tap.test('should save the car to the db', async (toolsArg) => { tap.test('should save the car to the db', async (toolsArg) => {
const myCar = new Car('red', 'Volvo'); const myCar = new Car('red', 'Volvo');
await myCar.save(); await myCar.save();

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartdata', name: '@push.rocks/smartdata',
version: '5.0.30', version: '5.0.41',
description: 'do more with data' description: 'do more with data'
} }

View File

@ -26,7 +26,8 @@ const collectionFactory = new CollectionFactory();
*/ */
export function Collection(dbArg: SmartdataDb | TDelayed<SmartdataDb>) { export function Collection(dbArg: SmartdataDb | TDelayed<SmartdataDb>) {
return function classDecorator<T extends { new (...args: any[]): {} }>(constructor: T) { return function classDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor { const decoratedClass = class extends constructor {
public static className = constructor.name;
public static get collection() { public static get collection() {
if (!(dbArg instanceof SmartdataDb)) { if (!(dbArg instanceof SmartdataDb)) {
dbArg = dbArg(); dbArg = dbArg();
@ -40,6 +41,7 @@ export function Collection(dbArg: SmartdataDb | TDelayed<SmartdataDb>) {
return collectionFactory.getCollection(constructor.name, dbArg); return collectionFactory.getCollection(constructor.name, dbArg);
} }
}; };
return decoratedClass;
}; };
} }
@ -56,9 +58,10 @@ export const setDefaultManagerForDoc = <T>(managerArg: IManager, dbDocArg: T): T
* This is a decorator that will tell the decorated class what dbTable to use * This is a decorator that will tell the decorated class what dbTable to use
* @param dbArg * @param dbArg
*/ */
export function Manager<TManager extends IManager>(managerArg?: TManager | TDelayed<TManager>) { export function managed<TManager extends IManager>(managerArg?: TManager | TDelayed<TManager>) {
return function classDecorator<T extends { new (...args: any[]): any }>(constructor: T) { return function classDecorator<T extends { new (...args: any[]): any }>(constructor: T) {
return class extends constructor { const decoratedClass = class extends constructor {
public static className = constructor.name;
public static get collection() { public static get collection() {
let dbArg: SmartdataDb; let dbArg: SmartdataDb;
if (!managerArg) { if (!managerArg) {
@ -106,9 +109,15 @@ export function Manager<TManager extends IManager>(managerArg?: TManager | TDela
return manager; return manager;
} }
}; };
return decoratedClass;
}; };
} }
/**
* @dpecrecated use @managed instead
*/
export const Manager = managed;
export class SmartdataCollection<T> { export class SmartdataCollection<T> {
/** /**
* the collection that is used * the collection that is used

View File

@ -1,9 +1,10 @@
import * as plugins from './smartdata.plugins.js'; import * as plugins from './smartdata.plugins.js';
import { SmartdataDb } from './smartdata.classes.db.js'; import { SmartdataDb } from './smartdata.classes.db.js';
import { Manager, setDefaultManagerForDoc } from './smartdata.classes.collection.js'; import { managed, setDefaultManagerForDoc } from './smartdata.classes.collection.js';
import { SmartDataDbDoc, svDb, unI } from './smartdata.classes.doc.js'; import { SmartDataDbDoc, svDb, unI } from './smartdata.classes.doc.js';
import { SmartdataDbWatcher } from './smartdata.classes.watcher.js';
@Manager() @managed()
export class DistributedClass extends SmartDataDbDoc<DistributedClass, DistributedClass> { export class DistributedClass extends SmartDataDbDoc<DistributedClass, DistributedClass> {
// INSTANCE // INSTANCE
@unI() @unI()
@ -39,6 +40,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
public db: SmartdataDb; public db: SmartdataDb;
private asyncExecutionStack = new plugins.lik.AsyncExecutionStack(); private asyncExecutionStack = new plugins.lik.AsyncExecutionStack();
public ownInstance: DistributedClass; public ownInstance: DistributedClass;
public distributedWatcher: SmartdataDbWatcher<DistributedClass>;
constructor(dbArg: SmartdataDb) { constructor(dbArg: SmartdataDb) {
super(); super();
@ -54,6 +56,9 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
public async stop() { public async stop() {
await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
if (this.distributedWatcher) {
await this.distributedWatcher.close();
}
if (this.ownInstance?.data.elected) { if (this.ownInstance?.data.elected) {
this.ownInstance.data.elected = false; this.ownInstance.data.elected = false;
} }
@ -208,12 +213,30 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
* the leading is implemented here * the leading is implemented here
*/ */
public async leadFunction() { public async leadFunction() {
const watcher = await DistributedClass.watch({}); this.distributedWatcher = await DistributedClass.watch({});
watcher.changeSubject.subscribe({
const currentTaskRequests: Array<{
taskName: string;
taskExecutionTime: number;
/**
* all instances that requested this task
*/
requestingDistibutedInstanceIds: string[];
responseTimeout: plugins.smartdelay.Timeout<any>;
}> = [];
this.distributedWatcher.changeSubject.subscribe({
next: async (distributedDoc) => { next: async (distributedDoc) => {
if (!distributedDoc) {
console.log(`registered deletion of instance...`);
return;
}
console.log(distributedDoc);
console.log(`registered change for ${distributedDoc.id}`);
distributedDoc; distributedDoc;
}, },
}); });
while (this.ownInstance.data.status !== 'stopped' && this.ownInstance.data.elected) { while (this.ownInstance.data.status !== 'stopped' && this.ownInstance.data.elected) {
const allInstances = await DistributedClass.getInstances({}); const allInstances = await DistributedClass.getInstances({});
for (const instance of allInstances) { for (const instance of allInstances) {
@ -239,8 +262,18 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
await this.ownInstance.save(); await this.ownInstance.save();
}); });
await plugins.smartdelay.delayFor(10000); await plugins.smartdelay.delayFor(10000);
const result = await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
return null; 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;
} }
public async updateDistributedTaskRequest( public async updateDistributedTaskRequest(

View File

@ -127,6 +127,13 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
} }
} }
/**
* get a unique id prefixed with the class name
*/
public static async getNewId<T = any>(this: plugins.tsclass.typeFest.Class<T>, lengthArg: number = 20) {
return `${(this as any).className}:${plugins.smartunique.shortId(lengthArg)}`;
}
/** /**
* get cursor * get cursor
* @returns * @returns

View File

@ -37,7 +37,16 @@ export class EasyStore<T> {
this.nameId = nameIdArg; this.nameId = nameIdArg;
} }
private async getEasyStore() { private easyStorePromise: Promise<InstanceType<typeof this.easyStoreClass>>;
private async getEasyStore(): Promise<InstanceType<typeof this.easyStoreClass>> {
if (this.easyStorePromise) {
return this.easyStorePromise;
};
// first run from here
const deferred = plugins.smartpromise.defer<InstanceType<typeof this.easyStoreClass>>();
this.easyStorePromise = deferred.promise;
let easyStore = await this.easyStoreClass.getInstance({ let easyStore = await this.easyStoreClass.getInstance({
nameId: this.nameId, nameId: this.nameId,
}); });
@ -48,7 +57,8 @@ export class EasyStore<T> {
easyStore.data = {}; easyStore.data = {};
await easyStore.save(); await easyStore.save();
} }
return easyStore; deferred.resolve(easyStore);
return this.easyStorePromise;
} }
/** /**
@ -70,7 +80,7 @@ export class EasyStore<T> {
/** /**
* writes a specific key to the keyValueStore * writes a specific key to the keyValueStore
*/ */
public async writeKey(keyArg: keyof T, valueArg: any) { public async writeKey<TKey extends keyof T>(keyArg: TKey, valueArg: T[TKey]) {
const easyStore = await this.getEasyStore(); const easyStore = await this.getEasyStore();
easyStore.data[keyArg] = valueArg; easyStore.data[keyArg] = valueArg;
await easyStore.save(); await easyStore.save();

View File

@ -17,9 +17,13 @@ export class SmartdataDbWatcher<T = any> {
smartdataDbDocArg: typeof SmartDataDbDoc smartdataDbDocArg: typeof SmartDataDbDoc
) { ) {
this.changeStream = changeStreamArg; this.changeStream = changeStreamArg;
this.changeStream.on('change', async (item: T) => { this.changeStream.on('change', async (item: any) => {
if (!item.fullDocument) {
this.changeSubject.next(null);
return;
}
this.changeSubject.next( this.changeSubject.next(
smartdataDbDocArg.createInstanceFromMongoDbNativeDoc(item) as any as T smartdataDbDocArg.createInstanceFromMongoDbNativeDoc(item.fullDocument) as any as T
); );
}); });
plugins.smartdelay.delayFor(0).then(() => { plugins.smartdelay.delayFor(0).then(() => {