@defer/client
Advanced tools
Comparing version 1.3.0-alpha-20230413192620-463ad3e to 1.3.0-alpha-20230424103114-8c97893
@@ -10,2 +10,3 @@ "use strict"; | ||
schedule_for: request.scheduleFor, | ||
metadata: request.metadata, | ||
}); | ||
@@ -12,0 +13,0 @@ return client("POST", "/api/v1/enqueue", data); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.INTERNAL_VERSION = void 0; | ||
exports.INTERNAL_VERSION = 4; | ||
exports.INTERNAL_VERSION = 3; |
179
cjs/index.js
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.awaitResult = exports.delay = exports.defer = exports.getExecution = exports.deferEnabled = exports.configure = void 0; | ||
exports.awaitResult = exports.addMetadata = exports.delay = exports.defer = exports.getExecution = exports.deferEnabled = exports.configure = void 0; | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
@@ -75,11 +75,2 @@ const crypto_1 = require("crypto"); | ||
exports.getExecution = getExecution; | ||
function defaultRetryPolicy() { | ||
return { | ||
maxAttempts: 13, | ||
initialInterval: 30, | ||
randomizationFactor: 0.5, | ||
multiplier: 1.5, | ||
maxInterval: 60 * 10, | ||
}; | ||
} | ||
const defer = (fn, options) => { | ||
@@ -102,2 +93,3 @@ const ret = async (...args) => { | ||
scheduleFor: new Date(), | ||
metadata: {}, | ||
}); | ||
@@ -113,34 +105,9 @@ } | ||
ret.__fn = fn; | ||
let retryPolicy = defaultRetryPolicy(); | ||
switch (typeof options?.retry) { | ||
case "boolean": { | ||
if (options.retry) | ||
retryPolicy = defaultRetryPolicy(); | ||
break; | ||
} | ||
case "number": { | ||
retryPolicy.maxAttempts = options.retry; | ||
break; | ||
} | ||
case "object": { | ||
if (options.retry.maxAttempts) | ||
retryPolicy.maxAttempts = options.retry.maxAttempts; | ||
if (options.retry.initialInterval) | ||
retryPolicy.initialInterval = options.retry.initialInterval; | ||
if (options.retry.randomizationFactor) | ||
retryPolicy.randomizationFactor = options.retry.randomizationFactor; | ||
if (options.retry.multiplier) | ||
retryPolicy.multiplier = options.retry.multiplier; | ||
if (options.retry.maxInterval) | ||
retryPolicy.maxInterval = options.retry.maxInterval; | ||
break; | ||
} | ||
case "undefined": { | ||
retryPolicy.maxAttempts = 0; | ||
break; | ||
} | ||
default: { | ||
throw new Error("invalid retry options"); | ||
} | ||
let retryPolicy = 0; | ||
if (options?.retry === true) { | ||
retryPolicy = 12; | ||
} | ||
if (typeof options?.retry === "number") { | ||
retryPolicy = options.retry; | ||
} | ||
ret.__metadata = { version: constants_js_1.INTERNAL_VERSION, retry: retryPolicy }; | ||
@@ -168,38 +135,105 @@ return ret; | ||
*/ | ||
const delay = (deferFn, delay) => async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
catch (error) { | ||
const e = error; | ||
throw new errors_js_1.DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
const delay = (deferFn, delay) => { | ||
const delayedDeferFn = async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
else { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
catch (error) { | ||
const e = error; | ||
throw new errors_js_1.DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
return (0, client_js_1.enqueueExecution)(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor: scheduleFor, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = (0, crypto_1.randomUUID)(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
} | ||
else { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
} | ||
return (0, client_js_1.enqueueExecution)(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor, | ||
metadata: deferFn.__execOptions?.metadata || {}, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = (0, crypto_1.randomUUID)(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
}; | ||
delayedDeferFn.__fn = deferFn.__fn; | ||
delayedDeferFn.__metadata = deferFn.__metadata; | ||
delayedDeferFn.__execOptions = { | ||
...deferFn.__execOptions, | ||
delay, | ||
}; | ||
return delayedDeferFn; | ||
}; | ||
exports.delay = delay; | ||
/** | ||
* Add metadata to the the execution of a background function | ||
* @constructor | ||
* @param {Function} deferFn - A background function (`defer(...)` result) | ||
* @param {Metadata} metadata - The metadata (ex: `{ foo: "bar" }`) | ||
* @returns Function | ||
*/ | ||
const addMetadata = (deferFn, metadata) => { | ||
const newMetadata = { ...deferFn.__execOptions?.metadata, ...metadata }; | ||
const deferFnWithMetadata = async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
catch (error) { | ||
const e = error; | ||
throw new errors_js_1.DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
const delay = deferFn.__execOptions?.delay; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
} | ||
else if (delay) { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
} | ||
else { | ||
scheduleFor = new Date(); | ||
} | ||
return (0, client_js_1.enqueueExecution)(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor, | ||
metadata: newMetadata, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = (0, crypto_1.randomUUID)(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
}; | ||
deferFnWithMetadata.__fn = deferFn.__fn; | ||
deferFnWithMetadata.__metadata = deferFn.__metadata; | ||
deferFnWithMetadata.__execOptions = { | ||
...deferFn.__execOptions, | ||
metadata: newMetadata, | ||
}; | ||
return deferFnWithMetadata; | ||
}; | ||
exports.addMetadata = addMetadata; | ||
/** | ||
* Trigger the execution of a background function and waits for its result | ||
@@ -227,2 +261,3 @@ * @constructor | ||
scheduleFor: new Date(), | ||
metadata: {}, | ||
}); | ||
@@ -229,0 +264,0 @@ response = await (0, client_js_1.waitExecutionResult)(__httpClient, { id: id }); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = "1.3.0-alpha-20230413192620-463ad3e"; | ||
exports.default = "1.3.0-alpha-20230424103114-8c97893"; |
@@ -7,2 +7,3 @@ import { jitter } from "./jitter.js"; | ||
schedule_for: request.scheduleFor, | ||
metadata: request.metadata, | ||
}); | ||
@@ -9,0 +10,0 @@ return client("POST", "/api/v1/enqueue", data); |
@@ -1,1 +0,1 @@ | ||
export const INTERNAL_VERSION = 4; | ||
export const INTERNAL_VERSION = 3; |
176
esm/index.js
@@ -65,11 +65,2 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
} | ||
function defaultRetryPolicy() { | ||
return { | ||
maxAttempts: 13, | ||
initialInterval: 30, | ||
randomizationFactor: 0.5, | ||
multiplier: 1.5, | ||
maxInterval: 60 * 10, | ||
}; | ||
} | ||
export const defer = (fn, options) => { | ||
@@ -92,2 +83,3 @@ const ret = async (...args) => { | ||
scheduleFor: new Date(), | ||
metadata: {}, | ||
}); | ||
@@ -103,34 +95,9 @@ } | ||
ret.__fn = fn; | ||
let retryPolicy = defaultRetryPolicy(); | ||
switch (typeof options?.retry) { | ||
case "boolean": { | ||
if (options.retry) | ||
retryPolicy = defaultRetryPolicy(); | ||
break; | ||
} | ||
case "number": { | ||
retryPolicy.maxAttempts = options.retry; | ||
break; | ||
} | ||
case "object": { | ||
if (options.retry.maxAttempts) | ||
retryPolicy.maxAttempts = options.retry.maxAttempts; | ||
if (options.retry.initialInterval) | ||
retryPolicy.initialInterval = options.retry.initialInterval; | ||
if (options.retry.randomizationFactor) | ||
retryPolicy.randomizationFactor = options.retry.randomizationFactor; | ||
if (options.retry.multiplier) | ||
retryPolicy.multiplier = options.retry.multiplier; | ||
if (options.retry.maxInterval) | ||
retryPolicy.maxInterval = options.retry.maxInterval; | ||
break; | ||
} | ||
case "undefined": { | ||
retryPolicy.maxAttempts = 0; | ||
break; | ||
} | ||
default: { | ||
throw new Error("invalid retry options"); | ||
} | ||
let retryPolicy = 0; | ||
if (options?.retry === true) { | ||
retryPolicy = 12; | ||
} | ||
if (typeof options?.retry === "number") { | ||
retryPolicy = options.retry; | ||
} | ||
ret.__metadata = { version: INTERNAL_VERSION, retry: retryPolicy }; | ||
@@ -157,37 +124,103 @@ return ret; | ||
*/ | ||
export const delay = (deferFn, delay) => async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
catch (error) { | ||
const e = error; | ||
throw new DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
export const delay = (deferFn, delay) => { | ||
const delayedDeferFn = async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
else { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
catch (error) { | ||
const e = error; | ||
throw new DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
return enqueueExecution(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor: scheduleFor, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = randomUUID(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
} | ||
else { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
} | ||
return enqueueExecution(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor, | ||
metadata: deferFn.__execOptions?.metadata || {}, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = randomUUID(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
}; | ||
delayedDeferFn.__fn = deferFn.__fn; | ||
delayedDeferFn.__metadata = deferFn.__metadata; | ||
delayedDeferFn.__execOptions = { | ||
...deferFn.__execOptions, | ||
delay, | ||
}; | ||
return delayedDeferFn; | ||
}; | ||
/** | ||
* Add metadata to the the execution of a background function | ||
* @constructor | ||
* @param {Function} deferFn - A background function (`defer(...)` result) | ||
* @param {Metadata} metadata - The metadata (ex: `{ foo: "bar" }`) | ||
* @returns Function | ||
*/ | ||
export const addMetadata = (deferFn, metadata) => { | ||
const newMetadata = { ...deferFn.__execOptions?.metadata, ...metadata }; | ||
const deferFnWithMetadata = async (...args) => { | ||
const fn = deferFn.__fn; | ||
let functionArguments; | ||
try { | ||
functionArguments = JSON.parse(JSON.stringify(args)); | ||
} | ||
catch (error) { | ||
const e = error; | ||
throw new DeferError(`cannot serialize argument: ${e.message}`); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] invoked.`); | ||
if (__httpClient) { | ||
let scheduleFor; | ||
const delay = deferFn.__execOptions?.delay; | ||
if (delay instanceof Date) { | ||
scheduleFor = delay; | ||
} | ||
else if (delay) { | ||
const now = new Date(); | ||
scheduleFor = withDelay(now, delay); | ||
} | ||
else { | ||
scheduleFor = new Date(); | ||
} | ||
return enqueueExecution(__httpClient, { | ||
name: fn.name, | ||
arguments: functionArguments, | ||
scheduleFor, | ||
metadata: newMetadata, | ||
}); | ||
} | ||
if (__verbose) | ||
console.log(`[defer.run][${fn.name}] defer ignore, no token found.`); | ||
const id = randomUUID(); | ||
__database.set(id, { id: id, state: "running" }); | ||
execLocally(id, fn, functionArguments); | ||
return { id }; | ||
}; | ||
deferFnWithMetadata.__fn = deferFn.__fn; | ||
deferFnWithMetadata.__metadata = deferFn.__metadata; | ||
deferFnWithMetadata.__execOptions = { | ||
...deferFn.__execOptions, | ||
metadata: newMetadata, | ||
}; | ||
return deferFnWithMetadata; | ||
}; | ||
/** | ||
* Trigger the execution of a background function and waits for its result | ||
@@ -215,2 +248,3 @@ * @constructor | ||
scheduleFor: new Date(), | ||
metadata: {}, | ||
}); | ||
@@ -217,0 +251,0 @@ response = await waitExecutionResult(__httpClient, { id: id }); |
@@ -1,1 +0,1 @@ | ||
export default "1.3.0-alpha-20230413192620-463ad3e"; | ||
export default "1.3.0-alpha-20230424103114-8c97893"; |
{ | ||
"name": "@defer/client", | ||
"version": "1.3.0-alpha-20230413192620-463ad3e", | ||
"version": "1.3.0-alpha-20230424103114-8c97893", | ||
"description": "Zero infrastructure NodeJS background jobs", | ||
@@ -5,0 +5,0 @@ "dependencies": { |
import type { HTTPClient } from "./httpClient.js"; | ||
import type { Metadata } from "./index.js"; | ||
export interface EnqueueExecutionRequest { | ||
@@ -6,2 +7,3 @@ name: string; | ||
scheduleFor: Date; | ||
metadata: Metadata; | ||
} | ||
@@ -8,0 +10,0 @@ export interface EnqueueExecutionResponse { |
@@ -1,1 +0,1 @@ | ||
export declare const INTERNAL_VERSION = 4; | ||
export declare const INTERNAL_VERSION = 3; |
@@ -13,4 +13,8 @@ import { Units } from "parse-duration"; | ||
export declare type DelayString = `${string}${Units}`; | ||
export interface Metadata { | ||
[key: string]: string; | ||
} | ||
export interface DeferExecutionOptions { | ||
delay: DelayString | Date; | ||
delay?: DelayString | Date; | ||
metadata?: Metadata; | ||
} | ||
@@ -20,2 +24,3 @@ export declare type DeferRetFnParameters<F extends (...args: any | undefined) => Promise<any>> = [...first: Parameters<F>, options: DeferExecutionOptions]; | ||
declare type Range<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>; | ||
export declare type RetryNumber = Range<0, 13>; | ||
export declare type Concurrency = Range<0, 51>; | ||
@@ -26,3 +31,3 @@ export interface HasDeferMetadata { | ||
cron?: string; | ||
retry?: RetryPolicy; | ||
retry?: RetryNumber; | ||
concurrency?: Concurrency; | ||
@@ -34,2 +39,3 @@ }; | ||
__fn: F; | ||
__execOptions?: DeferExecutionOptions; | ||
} | ||
@@ -47,11 +53,4 @@ export interface DeferScheduledFn<F extends (...args: never) => Promise<any>> extends HasDeferMetadata { | ||
} | ||
export interface RetryPolicy { | ||
maxAttempts: number; | ||
initialInterval: number; | ||
randomizationFactor: number; | ||
multiplier: number; | ||
maxInterval: number; | ||
} | ||
export interface DeferOptions { | ||
retry?: boolean | number | Partial<RetryPolicy>; | ||
retry?: boolean | RetryNumber; | ||
concurrency?: Concurrency; | ||
@@ -61,3 +60,3 @@ } | ||
interface DeferDelay { | ||
<F extends (...args: any | undefined) => Promise<any>>(deferFn: DeferRetFn<F>, delay: DelayString | Date): (...args: Parameters<F>) => Promise<EnqueueExecutionResponse>; | ||
<F extends (...args: any | undefined) => Promise<any>>(deferFn: DeferRetFn<F>, delay: DelayString | Date): DeferRetFn<F>; | ||
} | ||
@@ -72,2 +71,13 @@ /** | ||
export declare const delay: DeferDelay; | ||
interface DeferAddMetadata { | ||
<F extends (...args: any | undefined) => Promise<any>>(deferFn: DeferRetFn<F>, metadata: Metadata): DeferRetFn<F>; | ||
} | ||
/** | ||
* Add metadata to the the execution of a background function | ||
* @constructor | ||
* @param {Function} deferFn - A background function (`defer(...)` result) | ||
* @param {Metadata} metadata - The metadata (ex: `{ foo: "bar" }`) | ||
* @returns Function | ||
*/ | ||
export declare const addMetadata: DeferAddMetadata; | ||
interface DeferAwaitResult { | ||
@@ -74,0 +84,0 @@ <F extends (...args: any | undefined) => Promise<any>>(deferFn: DeferRetFn<F>): DeferAwaitRetFn<F>; |
@@ -1,2 +0,2 @@ | ||
declare const _default: "1.3.0-alpha-20230413192620-463ad3e"; | ||
declare const _default: "1.3.0-alpha-20230424103114-8c97893"; | ||
export default _default; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
46454
1092