library-ts/node/users/scheduler/Scheduler.ts

141 lines
3.1 KiB
TypeScript
Raw Normal View History

2025-11-15 18:58:30 +00:00
import { MinPriorityQueue } from '@datastructures-js/priority-queue';
import { Arrays } from '../../../browser/tools/Arrays';
import { DateHelper } from '../../../browser/date/DateHelper';
import { DateMath } from '../../../browser/date/DateMath';
import { Task } from './Task';
import { iTaskScheduler } from './iTaskScheduler';
import { RJLog } from '../../log/RJLog';
export class Scheduler
{
// [ Tasks ]
_queue:Task[] = [];
_scheduledTasks = new Set<string>();
// [ Next Task ]
_taskTimerCallback:NodeJS.Timeout;
_nextTaskID:string;
// [ Settings ]
_maxScheduleDurationDays:number = 1;
// [ Schedulers ]
_taskSchedulers:iTaskScheduler[] = [];
get taskSchedulers(){ return this._taskSchedulers; }
constructor()
{
this._queue =[];
this._taskTimerCallback = null;
this._nextTaskID = null;
}
get maxDate():Date
{
return DateMath.fromNowAddDays( this._maxScheduleDurationDays );
}
async update()
{
let maxDate = this.maxDate;
let allTasks:Task[] = [];
for ( let ts of this._taskSchedulers )
{
let tasks = await ts.getTasksToSchedule( maxDate );
allTasks = allTasks.concat( tasks );
}
this.scheduleTasks( allTasks );
}
scheduleTasks( tasks:Task[] )
{
let maxDate = DateMath.fromNowAddDays( this._maxScheduleDurationDays );
tasks = tasks.filter( t => ! this._scheduledTasks.has( t.id ) && ! DateMath.isAfter( t.date, maxDate ) );
this._queue = this._queue.concat( tasks );
tasks.forEach( t => this._scheduledTasks.add( t.id ) );
this._queue.sort( ( a, b ) => { return a.date.getTime() - b.date.getTime() } );
let newNextTask = this._queue[ 0 ];
if ( this._nextTaskID && newNextTask.id != this._nextTaskID )
{
this._resetTimer();
}
this._updateTimer();
}
protected _resetTimer()
{
if ( this._taskTimerCallback )
{
clearTimeout( this._taskTimerCallback );
this._taskTimerCallback = null;
}
this._nextTaskID = null;
}
protected _updateTimer()
{
// RJLog.log( "_updateTimer:" );
if ( this._taskTimerCallback || this._queue.length == 0 )
{
// RJLog.log( "Nothing to do. Has Timer:", this._taskTimerCallback, "Queue Length:", this._queue.length );
return;
}
let task = this._queue[ 0 ];
this._nextTaskID = task.id;
let delay = Math.max( 0, task.date.getTime() - Date.now() );
RJLog.log( "delaying:", delay );
this._taskTimerCallback = setTimeout(
() =>
{
this._taskTimerCallback = null;
Arrays.remove( this._queue, task );
this._scheduledTasks.delete( task.id );
this._nextTaskID = null;
try
{
task.action();
}
catch( e )
{
RJLog.log( e );
}
this._updateTimer();
},
delay
);
}
cancelTask( id:string ): void
{
let index = this._queue.findIndex( e => e.id === id );
if ( index === -1 )
{
return;
}
Arrays.removeAt( this._queue, index );
this._resetTimer();
this._updateTimer();
}
}