Skip to content

Commit

Permalink
feat: add strict mode
Browse files Browse the repository at this point in the history
This is used to ensure that the implementation is following the recommended usage, such as listening to the proper events etc
  • Loading branch information
nytamin committed Aug 11, 2022
1 parent 394e703 commit 75c4d4d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/parent-process/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ export class ThreadedClassManagerClass {
public get debug (): boolean {
return this._internal.debug
}
/**
* Enable strict mode.
* When strict mode is enabled, checks will be done to ensure that best-practices are followed (such as listening to the proper events, etc).
* Warnings will be output to the console if strict mode is enabled.
*/
public set strict (v: boolean) {
this._internal.strict = v
}
public get strict (): boolean {
return this._internal.strict
}
/** Whether to register exit handlers. If not, then the application should ensure the threads are aborted on process exit */
public set handleExit (v: RegisterExitHandlers) {
this._internal.handleExit = v
Expand Down Expand Up @@ -158,6 +169,7 @@ export class ThreadedClassManagerClassInternal {
private _children: {[id: string]: Child} = {}
private _pinging: boolean = true // for testing only
public debug: boolean = false
public strict: boolean = false
/** Pseudo-unique id to identify the parent ThreadedClass (for debugging) */
private uniqueId: number = Date.now() % 10000
/** Two-dimensional map, which maps Proxy -> event -> listener functions */
Expand Down Expand Up @@ -574,6 +586,44 @@ export class ThreadedClassManagerClassInternal {
public getChildDescriptor (child: Child): string {
return `${child.id} (${Object.keys(child.instances).join(', ')})`
}
public checkInstance (instance: ChildInstance, errStack: Error) {
if (!this.strict) return

const getStack = () => {
// strip first 2 lines of the stack:
return `${errStack.stack}`.split('\n').slice(2).join('\n')

}

// Wait a little bit, to allow for the events to have been set up asynchronously in user-land:
setTimeout(() => {

// Ensure that error events are set up:
const events = this._proxyEventListeners.get(instance.proxy)
if (!events || events.arraySize('error') === 0) {
this.consoleLog(`Warning: No listener for the 'error' event was registered,
Solve this by adding
ThreadedClassManager.onEvent(instance, 'error', (error) => {})
${getStack()}`)
}

if (!instance.config.autoRestart) {
if (!events || events.arraySize('thread_closed') === 0) {
this.consoleLog(`Warning: autoRestart is disabled and no listener for the 'thread_closed' event was registered.
Solve this by either set {autoRestart: true} in threadedClass() options, or set up an event listener to handle a restart:
use ThreadedClassManager.onEvent(instance, 'thread_closed', () => {})
at ${getStack()}`)
}
} else {
if (!events || events.arraySize('restarted') === 0) {
this.consoleLog(`Warning: No listener for the 'restarted' event was registered.
It is recommended to set up an event listener for this, so you are aware of that an instance has been restarted:
use ThreadedClassManager.onEvent(instance, 'restarted', () => {})
${getStack()}`)
}
}
}, 1)
}
public onProxyEvent (proxy: ThreadedClass<any>, event: string, cb: Function): { stop: () => void } {
let events = this._proxyEventListeners.get(proxy)
if (!events) events = new ArrayMap()
Expand Down
4 changes: 4 additions & 0 deletions src/parent-process/threadedClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export function threadedClass<T, TCtor extends new (...args: any) => T> (
): Promise<ThreadedClass<T>> {
let exportName: string = orgExport

/** Used to extrack the original stack */
const errStack = new Error()

if (typeof orgModule as any !== 'string') throw new Error('threadedClass parameter orgModule must be a string!')
if (typeof orgExport as any !== 'string') throw new Error('threadedClass parameter orgExport must be a string!')

Expand Down Expand Up @@ -293,6 +296,7 @@ export function threadedClass<T, TCtor extends new (...args: any) => T> (
})
ThreadedClassManagerInternal.startMonitoringChild(instanceInChild)
resolve(proxy)
ThreadedClassManagerInternal.checkInstance(instanceInChild, errStack)
return true
}
})
Expand Down
3 changes: 3 additions & 0 deletions src/shared/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ export class ArrayMap<Key extends string, Value extends any> extends Map<Key, Va
}
return removedSomething
}
arraySize (key: Key): number {
return this.get(key)?.length ?? 0
}
/** The total number of elements in all of the arrays */
get totalSize (): number {
let total = 0
Expand Down

0 comments on commit 75c4d4d

Please sign in to comment.