Modify GlobalRegistry to use async local storage to support multiple "global" containers
This commit is contained in:
parent
463076d182
commit
9204a02450
@ -1,18 +1,30 @@
|
|||||||
import {Collection} from '../collection/Collection'
|
import {Collection} from '../collection/Collection'
|
||||||
import {uuid4} from './data'
|
import {uuid4} from './data'
|
||||||
|
import {AsyncLocalStorage} from 'async_hooks'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type structure for a single item in the global registry.
|
* Type structure for a single item in the global registry.
|
||||||
*/
|
*/
|
||||||
export type GlobalRegistrant = { key: string | symbol, value: any }
|
export type GlobalRegistrant = { key: string | symbol, value: any }
|
||||||
|
|
||||||
|
export class AccessGlobalRegistryOutsideAsyncLifecycleError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super('Attempted to access global registry outside of an async context.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A convenient class to manage global variables.
|
* A convenient class to manage global variables.
|
||||||
*/
|
*/
|
||||||
export class GlobalRegistry extends Collection<GlobalRegistrant> {
|
export class GlobalRegistry {
|
||||||
constructor() {
|
protected readonly storage: AsyncLocalStorage<Collection<GlobalRegistrant>> = new AsyncLocalStorage<Collection<GlobalRegistrant>>()
|
||||||
super()
|
|
||||||
|
/** Run a closure with a global registry. */
|
||||||
|
public run<T>(closure: () => T): T {
|
||||||
|
return this.storage.run(new Collection<GlobalRegistrant>(), (): T => {
|
||||||
this.setGlobal('registry_uuid', uuid4())
|
this.setGlobal('registry_uuid', uuid4())
|
||||||
|
return closure()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,11 +33,11 @@ export class GlobalRegistry extends Collection<GlobalRegistrant> {
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
public setGlobal(key: string | symbol, value: unknown): this {
|
public setGlobal(key: string | symbol, value: unknown): this {
|
||||||
const existing = this.firstWhere('key', '=', key)
|
const existing = this.getCollection().firstWhere('key', '=', key)
|
||||||
if ( existing ) {
|
if ( existing ) {
|
||||||
existing.value = value
|
existing.value = value
|
||||||
} else {
|
} else {
|
||||||
this.push({
|
this.getCollection().push({
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
})
|
})
|
||||||
@ -39,7 +51,17 @@ export class GlobalRegistry extends Collection<GlobalRegistrant> {
|
|||||||
* @param key
|
* @param key
|
||||||
*/
|
*/
|
||||||
public getGlobal(key: string | symbol): any {
|
public getGlobal(key: string | symbol): any {
|
||||||
return this.firstWhere('key', '=', key)?.value
|
return this.getCollection().firstWhere('key', '=', key)?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the globals collection or throw an error if outside async context. */
|
||||||
|
protected getCollection(): Collection<GlobalRegistrant> {
|
||||||
|
const coll = this.storage.getStore()
|
||||||
|
if ( !coll ) {
|
||||||
|
throw new AccessGlobalRegistryOutsideAsyncLifecycleError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return coll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user