smartdata/ts/classes.watcher.ts

74 lines
2.3 KiB
TypeScript
Raw Normal View History

import { SmartDataDbDoc } from './classes.doc.js';
import * as plugins from './plugins.js';
import { EventEmitter } from 'events';
2022-05-17 00:33:44 +02:00
/**
* a wrapper for the native mongodb cursor. Exposes better
*/
/**
* Wraps a MongoDB ChangeStream with RxJS and EventEmitter support.
*/
export class SmartdataDbWatcher<T = any> extends EventEmitter {
2022-05-17 00:33:44 +02:00
// STATIC
2022-05-17 21:26:17 +02:00
public readyDeferred = plugins.smartpromise.defer();
2022-05-17 00:33:44 +02:00
// INSTANCE
2022-05-17 23:54:26 +02:00
private changeStream: plugins.mongodb.ChangeStream<T>;
private rawSubject: plugins.smartrx.rxjs.Subject<T>;
/** Emits change documents (or arrays of documents if buffered) */
public changeSubject: any;
/**
* @param changeStreamArg native MongoDB ChangeStream
* @param smartdataDbDocArg document class for instance creation
* @param opts.bufferTimeMs optional milliseconds to buffer events via RxJS
*/
2022-11-01 18:23:57 +01:00
constructor(
changeStreamArg: plugins.mongodb.ChangeStream<T>,
smartdataDbDocArg: typeof SmartDataDbDoc,
opts?: { bufferTimeMs?: number },
2022-11-01 18:23:57 +01:00
) {
super();
this.rawSubject = new plugins.smartrx.rxjs.Subject<T>();
// Apply buffering if requested
if (opts && opts.bufferTimeMs) {
this.changeSubject = this.rawSubject.pipe(plugins.smartrx.rxjs.ops.bufferTime(opts.bufferTimeMs));
} else {
this.changeSubject = this.rawSubject;
}
2022-05-17 00:33:44 +02:00
this.changeStream = changeStreamArg;
2023-08-16 13:16:39 +02:00
this.changeStream.on('change', async (item: any) => {
let docInstance: T = null;
if (item.fullDocument) {
docInstance = smartdataDbDocArg.createInstanceFromMongoDbNativeDoc(
item.fullDocument
) as any as T;
2023-08-16 13:16:39 +02:00
}
// Notify subscribers
this.rawSubject.next(docInstance);
this.emit('change', docInstance);
2022-11-01 18:23:57 +01:00
});
// Signal readiness after one tick
2022-05-17 21:26:17 +02:00
plugins.smartdelay.delayFor(0).then(() => {
this.readyDeferred.resolve();
});
2022-05-17 00:33:44 +02:00
}
/**
* Close the change stream, complete the RxJS subject, and remove listeners.
*/
public async close(): Promise<void> {
// Close MongoDB ChangeStream
2022-05-17 00:33:44 +02:00
await this.changeStream.close();
// Complete the subject to teardown any buffering operators
this.rawSubject.complete();
// Remove all EventEmitter listeners
this.removeAllListeners();
}
/**
* Alias for close(), matching README usage
*/
public async stop(): Promise<void> {
return this.close();
2022-05-17 00:33:44 +02:00
}
}