Skip to content

Commit

Permalink
updating ioc api, experimenting with cron
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoobes committed May 16, 2024
1 parent 44c072f commit d3227e5
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 26 deletions.
4 changes: 2 additions & 2 deletions src/core/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]] {
Expand Down
17 changes: 8 additions & 9 deletions src/core/ioc/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand All @@ -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);
}
}

10 changes: 10 additions & 0 deletions src/core/ioc/global.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UnpackedDependencies } from '../../types/utility';
import { Container } from './container';

//SIDE EFFECT: GLOBAL DI
Expand All @@ -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
Expand All @@ -32,6 +41,7 @@ export async function __init_container(options: {
}) {
containerSubject = new Container(options);
await containerSubject.ready()
return containerSubject
}

/**
Expand Down
36 changes: 21 additions & 15 deletions src/core/structures/default-services.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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;
}
}
2 changes: 2 additions & 0 deletions src/types/core-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

Expand Down

0 comments on commit d3227e5

Please sign in to comment.