From 9e5cee7483cbbed523717451a23ddbc8b9188995 Mon Sep 17 00:00:00 2001 From: KaKa Date: Thu, 18 Apr 2024 11:59:01 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=A8=E2=80=8D=F0=9F=92=BB=20Add=20types?= =?UTF-8?q?=20declaration=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adapters/blank-example.d.ts | 87 ++++++++++++++ adapters/mongo.d.ts | 44 ++++++++ adapters/redis.d.ts | 42 +++++++ index.d.cts | 220 ++++++++++++++++++++++++++++++++++++ index.d.ts | 138 ++++++++++++++++++++++ 5 files changed, 531 insertions(+) create mode 100644 adapters/blank-example.d.ts create mode 100644 adapters/mongo.d.ts create mode 100644 adapters/redis.d.ts create mode 100644 index.d.cts create mode 100644 index.d.ts diff --git a/adapters/blank-example.d.ts b/adapters/blank-example.d.ts new file mode 100644 index 0000000..468c3b2 --- /dev/null +++ b/adapters/blank-example.d.ts @@ -0,0 +1,87 @@ +export interface BlankAdapterOption { + requiredOption: unknown; + prefix?: string; + resetOnInit?: boolean; +} + +export class BlankAdapter { + /** + * Create a BlankAdapter instance + * @param {object} opts - configuration object + * @param {object} opts.requiredOption - Required option description + * @param {string} [opts.prefix] - prefix for scope isolation; use when creating multiple JoSK instances within the single application + * @param {boolean} [opts.resetOnInit] - Make sure all old tasks is completed before setting a new one, see readme for more details + */ + constructor(opts?: BlankAdapterOption); + name: string; + prefix: string; + resetOnInit: boolean; + uniqueName: string; + lockKey: string; + requiredOption: unknown; + /** + * @async + * @memberOf BlankAdapter + * @name ping + * @description Check connection to Storage + * @returns {Promise} + */ + ping(): Promise; + /** + * @async + * @memberOf BlankAdapter + * Function called to acquire read/write lock on Storage adapter + * @name acquireLock + * @returns {Promise} + */ + acquireLock(): Promise; + /** + * @async + * @memberOf BlankAdapter + * Function called to release write/read lock from Storage adapter + * @name releaseLock + * @returns {Promise} + */ + releaseLock(): Promise; + /** + * @async + * @memberOf BlankAdapter + * Function called to remove task from the storage + * @name remove + * @param {string} uid - Unique ID of the task + * @returns {Promise} + */ + remove(uid: string): Promise; + /** + * @async + * @memberOf BlankAdapter + * Function called to add task to the storage + * @name add + * @param {string} uid - Unique ID of the task + * @param {boolean} isInterval - true/false defining loop or one-time task + * @param {number} delay - Delay in milliseconds + * @returns {Promise} + */ + add(uid: string, isInterval: boolean, delay: number): Promise; + /** + * @async + * @memberOf BlankAdapter + * Function called after executing tasks + * Used by "Interval" tasks to set the next execution + * @name update + * @param {object} task - Full object of the task from storage + * @param {Date} nextExecuteAt - Date defining time of the next execution for "Interval" tasks + * @returns {Promise} - `true` if updated, `false` id doesn't exist + */ + update(task: unknown, nextExecuteAt: Date): Promise; + /** + * @async + * @memberOf BlankAdapter + * Find and run tasks one by one + * @name iterate + * @param {Date} nextExecuteAt - Date defining time of the next execution for "zombie" tasks + * @param {function} cb - callback that must get called after looping over tasks + * @returns {void 0} + */ + iterate(nextExecuteAt: Date): void; +} diff --git a/adapters/mongo.d.ts b/adapters/mongo.d.ts new file mode 100644 index 0000000..6318c55 --- /dev/null +++ b/adapters/mongo.d.ts @@ -0,0 +1,44 @@ +import { Db } from 'mongodb'; + +export interface MongoAdapterOption { + db: Db; + lockCollectionName?: string; + prefix?: string; + resetOnInit?: boolean; +} + +/** Class representing MongoDB adapter for JoSk */ +export class MongoAdapter { + /** + * Create a MongoAdapter instance + * @param {JoSk} joskInstance - JoSk instance + * @param {object} opts - configuration object + * @param {Db} opts.db - Required, Mongo's `Db` instance, like one returned from `MongoClient#db()` method + * @param {string} [opts.lockCollectionName] - custom "lock" collection name + * @param {string} [opts.prefix] - prefix for scope isolation; use when creating multiple JoSK instances within the single application + * @param {boolean} [opts.resetOnInit] - Make sure all old tasks is completed before setting a new one, see readme for more details + */ + constructor(opts?: MongoAdapterOption); + name: string; + prefix: string; + lockCollectionName: string; + resetOnInit: boolean; + db: Db; + uniqueName: string; + collection: any; + lockCollection: any; + /** + * @async + * @memberOf MongoAdapter + * @name ping + * @description Check connection to MongoDB + * @returns {Promise} + */ + ping(): Promise; + acquireLock(): Promise; + releaseLock(): Promise; + remove(uid: string): Promise; + add(uid: string, isInterval: boolean, delay: number): Promise; + update(task: unknown, nextExecuteAt: Date): Promise; + iterate(nextExecuteAt: Date): Promise; +} diff --git a/adapters/redis.d.ts b/adapters/redis.d.ts new file mode 100644 index 0000000..fdebd58 --- /dev/null +++ b/adapters/redis.d.ts @@ -0,0 +1,42 @@ +import { RedisClientType as RedisClient } from 'redis'; + +export interface RedisAdapterOption { + client: RedisClient; + lockCollectionName?: string; + prefix?: string; + resetOnInit?: boolean; +} + +/** Class representing Redis adapter for JoSk */ +export class RedisAdapter { + /** + * Create a RedisAdapter instance + * @param {object} opts - configuration object + * @param {RedisClient} opts.client - Required, Redis'es `RedisClient` instance, like one returned from `await redis.createClient().connect()` method + * @param {string} [opts.lockCollectionName] - custom "lock" collection name + * @param {string} [opts.prefix] - prefix for scope isolation; use when creating multiple JoSK instances within the single application + * @param {boolean} [opts.resetOnInit] - Make sure all old tasks is completed before setting a new one, see readme for more details + */ + constructor(opts?: RedisAdapterOption); + name: string; + prefix: string; + uniqueName: string; + lockKey: string; + resetOnInit: boolean; + client: RedisClient; + /** + * @async + * @memberOf RedisAdapter + * @name ping + * @description Check connection to Redis + * @returns {Promise} + */ + ping(): Promise; + acquireLock(): Promise; + releaseLock(): Promise; + remove(uid: string): Promise; + add(uid: string, isInterval: boolean, delay: number): Promise; + update(task: unknown, nextExecuteAt: Date): Promise; + iterate(nextExecuteAt: Date): Promise; + __getTaskKey(uid: string): string; +} diff --git a/index.d.cts b/index.d.cts new file mode 100644 index 0000000..b940ebe --- /dev/null +++ b/index.d.cts @@ -0,0 +1,220 @@ +import { Db } from 'mongodb'; +import { RedisClientType as RedisClient } from 'redis'; +interface ErrorDetails { + description: string + error: Error + uid: null | string + task?: unknown +} + +interface ExecutedDetails { + uid: string + date: Date + delay: number + timestamp: number +} + +type OnErrorFunc = (title: string, details: ErrorDetails) => void +type OnExecutedFunc = (uid: string, details: ExecutedDetails) => void +type AsyncTaskFunc = () => Promise +type SyncTaskFunc = () => void +type SyncNextTaskFunc = (ready: (next?: Date) => void) => void + +export interface JoSkOption { + debug?: boolean; + onError?: OnErrorFunc; + autoClear?: boolean; + zombieTime?: number; + onExecuted?: OnExecutedFunc; + minRevolvingDelay?: number; + maxRevolvingDelay?: number; +} + +/** Class representing a JoSk task runner (cron). */ +export class JoSk { + /** + * Create a JoSk instance + * @param {object} opts - configuration object + * @param {boolean} [opts.debug] - Enable debug logging + * @param {function} [opts.onError] - Informational hook, called instead of throwing exceptions, see readme for more details + * @param {boolean} [opts.autoClear] - Remove obsolete tasks (any tasks which are not found in the instance memory during runtime, but exists in the database) + * @param {number} [opts.zombieTime] - Time in milliseconds, after this period of time - task will be interpreted as "zombie". This parameter allows to rescue task from "zombie mode" in case when: `ready()` wasn't called, exception during runtime was thrown, or caused by bad logic + * @param {function} [opts.onExecuted] - Informational hook, called when task is finished, see readme for more details + * @param {number} [opts.minRevolvingDelay] - Minimum revolving delay — the minimum delay between tasks executions in milliseconds + * @param {number} [opts.maxRevolvingDelay] - Maximum revolving delay — the maximum delay between tasks executions in milliseconds + */ + constructor(opts?: JoSkOption); + debug: boolean; + onError: false | OnErrorFunc; + autoClear: boolean; + zombieTime: number; + onExecuted: false | OnExecutedFunc; + isDestroyed: boolean; + minRevolvingDelay: number; + maxRevolvingDelay: number; + nextRevolutionTimeout: number; + tasks: {}; + _debug: (...args: any[]) => void; + adapter: any; + /** + * @async + * @memberOf JoSk + * @name ping + * @description Check package readiness and connection to Storage + * @returns {Promise} + * @throws {mix} + */ + ping(): Promise; + /** + * @async + * @memberOf JoSk + * Create recurring task (loop) + * @name setInterval + * @param {function} func - Function (task) to execute + * @param {number} delay - Delay between task execution in milliseconds + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setInterval(func: AsyncTaskFunc | SyncNextTaskFunc, delay: number, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Create delayed task + * @name setTimeout + * @param {function} func - Function (task) to execute + * @param {number} delay - Delay before task execution in milliseconds + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setTimeout(func: AsyncTaskFunc | SyncTaskFunc, delay: number, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Create task, which would get executed immediately and only once across multi-server setup + * @name setImmediate + * @param {function} func - Function (task) to execute + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setImmediate(func: AsyncTaskFunc | SyncTaskFunc, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Cancel (abort) current interval timer. + * Must be called in a separate event loop from `.setInterval()` + * @name clearInterval + * @param {string|Promise} timerId - Unique function (task) identification as a string, returned from `.setInterval()` + * @param {function} [callback] - optional callback + * @returns {Promise} - `true` if task cleared, `false` if task doesn't exist + */ + clearInterval(timerId: string | Promise): Promise; + /** + * @async + * @memberOf JoSk + * Cancel (abort) current timeout timer. + * Must be called in a separate event loop from `.setTimeout()` + * @name clearTimeout + * @param {string|Promise} timerId - Unique function (task) identification as a string, returned from `.setTimeout()` + * @param {function} [callback] - optional callback + * @returns {Promise} - `true` if task cleared, `false` if task doesn't exist + */ + clearTimeout(timerId: string | Promise): Promise; + /** + * @memberOf JoSk + * Destroy JoSk instance and stop all tasks + * @name destroy + * @returns {boolean} - `true` if instance successfully destroyed, `false` if instance already destroyed + */ + destroy(): boolean; + __checkState(): boolean; + __remove(timerId: string): Promise; + __add(uid: string, isInterval: boolean, delay: number): Promise; + __execute(task: unknown): Promise; + __iterate(): Promise; + __tick(): void; + __errorHandler(error: unknown, title: string, description: string, uid: string): void; +} + +export interface MongoAdapterOption { + db: Db; + lockCollectionName?: string; + prefix?: string; + resetOnInit?: boolean; +} + +/** Class representing MongoDB adapter for JoSk */ +export class MongoAdapter { + /** + * Create a MongoAdapter instance + * @param {JoSk} joskInstance - JoSk instance + * @param {object} opts - configuration object + * @param {Db} opts.db - Required, Mongo's `Db` instance, like one returned from `MongoClient#db()` method + * @param {string} [opts.lockCollectionName] - custom "lock" collection name + * @param {string} [opts.prefix] - prefix for scope isolation; use when creating multiple JoSK instances within the single application + * @param {boolean} [opts.resetOnInit] - Make sure all old tasks is completed before setting a new one, see readme for more details + */ + constructor(opts?: MongoAdapterOption); + name: string; + prefix: string; + lockCollectionName: string; + resetOnInit: boolean; + db: Db; + uniqueName: string; + collection: any; + lockCollection: any; + /** + * @async + * @memberOf MongoAdapter + * @name ping + * @description Check connection to MongoDB + * @returns {Promise} + */ + ping(): Promise; + acquireLock(): Promise; + releaseLock(): Promise; + remove(uid: string): Promise; + add(uid: string, isInterval: boolean, delay: number): Promise; + update(task: unknown, nextExecuteAt: Date): Promise; + iterate(nextExecuteAt: Date): Promise; +} + +export interface RedisAdapterOption { + client: RedisClient; + lockCollectionName?: string; + prefix?: string; + resetOnInit?: boolean; +} + +/** Class representing Redis adapter for JoSk */ +export class RedisAdapter { + /** + * Create a RedisAdapter instance + * @param {object} opts - configuration object + * @param {RedisClient} opts.client - Required, Redis'es `RedisClient` instance, like one returned from `await redis.createClient().connect()` method + * @param {string} [opts.lockCollectionName] - custom "lock" collection name + * @param {string} [opts.prefix] - prefix for scope isolation; use when creating multiple JoSK instances within the single application + * @param {boolean} [opts.resetOnInit] - Make sure all old tasks is completed before setting a new one, see readme for more details + */ + constructor(opts?: RedisAdapterOption); + name: string; + prefix: string; + uniqueName: string; + lockKey: string; + resetOnInit: boolean; + client: RedisClient; + /** + * @async + * @memberOf RedisAdapter + * @name ping + * @description Check connection to Redis + * @returns {Promise} + */ + ping(): Promise; + acquireLock(): Promise; + releaseLock(): Promise; + remove(uid: string): Promise; + add(uid: string, isInterval: boolean, delay: number): Promise; + update(task: unknown, nextExecuteAt: Date): Promise; + iterate(nextExecuteAt: Date): Promise; + __getTaskKey(uid: string): string; +} diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..b04d4fa --- /dev/null +++ b/index.d.ts @@ -0,0 +1,138 @@ +interface ErrorDetails { + description: string + error: Error + uid: null | string + task?: unknown +} + +interface ExecutedDetails { + uid: string + date: Date + delay: number + timestamp: number +} + +type OnErrorFunc = (title: string, details: ErrorDetails) => void +type OnExecutedFunc = (uid: string, details: ExecutedDetails) => void +type AsyncTaskFunc = () => Promise +type SyncTaskFunc = () => void +type SyncNextTaskFunc = (ready: (next?: Date) => void) => void + +export interface JoSkOption { + debug?: boolean; + onError?: OnErrorFunc; + autoClear?: boolean; + zombieTime?: number; + onExecuted?: OnExecutedFunc; + minRevolvingDelay?: number; + maxRevolvingDelay?: number; +} + +/** Class representing a JoSk task runner (cron). */ +export class JoSk { + /** + * Create a JoSk instance + * @param {object} opts - configuration object + * @param {boolean} [opts.debug] - Enable debug logging + * @param {function} [opts.onError] - Informational hook, called instead of throwing exceptions, see readme for more details + * @param {boolean} [opts.autoClear] - Remove obsolete tasks (any tasks which are not found in the instance memory during runtime, but exists in the database) + * @param {number} [opts.zombieTime] - Time in milliseconds, after this period of time - task will be interpreted as "zombie". This parameter allows to rescue task from "zombie mode" in case when: `ready()` wasn't called, exception during runtime was thrown, or caused by bad logic + * @param {function} [opts.onExecuted] - Informational hook, called when task is finished, see readme for more details + * @param {number} [opts.minRevolvingDelay] - Minimum revolving delay — the minimum delay between tasks executions in milliseconds + * @param {number} [opts.maxRevolvingDelay] - Maximum revolving delay — the maximum delay between tasks executions in milliseconds + */ + constructor(opts?: JoSkOption); + debug: boolean; + onError: false | OnErrorFunc; + autoClear: boolean; + zombieTime: number; + onExecuted: false | OnExecutedFunc; + isDestroyed: boolean; + minRevolvingDelay: number; + maxRevolvingDelay: number; + nextRevolutionTimeout: number; + tasks: {}; + _debug: (...args: any[]) => void; + adapter: any; + /** + * @async + * @memberOf JoSk + * @name ping + * @description Check package readiness and connection to Storage + * @returns {Promise} + * @throws {mix} + */ + ping(): Promise; + /** + * @async + * @memberOf JoSk + * Create recurring task (loop) + * @name setInterval + * @param {function} func - Function (task) to execute + * @param {number} delay - Delay between task execution in milliseconds + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setInterval(func: AsyncTaskFunc | SyncNextTaskFunc, delay: number, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Create delayed task + * @name setTimeout + * @param {function} func - Function (task) to execute + * @param {number} delay - Delay before task execution in milliseconds + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setTimeout(func: AsyncTaskFunc | SyncTaskFunc, delay: number, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Create task, which would get executed immediately and only once across multi-server setup + * @name setImmediate + * @param {function} func - Function (task) to execute + * @param {string} uid - Unique function (task) identification as a string + * @returns {Promise} - Timer ID + */ + setImmediate(func: AsyncTaskFunc | SyncTaskFunc, uid: string): Promise; + /** + * @async + * @memberOf JoSk + * Cancel (abort) current interval timer. + * Must be called in a separate event loop from `.setInterval()` + * @name clearInterval + * @param {string|Promise} timerId - Unique function (task) identification as a string, returned from `.setInterval()` + * @param {function} [callback] - optional callback + * @returns {Promise} - `true` if task cleared, `false` if task doesn't exist + */ + clearInterval(timerId: string | Promise): Promise; + /** + * @async + * @memberOf JoSk + * Cancel (abort) current timeout timer. + * Must be called in a separate event loop from `.setTimeout()` + * @name clearTimeout + * @param {string|Promise} timerId - Unique function (task) identification as a string, returned from `.setTimeout()` + * @param {function} [callback] - optional callback + * @returns {Promise} - `true` if task cleared, `false` if task doesn't exist + */ + clearTimeout(timerId: string | Promise): Promise; + /** + * @memberOf JoSk + * Destroy JoSk instance and stop all tasks + * @name destroy + * @returns {boolean} - `true` if instance successfully destroyed, `false` if instance already destroyed + */ + destroy(): boolean; + __checkState(): boolean; + __remove(timerId: any): Promise; + __add(uid: any, isInterval: any, delay: any): Promise; + __execute(task: any): Promise; + __iterate(): Promise; + __tick(): void; + __errorHandler(error: any, title: any, description: any, uid: any): void; +} +import { MongoAdapter } from './adapters/mongo.js' +import { RedisAdapter } from './adapters/redis.js' +export { MongoAdapter, RedisAdapter } +