@nivinjoseph/n-job
Version:
Job scheduling and execution
89 lines (67 loc) • 2.68 kB
text/typescript
import { given } from "@nivinjoseph/n-defensive";
import { ObjectDisposedException } from "@nivinjoseph/n-exception";
import { Logger } from "@nivinjoseph/n-log";
import { Duration } from "@nivinjoseph/n-util";
import { Job } from "./job.js";
// public
export abstract class TimedJob implements Job
{
private readonly _logger: Logger;
private readonly _intervalMilliseconds: number;
private _isStarted = false;
private _isDisposed = false;
private _timeout: any = null;
protected get logger(): Logger { return this._logger; }
protected get isDisposed(): boolean { return this._isDisposed; }
public constructor(logger: Logger, intervalDuration: Duration)
{
given(logger, "logger").ensureHasValue().ensureIsObject();
this._logger = logger;
given(intervalDuration, "intervalDuration").ensureHasValue().ensureIsObject()
.ensure(t => t.toMilliSeconds(true) >= 0 && t.toMilliSeconds(true) <= Duration.fromHours(12).toMilliSeconds(true), "should be between 0 ms and 12 hrs");
this._intervalMilliseconds = intervalDuration.toMilliSeconds(true);
}
public start(): void
{
if (this._isDisposed)
throw new ObjectDisposedException(this);
given(this, "this").ensure(t => !t._isStarted, "already started");
this._isStarted = true;
this._execute();
}
public async dispose(): Promise<void>
{
if (this._isDisposed)
return;
this._isDisposed = true;
if (this._timeout)
clearTimeout(this._timeout);
}
protected abstract run(): Promise<void>;
private _execute(): void
{
if (this._isDisposed)
return;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this._timeout = setTimeout(async (): Promise<void> =>
{
if (this._isDisposed)
return;
let isError = false;
await this._logger.logInfo(`Starting to run timed job ${(<Object>this).getTypeName()}.`);
try
{
await this.run();
}
catch (error: any)
{
await this._logger.logWarning(`Failed to run timed job ${(<Object>this).getTypeName()}.`);
await this._logger.logError(error);
isError = true;
}
if (!isError)
await this._logger.logInfo(`Finished running timed job ${(<Object>this).getTypeName()}.`);
this._execute();
}, this._intervalMilliseconds);
}
}