mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
updating ioc api, experimenting with cron
This commit is contained in:
@@ -14,8 +14,8 @@ import { PayloadType, PluginType } from './structures/enums';
|
||||
import assert from 'assert';
|
||||
import type { Payload } from '../types/utility';
|
||||
|
||||
export const ok = () => Ok.EMPTY;
|
||||
export const err = () => Err.EMPTY;
|
||||
export const ok = (val: unknown) => Ok(val);
|
||||
export const err = (val: string) => Err(val);
|
||||
|
||||
export function partitionPlugins<T,V>
|
||||
(arr: Array<{ type: PluginType }> = []): [T[], V[]] {
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { DependencyConfiguration } from '../../types/ioc';
|
||||
import { Container } from './container';
|
||||
import * as __Services from '../structures/default-services';
|
||||
import type { Logging } from '../interfaces';
|
||||
import { __add_container, __init_container, __swap_container, useContainerRaw } from './global';
|
||||
import { __add_container, __add_wiredcontainer, __init_container, __swap_container, useContainerRaw } from './global';
|
||||
import { EventEmitter } from 'node:events';
|
||||
|
||||
export function disposeAll(logger: Logging|undefined) {
|
||||
@@ -70,9 +70,9 @@ async function composeRoot(
|
||||
__add_container('@sern/logger', new __Services.DefaultLogging());
|
||||
}
|
||||
__add_container('@sern/errors', new __Services.DefaultErrorHandling());
|
||||
__add_container('@sern/cron', new __Services.Cron())
|
||||
__add_container('@sern/modules', new Map())
|
||||
__add_container('@sern/emitter', new EventEmitter())
|
||||
__add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps))
|
||||
//Build the container based on the callback provided by the user
|
||||
conf.build(container as Container);
|
||||
|
||||
@@ -84,26 +84,25 @@ async function composeRoot(
|
||||
}
|
||||
|
||||
export async function makeDependencies (conf: ValidDependencyConfig) {
|
||||
await __init_container({ autowire: false });
|
||||
|
||||
const container = await __init_container({ autowire: false });
|
||||
if(typeof conf === 'function') {
|
||||
const excluded: string[] = [];
|
||||
conf(dependencyBuilder(useContainerRaw(), excluded));
|
||||
conf(dependencyBuilder(container, excluded));
|
||||
//We only include logger if it does not exist
|
||||
const includeLogger =
|
||||
!excluded.includes('@sern/logger')
|
||||
&& !useContainerRaw().hasKey('@sern/logger');
|
||||
&& !container.hasKey('@sern/logger');
|
||||
|
||||
if(includeLogger) {
|
||||
__add_container('@sern/logger', new __Services.DefaultLogging);
|
||||
}
|
||||
__add_container('@sern/errors', new __Services.DefaultErrorHandling());
|
||||
__add_container('@sern/cron', new __Services.Cron())
|
||||
__add_container('@sern/modules', new Map())
|
||||
__add_container('@sern/emitter', new EventEmitter())
|
||||
await useContainerRaw().ready();
|
||||
__add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps))
|
||||
await container.ready();
|
||||
} else {
|
||||
await composeRoot(useContainerRaw(), conf);
|
||||
await composeRoot(container, conf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UnpackedDependencies } from '../../types/utility';
|
||||
import { Container } from './container';
|
||||
|
||||
//SIDE EFFECT: GLOBAL DI
|
||||
@@ -22,6 +23,14 @@ export function __add_container(key: string, v: object) {
|
||||
containerSubject.addSingleton(key, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything
|
||||
* then it will swap
|
||||
*/
|
||||
export function __add_wiredcontainer(key: string, depfn : (deps: UnpackedDependencies) => object) {
|
||||
//@ts-ignore
|
||||
containerSubject.addWiredSingleton(key, depfn);
|
||||
}
|
||||
/**
|
||||
* Initiates the global api.
|
||||
* Once this is finished, the Service api and the other global api is available
|
||||
@@ -32,6 +41,7 @@ export async function __init_container(options: {
|
||||
}) {
|
||||
containerSubject = new Container(options);
|
||||
await containerSubject.ready()
|
||||
return containerSubject
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { LogPayload, Logging, ErrorHandling } from '../interfaces';
|
||||
import { AnyFunction } from '../../types/utility';
|
||||
import type { LogPayload, Logging, ErrorHandling, Emitter } from '../interfaces';
|
||||
import { AnyFunction, UnpackedDependencies } from '../../types/utility';
|
||||
import cron from 'node-cron'
|
||||
import { EventEmitter } from 'events';
|
||||
import type { CronEventCommand, Module } from '../../types/core-modules'
|
||||
@@ -13,12 +13,8 @@ export class DefaultErrorHandling implements ErrorHandling {
|
||||
crash(err: Error): never {
|
||||
throw err;
|
||||
}
|
||||
keepAlive = 1;
|
||||
updateAlive(err: Error) {
|
||||
this.keepAlive--;
|
||||
if (this.keepAlive === 0) {
|
||||
throw err;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,41 +43,51 @@ export class DefaultLogging implements Logging {
|
||||
}
|
||||
}
|
||||
|
||||
export class Cron extends EventEmitter {
|
||||
export class Cron implements Emitter {
|
||||
tasks: string[] = [];
|
||||
modules: Map<string, CronEventCommand> = new Map();
|
||||
constructor(private deps: UnpackedDependencies) {}
|
||||
private sanityCheck(eventName: string | symbol) : asserts eventName is string {
|
||||
if(typeof eventName === 'symbol') throw Error("Cron cannot add symbol based listener")
|
||||
|
||||
}
|
||||
addCronModule(module: Module) {
|
||||
if(module.type !== EventType.Cron) {
|
||||
throw Error("Can only add cron modules");
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
if(!cron.validate(module.pattern)) {
|
||||
throw Error("Invalid cron expression while adding " + module.name)
|
||||
}
|
||||
(module as CronEventCommand)
|
||||
this.modules.set(module.name!, module as CronEventCommand);
|
||||
}
|
||||
addListener(eventName: string | symbol, listener: AnyFunction): this {
|
||||
this.sanityCheck(eventName);
|
||||
const retrievedModule = this.modules.get(eventName);
|
||||
if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found");
|
||||
cron.schedule(retrievedModule.pattern, listener, {
|
||||
name: retrievedModule?.name!
|
||||
});
|
||||
|
||||
cron.schedule(retrievedModule.pattern,
|
||||
(date) => listener({ date, deps: this.deps }),
|
||||
{ name: retrievedModule?.name!,
|
||||
runOnInit: retrievedModule.runOnInit,
|
||||
timezone: retrievedModule.timezone,
|
||||
});
|
||||
return this;
|
||||
}
|
||||
removeListener(eventName: string | symbol, listener: AnyFunction) {
|
||||
this.sanityCheck(eventName);
|
||||
const retrievedModule = this.modules.get(eventName);
|
||||
if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found");
|
||||
const task= cron.getTasks().get(retrievedModule.name!)
|
||||
const task = cron.getTasks().get(retrievedModule.name!)
|
||||
if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found");
|
||||
task.stop();
|
||||
super.removeListener(eventName, listener);
|
||||
return this;
|
||||
}
|
||||
emit(eventName: string | symbol, ...payload: any[]): boolean {
|
||||
this.sanityCheck(eventName);
|
||||
const retrievedModule = this.modules.get(eventName);
|
||||
if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found");
|
||||
const task= cron.getTasks().get(retrievedModule.name!)
|
||||
return task?.emit(eventName, payload) ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ export interface CronEventCommand extends Module {
|
||||
type: EventType.Cron;
|
||||
name?: string;
|
||||
pattern: string;
|
||||
runOnInit?: boolean
|
||||
timezone?: string;
|
||||
execute(...args: unknown[]): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user