Source: Scheduler.js

const EventEmitter = require('events').EventEmitter
, absMethod = 'Abstract method'
, { Observable, fromEvent } = require('rxjs')
, { filter } = require('rxjs/operators')
, { Schedule, ScheduleEvent, PreliminaryScheduleEvent } = require('./Schedule');


/**
 * Generic scheduler class that can emit events of type T. The purpose
 * of this scheduler is to notify when an event occurs or something should
 * be executed. It shall be used as base-class to other schedulers. It is
 * not to be used for executing jobs, use an appropriate queue for that.
 * Although providing Observables, Schedulers never error or complete.
 * 
 * @author Sebastian Hönel <development@hoenel.net>
 * @extends {EventEmitter}
 * @template T
 */
class Scheduler extends EventEmitter {
	/**
	 * @param {Symbol} schedulerSymbol The symbol that is used for emitting
	 * events from this Scheduler.
	 */
	constructor(schedulerSymbol) {
		super();
		/** @protected */
		this._symbol = schedulerSymbol;
		/**
		 * @protected
		 * @type {Observable<T>}
		 */
		this._observable = fromEvent(this, schedulerSymbol);
	};

	/**
	 * Returns the same Observable<T> to every subscriber. Note that this Observable
	 * never errors or drains. You will need to observe a particular Schedule to get
	 * its errors or completion. The Observable never errors or completes.
	 * 
	 * @template T Must be of type ScheduleEvent or more derived.
	 * @type {Observable<T|ScheduleEvent>}
	 */
	get observable() {
		return this._observable;
	};

	/**
	 * @template T Must be of type ScheduleEvent or more derived.
	 * @param {T|Schedule} schedule
	 * @returns {Observable<T|ScheduleEvent>} An Observable for the designated schedule.
	 */
	getObservableForSchedule(schedule) {
		return this.observable.pipe(filter(evt => evt.schedule === schedule));
	};

	/**
	 * Add a Schedule to this scheduler. This is an abstract method.
	 * 
	 * @param {Schedule} schedule
	 * @returns {this}
	 */
	addSchedule(schedule) {
		throw new Error(absMethod);
	};

	/**
	 * Remove a Schedule from this scheduler. This is an abstract method.
	 * 
	 * @param {Schedule} schedule
	 * @returns {this}
	 */
	removeSchedule(schedule) {
		throw new Error(absMethod);
	};

	/**
	 * Removes all Schedules from this scheduler. This is an abstract methdod.
	 * 
	 * @returns {Array<Schedule>} All Schedules as array.
	 */
	removeAllSchedules() {
		throw new Error(absMethod);
	};

	/**
	 * Returns a value indicating whether this Scheduler has the given
	 * Schedule. This is an abstract method.
	 * 
	 * @param {Schedule} schedule
	 * @returns {this}
	 */
	hasSchedule(schedule) {
		throw new Error(absMethod);
	};

	/**
	 * A generator that supposedly yields all schedules' preliminary events.
	 * 
	 * @template T Must be of type PreliminaryScheduleEvent or more derived.
	 * @param {Date} [after] Optional. Defaults to undefined.
	 * @param {Date} [before] Optional. Defaults to undefined.
	 * @returns {IterableIterator<PreliminaryScheduleEvent<T|Schedule, any>>}
	 */
	*preliminaryEvents(after, before) {
	};
};

module.exports = Object.freeze({
	Scheduler
});