@jovian/type-tools
Version:
TypeTools is a Typescript library for providing extensible tooling runtime validations and type helpers.
1,179 lines • 45.2 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.timerInterval = exports.TimerRegistrant = exports.Timer = exports.mainSharedTimer = exports.SharedTimer = exports.SharedTimerBlock = void 0;
var ix_config_1 = require("./ix.config");
var ix_entity_1 = require("./ix.entity");
var prom_util_1 = require("./util/prom.util");
var SharedTimerBlock = (function (_super) {
__extends(SharedTimerBlock, _super);
function SharedTimerBlock(init) {
var _this = _super.call(this, 'timerblock') || this;
_this.name = '';
_this.active = true;
_this.started = false;
_this.startTime = 0;
_this.maxBlocks = 10000;
_this.blockMs = 1;
_this.procCount = 1;
_this.procInterval = 1;
_this.lastRegister = 0;
_this.pendingCount = 0;
_this.notMsBlock = false;
_this.procs = [];
_this.immediates = [];
_this.timeblock = [];
_this.timeblockCursor = 0;
_this.maxMs = _this.maxBlocks * _this.blockMs;
_this.last = 0;
_this.totalHandledBlocksCount = 0;
if (init) {
Object.assign(_this, init);
}
_this.addOnDestroy(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
this.clearAllProcs();
return [2];
}); }); });
_this.maxMs = _this.maxBlocks * _this.blockMs;
_this.notMsBlock = (_this.blockMs > 1);
return _this;
}
Object.defineProperty(SharedTimerBlock.prototype, "maxSupportedMs", {
get: function () { return this.maxMs; },
enumerable: false,
configurable: true
});
Object.defineProperty(SharedTimerBlock.prototype, "totalHandledBlocks", {
get: function () { return this.totalHandledBlocksCount; },
enumerable: false,
configurable: true
});
SharedTimerBlock.prototype.clearAllProcs = function () {
this.checkingLogic(true);
for (var _i = 0, _a = this.procs; _i < _a.length; _i++) {
var proc = _a[_i];
clearInterval(proc);
}
};
SharedTimerBlock.prototype.setImmediate = function (reg) {
if (!reg.regStart) {
reg.regStart = Date.now();
}
if (!this.replacedBy) {
var now = Date.now();
this.lastRegister = now;
this.immediates.push({ reg: reg });
}
else {
this.getReplacement().setImmediate(reg);
}
};
SharedTimerBlock.prototype.getReplacement = function () {
var rpl = this.replacedBy;
while (rpl.replacedBy) {
rpl = rpl.replacedBy;
}
return rpl;
};
SharedTimerBlock.prototype.setImmediateOnce = function (reg) {
if (!reg.regStart) {
reg.regStart = Date.now();
}
if (!this.controller.started) {
this.controller.startBlocks();
}
if (!this.replacedBy) {
var now = Date.now();
this.lastRegister = now;
this.immediates.push({ reg: reg, once: true });
}
else {
var rpl = this.getReplacement();
rpl.immediates.push({ reg: reg, once: true });
}
};
SharedTimerBlock.prototype.setIntoBlock = function (reg) {
if (!this.replacedBy) {
var now = Date.now();
this.lastRegister = now;
++this.pendingCount;
if (this.notMsBlock) {
var adjusted = reg.blockInterval;
adjusted += this.timeblockCursor;
while (adjusted >= this.timeblock.length) {
adjusted -= this.timeblock.length;
}
var spot = this.timeblock[adjusted];
spot.push({ reg: reg });
reg.regSpot = spot;
reg.regLast = now;
}
else {
if (reg.nowait && reg.blockInterval > 0 && reg.regLast > 0) {
var overflow = now - reg.regLast - reg.blockInterval + reg.regOverflow;
var adjusted = reg.blockInterval - overflow;
if (adjusted < 0) {
adjusted = 0;
}
adjusted += this.timeblockCursor;
while (adjusted >= this.timeblock.length) {
adjusted -= this.timeblock.length;
}
var spot = this.timeblock[adjusted];
spot.push({ reg: reg });
reg.regSpot = spot;
reg.regOverflow = overflow;
}
else {
var adjusted = reg.blockInterval;
adjusted += this.timeblockCursor;
while (adjusted >= this.timeblock.length) {
adjusted -= this.timeblock.length;
}
var spot = this.timeblock[reg.blockInterval];
spot.push({ reg: reg });
reg.regSpot = spot;
reg.regLast = now;
}
}
reg.regLast = now;
reg.timerblock = this;
reg.controller = this.controller;
}
else {
this.getReplacement().setIntoBlock(reg);
}
};
SharedTimerBlock.prototype.register = function (reg) {
if (!reg.regStart) {
reg.regStart = Date.now();
}
if (!this.controller.started) {
this.controller.startBlocks();
}
if (reg.immediate || reg.ms < 1) {
this.controller.baseblock.setImmediate(reg);
}
else {
if (!this.replacedBy) {
this.setIntoBlock(reg);
}
else {
this.getReplacement().setIntoBlock(reg);
}
}
return reg;
};
SharedTimerBlock.prototype.start = function () {
var _this = this;
if (this.started) {
return;
}
this.started = true;
this.startTime = Date.now();
this.last = Date.now();
this.timeblock.length = this.maxBlocks;
for (var i = 0; i < this.maxBlocks; ++i) {
this.timeblock[i] = [];
}
this.checkingLogic = function (immediatesOnly) {
var now = Date.now();
var repeatersList = [];
for (var j = 0; j < _this.immediates.length; ++j) {
_this.handleRegistration(_this.immediates[j], now, repeatersList);
}
_this.immediates = [];
_this.handlerRepeatersIfAny(repeatersList);
if (immediatesOnly) {
return;
}
var delta = now - _this.last;
if (delta === 0) {
return;
}
var rawDelta = _this.notMsBlock ? delta / _this.blockMs : delta;
var blockCountToHandle = _this.notMsBlock ? Math.floor(delta / _this.blockMs) : delta;
if (blockCountToHandle === 0) {
return;
}
if (_this.notMsBlock) {
var timeOvercounted = Math.round((rawDelta - blockCountToHandle) * _this.blockMs);
_this.last = now - timeOvercounted;
}
else {
_this.last = now;
}
if (_this.timeblock.length === 0) {
_this.clearAllProcs();
return;
}
var blockCountToHandleSafe = Math.min(blockCountToHandle, _this.timeblock.length);
for (var j = 0; j < blockCountToHandleSafe; ++j) {
var index = _this.timeblockCursor + j;
while (index >= _this.timeblock.length) {
index -= _this.timeblock.length;
}
var ontheblock = _this.timeblock[index];
for (var _i = 0, ontheblock_1 = ontheblock; _i < ontheblock_1.length; _i++) {
var streg = ontheblock_1[_i];
--_this.pendingCount;
_this.handleRegistration(streg, now, repeatersList);
}
if (!_this.replacedBy) {
_this.timeblock[index] = [];
}
else if (_this.timeblock.length === 0) {
_this.clearAllProcs();
break;
}
}
_this.timeblockCursor += blockCountToHandleSafe;
while (_this.timeblockCursor >= _this.timeblock.length) {
_this.timeblockCursor -= _this.timeblock.length;
}
_this.handlerRepeatersIfAny(repeatersList);
_this.totalHandledBlocksCount += blockCountToHandleSafe;
};
for (var i = 0; i < this.procCount; ++i) {
this.procs.push(setInterval(this.checkingLogic, this.procInterval));
}
};
SharedTimerBlock.prototype.handlerRepeatersIfAny = function (repeatersList) {
if (repeatersList.length > 0) {
for (var _i = 0, repeatersList_1 = repeatersList; _i < repeatersList_1.length; _i++) {
var reg = repeatersList_1[_i];
reg.timerblock.setIntoBlock(reg);
}
repeatersList.length = 0;
}
};
SharedTimerBlock.prototype.handleRegistration = function (streg, now, repeatersList) {
var _this = this;
var _a, _b, _c;
var reg = streg.reg;
if (!reg.active) {
return;
}
reg.last = now;
if (!reg.paused && reg.skipCount === 0) {
(_a = reg.pre) === null || _a === void 0 ? void 0 : _a.call(reg, reg);
reg.callback(reg);
var ibhKeys = reg.intervalBehavior ? Object.keys(reg.intervalBehavior) : null;
if (ibhKeys && ibhKeys.length > 0) {
for (var _i = 0, ibhKeys_1 = ibhKeys; _i < ibhKeys_1.length; _i++) {
var ibhKey = ibhKeys_1[_i];
var bh = reg.intervalBehavior[ibhKey];
(_b = bh.callback) === null || _b === void 0 ? void 0 : _b.call(bh, bh, reg);
}
}
(_c = reg.post) === null || _c === void 0 ? void 0 : _c.call(reg, reg);
}
if (reg.skipCount > 0) {
--reg.skipCount;
}
if (reg.repeat) {
if (!reg.waitBeforeRepeat) {
repeatersList.push(reg);
}
else {
++this.pendingCount;
reg.waitBeforeRepeat.then(function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (reg.regSpot) {
--this.pendingCount;
}
if (reg.active && reg.repeat) {
reg.timerblock.setIntoBlock(reg);
}
return [2];
});
}); });
reg.waitBeforeRepeat = null;
}
}
};
return SharedTimerBlock;
}(ix_entity_1.Entity));
exports.SharedTimerBlock = SharedTimerBlock;
var SharedTimer = (function (_super) {
__extends(SharedTimer, _super);
function SharedTimer(rubric) {
var _this = _super.call(this, 'shared-timer') || this;
_this.name = '';
_this.timerblocks = [];
_this.started = false;
_this.name = rubric.name;
for (var _i = 0, _a = rubric.timerblocks; _i < _a.length; _i++) {
var timerBlockConfig = _a[_i];
var timerblock = new SharedTimerBlock(timerBlockConfig);
timerblock.controller = _this;
timerblock.lcManagedBy(_this);
_this.timerblocks.push(timerblock);
}
_this.baseblock = _this.timerblocks[0];
_this.addOnDestroy(function () {
if (_this.checkerId) {
clearInterval(_this.checkerId);
}
});
return _this;
}
SharedTimer.prototype.startBlocks = function () {
if (this.started) {
return this;
}
this.started = true;
for (var _i = 0, _a = this.timerblocks; _i < _a.length; _i++) {
var timerblock = _a[_i];
timerblock.start();
}
return this;
};
SharedTimer.prototype.endOnEmpty = function (checkingInterval) {
var _this = this;
if (checkingInterval === void 0) { checkingInterval = 200; }
if (this.checkerId) {
return this;
}
this.checkerId = setInterval(function () {
var totalPending = 0;
for (var _i = 0, _a = _this.timerblocks; _i < _a.length; _i++) {
var timerblock = _a[_i];
totalPending += timerblock.pendingCount;
}
if (totalPending === 0) {
_this.destroy();
}
}, checkingInterval);
return this;
};
SharedTimer.prototype.setPrecision = function (level) {
var procInterval = this.baseblock.procInterval;
switch (level) {
case 'max':
procInterval = 0;
break;
case 'ultra':
procInterval = 1;
break;
case 'super':
procInterval = 2;
break;
case 'faster':
procInterval = 5;
break;
case 'default':
procInterval = 10;
break;
case 'slower':
procInterval = 20;
break;
case 'lazy':
procInterval = 33;
break;
case 'superlazy':
procInterval = 50;
break;
case 'ultralazy':
procInterval = 100;
break;
default: return;
}
if (this.baseblock.procInterval !== procInterval) {
var oldBlock = this.baseblock;
var newBlock = new SharedTimerBlock({
name: oldBlock.name,
procInterval: procInterval,
procCount: oldBlock.procCount,
blockMs: oldBlock.blockMs,
maxBlocks: oldBlock.maxBlocks,
});
newBlock.controller = this;
newBlock.replacing = oldBlock;
newBlock.start();
oldBlock.replacedBy = newBlock;
this.baseblock = this.timerblocks[0] = newBlock;
}
return this;
};
return SharedTimer;
}(ix_entity_1.Entity));
exports.SharedTimer = SharedTimer;
exports.mainSharedTimer = new SharedTimer({
name: 'main', timerblocks: [
{ name: 'up to 10s', procInterval: 1, blockMs: 1, maxBlocks: 10000 },
{ name: 'up to 10m', procInterval: 200, blockMs: 100, maxBlocks: 6000 },
{ name: 'up to 10h', procInterval: 1000, blockMs: 10000, maxBlocks: 3600 },
{ name: 'up to 10d', procInterval: 1000, blockMs: 120000, maxBlocks: 7200 },
{ name: 'up to 3mo', procInterval: 1000, blockMs: 10800000, maxBlocks: 720 },
]
});
exports.mainSharedTimer.addOnDestroy(function () { ix_config_1.ixConfig.sleepFunctions.useSharedTimer = false; });
var Timer = (function (_super) {
__extends(Timer, _super);
function Timer(spec, ontick) {
var _this = _super.call(this, 'timer') || this;
_this.name = '';
_this.maxCount = 1;
_this.count = 0;
_this.paused = false;
_this.started = false;
_this.ended = false;
_this.finished = false;
_this.startTime = -1;
_this.endTime = -1;
_this.finishTime = -1;
_this.deltaEnd = -1;
_this.deltaFinish = -1;
_this.deltaEndFinish = -1;
_this.lastTick = -1;
_this.lastExec = -1;
_this.autoDestroy = false;
_this.result = null;
_this.error = null;
_this.reg = new TimerRegistrant({ source: _this });
_this.interval = 1000;
_this.cond = null;
_this.endResolves = [];
_this.finishResolves = [];
_this.lingeringLogic = {};
_this.endOnResult = false;
_this.executing = false;
if (!spec) {
spec = {};
}
if (typeof spec === 'number') {
spec = { ms: spec };
}
_this.options = spec;
_this.ontick = ontick ? ontick : function () { };
_this.interval = _this.fromUnit(_this.options);
if (_this.interval <= 0) {
_this.interval = 1000;
}
_this.name = _this.options.name ? _this.options.name : "(timer-".concat(_this.ixId, ")");
_this.addOnDestroy(function () { _this.end(); });
if (_this.options.count !== null && _this.options.count !== undefined) {
_this.maxCount = _this.options.count;
}
if (_this.options.forever) {
_this.maxCount = 0;
}
if (!_this.options.defer) {
var startNow = _this.options.immediately || _this.options.startNow;
_this.nudge(startNow ? { immediately: true } : null);
}
return _this;
}
Object.defineProperty(Timer.prototype, "ordinal", {
get: function () { return this.count + 1; },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "nth", {
get: function () { return this.count + 1; },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "elapsed", {
get: function () { return this.startTime < 0 ? 0 : Date.now() - this.startTime; },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "now", {
get: function () { return Date.now(); },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "endPromise", {
get: function () {
var _this = this;
return new Promise(function (resolve) { return _this.ended ? resolve(_this) : _this.endResolves.push(resolve); });
},
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "finishPromise", {
get: function () {
var _this = this;
return new Promise(function (resolve) { return _this.finished ? resolve(_this) : _this.finishResolves.push(resolve); });
},
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "beforetick$", {
get: function () { return this.ixRx('beforetick').obs(); },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "tick$", {
get: function () { return this.ixRx('tick').obs(); },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "aftertick$", {
get: function () { return this.ixRx('aftertick').obs(); },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "end$", {
get: function () { return this.ixRx('end').obs(); },
enumerable: false,
configurable: true
});
Object.defineProperty(Timer.prototype, "finish$", {
get: function () { return this.ixRx('finish').obs(); },
enumerable: false,
configurable: true
});
Timer.prototype.asPromise = function () { return this.finishPromise; };
Timer.prototype.runOnce = function () {
var _this = this;
if (this.ended) {
return null;
}
this.lastTick = Date.now();
if (this.startTime < 0) {
this.started = true;
this.startTime = Date.now();
}
if (this.paused) {
return null;
}
var isPromise = false;
var e = this.getSnapshot('');
var preCondPassed = (this.cond !== false && this.cond === null || this.cond === true || (this.cond && this.cond(this)));
if (preCondPassed && this.maxCount === 0 || this.count < this.maxCount) {
e.context = 'beforetick';
this.ixRx('beforetick').next(e);
try {
this.executing = true;
this.lastExec = Date.now();
e.context = 'main';
var res = this.ontick(e);
isPromise = (res && res.then);
if (isPromise) {
var iterId_1 = this.count + '';
var iterProm = this.execProm = res;
this.lingeringLogic[iterId_1] = iterProm;
iterProm.then(function (r) {
_this.executing = false;
_this.result = e.result = r;
_this.error = e.error = null;
if (_this.lingeringLogic[iterId_1]) {
delete _this.lingeringLogic[iterId_1];
}
e.context = 'aftertick-async';
_this.ixRx('aftertick').next(e);
if (_this.result && _this.endOnResult) {
_this.end();
}
_this.detectStopCond();
}).catch(function (error) {
_this.executing = false;
_this.result = e.result = null;
_this.error = e.error = error;
if (_this.lingeringLogic[iterId_1]) {
delete _this.lingeringLogic[iterId_1];
}
e.context = 'main-error-async';
_this.ixError(error, null, e);
e.context = 'aftertick-async';
_this.ixRx('aftertick').next(e);
_this.detectStopCond();
});
}
else {
this.executing = false;
this.result = e.result = res;
this.error = e.error = null;
}
}
catch (error) {
this.executing = false;
this.error = e.error = error;
}
if (!e.error) {
e.context = 'tick';
this.ixRx('tick').next(e);
}
else {
e.context = 'main-error';
this.ixError(e.error, null, e);
}
if (!isPromise) {
e.context = 'aftertick';
this.ixRx('aftertick').next(e);
}
this.count += 1;
if (this.result && this.endOnResult) {
this.end();
}
}
if (!isPromise) {
this.detectStopCond();
}
return isPromise ? this.execProm : null;
};
Timer.prototype.start = function () {
var _this = this;
var _a, _b;
if (this.started) {
return this;
}
this.started = true;
this.startTime = Date.now();
this.reg.nowait = !!this.options.nowait;
this.reg.update({
immediate: !!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.immediately) || ((_b = this.options) === null || _b === void 0 ? void 0 : _b.startNow)),
ms: this.interval,
repeat: true,
callback: function (reg) {
var res = _this.runOnce();
var needToWait = _this.executing && !_this.options.nowait;
if (res && res.then && needToWait) {
reg.waitBeforeRepeat = res;
}
}
});
this.reg.registerOn(exports.mainSharedTimer);
return this;
};
Timer.prototype.immediate = function () {
this.options.startNow = this.options.immediately = true;
return this;
};
Timer.prototype.pause = function () { this.paused = true; return this; };
Timer.prototype.resume = function () { this.paused = false; return this; };
Timer.prototype.nudge = function (options, beforenudge) {
var _this = this;
if (options === null || options === void 0 ? void 0 : options.immediately) {
this.options.immediately = true;
}
if (!this.started) {
(0, prom_util_1.promise)(function (resolve) { return setTimeout(resolve, 0); }).then(function () {
if (beforenudge) {
beforenudge();
}
_this.start();
});
}
return this;
};
Timer.prototype.watch = function (ms, onwatchtick) {
var _this = this;
if (!ms) {
ms = 1000;
}
if (onwatchtick) {
this.onwatchtick = onwatchtick;
}
this.startRegCondCheck(ms);
this.regWatch.callback = function () {
if (_this.onwatchtick) {
_this.onwatchtick(_this);
}
if (_this.cond && typeof _this.cond !== 'boolean') {
var passed = _this.cond(_this);
if (!passed) {
_this.end();
}
}
};
this.regWatch.registerOn(exports.mainSharedTimer);
this.regWatch.updateInterval(ms);
return this;
};
Timer.prototype.attend = function (level, onwatchtick) {
if (level === void 0) { level = 'default'; }
switch (level) {
case 'hyper': return this.watch(1, onwatchtick);
case 'super': return this.watch(10, onwatchtick);
case 'vigilant': return this.watch(100, onwatchtick);
case 'default': return this.watch(null, onwatchtick);
case 'lazy': return this.watch(1000, onwatchtick);
case 'lazier': return this.watch(10001, onwatchtick);
case 'superlazy': return this.watch(60000, onwatchtick);
case 'ultralazy': return this.watch(600000, onwatchtick);
default: return this;
}
};
Timer.prototype.stop = function () { return this.end(); };
Timer.prototype.end = function () {
var _this = this;
if (this.ended) {
return this;
}
if (this.startTime < 0) {
this.started = true;
this.startTime = Date.now();
}
this.ended = true;
this.endTime = Date.now();
this.deltaEnd = this.endTime - this.startTime;
if (this.reg) {
this.reg.invalidate();
}
if (this.regWatch) {
this.regWatch.invalidate();
}
this.ixRx('end').next(this);
for (var _i = 0, _a = this.endResolves; _i < _a.length; _i++) {
var resolve = _a[_i];
try {
resolve(this);
}
catch (error) {
var e = this.getSnapshot('end-error');
e.error = error;
this.ixError(error, 1, e);
}
}
var lingerIterationsKeys = Object.keys(this.lingeringLogic);
var finishingNow = (this.options.endSharp || lingerIterationsKeys.length === 0);
if (finishingNow) {
this.finishingWrapUp();
}
else {
var lingeringProms = lingerIterationsKeys.map(function (key) { return _this.lingeringLogic[key]; });
prom_util_1.PromUtil.allSettled(lingeringProms).then(function () { _this.finishingWrapUp(); });
}
return this;
};
Timer.prototype.forever = function () {
this.maxCount = 0;
this.nudge();
return this;
};
Timer.prototype.nowAndForever = function () {
this.maxCount = 0;
this.nudge({ immediately: true });
return this;
};
Timer.prototype.countUp = function (count) {
if (count <= 0 || !Number.isFinite(count)) {
throw new Error("'count' argument of value '".concat(count, " is not valid'"));
}
this.maxCount = count;
this.nudge();
return this;
};
Timer.prototype.countUpNow = function (count) {
if (count <= 0 || !Number.isFinite(count)) {
throw new Error("'count' argument of value '".concat(count, " is not valid'"));
}
this.maxCount = count;
this.nudge({ immediately: true });
return this;
};
Timer.prototype.repeatFor = function (count) {
if (count <= 0 || !Number.isFinite(count)) {
throw new Error("'count' argument of value '".concat(count, " is not valid'"));
}
return this.countUp(count + 1);
};
Timer.prototype.nowAndRepeatFor = function (count) {
if (count <= 0 || !Number.isFinite(count)) {
throw new Error("'count' argument of value '".concat(count, " is not valid'"));
}
return this.countUpNow(count + 1);
};
Timer.prototype.until = function (cond) {
var _this = this;
this.cond = typeof cond === 'boolean' ? !cond : function () { return !cond(_this); };
this.maxCount = 0;
this.nudge();
return this;
};
Timer.prototype.while = function (cond) {
this.maxCount = 0;
this.cond = cond;
this.nudge();
return this;
};
Timer.prototype.nowAndWhile = function (cond) {
this.maxCount = 0;
this.cond = cond;
this.nudge({ immediately: true });
return this;
};
Timer.prototype.untilTime = function (ts) {
this.while(function () { return Date.now() <= ts; });
return this;
};
Timer.prototype.untilTimeNow = function (ts) {
this.nowAndWhile(function () { return Date.now() <= ts; });
return this;
};
Timer.prototype.forDuration = function (t) {
var ms = this.fromUnit(t);
if (ms < 0) {
throw new Error("Given profile has no time units in [ms,s,m,h,d,w,mo,yr]");
}
var startTime = Date.now();
this.while(function () { return Date.now() - startTime <= ms; });
return this;
};
Timer.prototype.forDurationNow = function (t) {
var ms = this.fromUnit(t);
if (ms < 0) {
throw new Error("Given profile has no time units in [ms,s,m,h,d,w,mo,yr]");
}
var startTime = Date.now();
this.nowAndWhile(function () { return Date.now() - startTime <= ms; });
return this;
};
Timer.prototype.untilResult = function (type, options) {
var _this = this;
if (type === void 0) { type = { backoff: 'default' }; }
this.endOnResult = true;
this.retryArgsPrep(type, 'untilResult', options);
return this.while(function () { return _this.result === null || _this.result === undefined; });
};
Timer.prototype.untilResultNow = function (type, options) {
var _this = this;
if (type === void 0) { type = { backoff: 'default' }; }
this.endOnResult = true;
this.retryArgsPrep(type, 'untilResult', options);
return this.nowAndWhile(function () { return _this.result === null || _this.result === undefined; });
};
Timer.prototype.backOff = function (type, max, value, start) {
if (max === void 0) { max = 1200; }
if (value === void 0) { value = 1; }
if (start === void 0) { start = this.interval / 1000; }
this.retryArgsPrep({ backoff: type }, 'backOff', { backoff: { type: type, max: max, value: value, start: start } });
return this.forever();
};
Timer.prototype.backOffNow = function (type, max, value, start) {
if (max === void 0) { max = 1200; }
if (value === void 0) { value = 1; }
if (start === void 0) { start = this.interval / 1000; }
this.retryArgsPrep({ backoff: type }, 'backOff', { backoff: { type: type, max: max, value: value, start: start } });
return this.nowAndForever();
};
Timer.prototype.andOutputTime = function (nameProfile) {
var _this = this;
this.finishPromise.then(function () {
if (!nameProfile) {
nameProfile = _this.name;
}
console['log']("".concat(nameProfile, " took ").concat(_this.deltaFinish, " ms.\n") +
" \u2514\u2500 start: ".concat(_this.startTime, ", end: ").concat(_this.endTime, ", finish: ").concat(_this.finishTime, "\n") +
(_this.result ? " \u2514\u2500 result: ".concat(_this.result) : ""));
});
return this;
};
Timer.prototype.andDestroy = function () {
this.autoDestroy = true;
if (this.endTime > 0) {
this.destroy();
}
return this;
};
Timer.prototype.newBackOffOptions = function (type, max, value, start) {
if (max === void 0) { max = 1200; }
if (value === void 0) { value = 1; }
if (start === void 0) { start = this.interval / 1000; }
var profile;
if (type === 'expo') {
profile = { backoff: { type: type, start: start, value: value, max: max } };
}
else if (type === 'linear') {
profile = { backoff: { type: type, start: start, value: value, max: max } };
}
return profile;
};
Timer.prototype.updateInterval = function (newIntervalMs) {
this.reg.updateInterval(newIntervalMs);
};
Timer.prototype.newBackOffIntervalBehavior = function (options) {
var _this = this;
return {
data: {},
begun: false,
callback: function (bh) {
var boConf = options.backoff;
if (boConf) {
if (!bh.begun) {
_this.interval = boConf.start * 1000;
bh.begun = true;
}
else {
var maxMs = boConf.max * 1000;
if (boConf.type === 'expo') {
if (_this.interval < maxMs) {
_this.interval *= (Math.E * boConf.value);
if (_this.interval > maxMs) {
_this.interval = maxMs;
}
_this.updateInterval(_this.interval);
}
}
else if (boConf.type === 'linear') {
if (_this.interval < maxMs) {
_this.interval += boConf.value * 1000;
if (_this.interval > maxMs) {
_this.interval = maxMs;
}
_this.updateInterval(_this.interval);
}
}
}
}
}
};
};
Timer.prototype.startRegCondCheck = function (ms) {
if (!this.regWatch) {
this.regWatch = new TimerRegistrant({
source: this,
ms: ms,
repeat: true, immediate: true
});
}
};
Timer.prototype.getSnapshot = function (context) {
var now = Date.now();
var e = {
now: now,
result: this.result,
context: context,
maxCount: this.maxCount,
count: this.count,
nth: this.count + 1,
ordinal: this.count + 1,
elapsed: now - this.startTime,
timer: this,
};
return e;
};
Timer.prototype.detectStopCond = function () {
var shouldStop = (this.cond === false || (this.cond && typeof this.cond !== 'boolean' && !this.cond(this)));
if (shouldStop || (this.maxCount !== 0 && this.count === this.maxCount)) {
this.end();
}
};
Timer.prototype.fromUnit = function (units) {
var ms = -1;
for (var _i = 0, _a = Object.keys(units); _i < _a.length; _i++) {
var unit = _a[_i];
if (unit.length > 2 || unit === 't') {
continue;
}
var n = units[unit];
if (!n || !Number.isFinite(n)) {
continue;
}
if (unit === 'ms') {
ms = n;
break;
}
if (unit === 's') {
ms = n * 1000;
break;
}
if (unit === 'm') {
ms = n * 60000;
break;
}
if (unit === 'h') {
ms = n * 3600000;
break;
}
if (unit === 'd') {
ms = n * 86400000;
break;
}
if (unit === 'w') {
ms = n * 604800000;
break;
}
if (unit === 'mo') {
ms = n * 2592000000;
break;
}
if (unit === 'yr') {
ms = n * 31536000000;
break;
}
}
return ms;
};
Timer.prototype.retryArgsPrep = function (type, context, options) {
if (type === void 0) { type = { backoff: 'default' }; }
if (context === void 0) { context = 'default'; }
var bhKey = "".concat(this.ixId, "-").concat(context);
if (type.backoff === 'default') {
if (this.reg.intervalBehavior[bhKey]) {
delete this.reg.intervalBehavior[bhKey];
}
}
else {
var retryOptions = options ? options : this.newBackOffOptions(type.backoff);
var bh = this.newBackOffIntervalBehavior(retryOptions);
this.reg.intervalBehavior[bhKey] = bh;
}
};
Timer.prototype.finishingWrapUp = function () {
if (this.finished) {
return this;
}
this.finished = true;
this.finishTime = Date.now();
this.deltaFinish = this.finishTime - this.startTime;
this.deltaEndFinish = this.finishTime - this.endTime;
this.ixRx('finish').next(this);
for (var _i = 0, _a = this.finishResolves; _i < _a.length; _i++) {
var resolve = _a[_i];
try {
resolve(this);
}
catch (error) {
var e = this.getSnapshot('finish-error');
e.error = error;
this.ixError(error, 1, e);
}
}
if (this.autoDestroy) {
this.destroy();
}
};
Timer.allActiveTimers = {};
return Timer;
}(ix_entity_1.Entity));
exports.Timer = Timer;
var TimerRegistrant = (function () {
function TimerRegistrant(init) {
this.name = '';
this.ms = -1;
this.msBefore = -2;
this.immediate = false;
this.blockInterval = -1;
this.repeat = false;
this.paused = false;
this.skipCount = 0;
this.active = true;
this.last = 0;
this.nowait = false;
this.regStart = 0;
this.regLast = 0;
this.regOverflow = 0;
this.intervalBehavior = {};
if (init) {
Object.assign(this, init);
}
if (this.ms < 0) {
this.ms = 0;
}
this.ms = Math.ceil(this.ms);
}
TimerRegistrant.prototype.invalidate = function () {
this.active = false;
if (this.regSpot) {
var i = 0;
for (var _i = 0, _a = this.regSpot; _i < _a.length; _i++) {
var regInfo = _a[_i];
if (regInfo.reg === this) {
--this.timerblock.pendingCount;
this.regSpot.splice(i, 1);
break;
}
++i;
}
}
this.regSpot = null;
};
TimerRegistrant.prototype.update = function (updater) { if (updater) {
Object.assign(this, updater);
} };
TimerRegistrant.prototype.setImmediate = function () { var _a, _b; (_b = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.baseblock) === null || _b === void 0 ? void 0 : _b.setImmediate(this); return this; };
TimerRegistrant.prototype.registerOn = function (t) { var _a; (_a = this.updatePlacement(t)) === null || _a === void 0 ? void 0 : _a.register(this); return this; };
TimerRegistrant.prototype.updateInterval = function (newMs) { this.ms = Math.ceil(newMs); this.updatePlacement(); };
TimerRegistrant.prototype.updatePlacement = function (t) {
if (!t) {
t = this.controller;
if (!t) {
return null;
}
}
if (t !== this.controller) {
this.msBefore = -1;
this.timerblock = null;
}
if (this.msBefore === this.ms) {
return null;
}
var matched = null;
for (var _i = 0, _a = t.timerblocks; _i < _a.length; _i++) {
var timerblock = _a[_i];
if (this.ms <= timerblock.maxSupportedMs) {
matched = timerblock;
break;
}
}
this.controller = t;
this.timerblock = matched;
this.msBefore = this.ms;
this.blockInterval = this.timerblock.blockMs !== 1 ?
Math.ceil(this.ms / this.timerblock.blockMs)
: Math.ceil(this.ms);
return this.timerblock;
};
return TimerRegistrant;
}());
exports.TimerRegistrant = TimerRegistrant;
function timerInterval(spec, ontick) {
return new Timer(spec, ontick).forever();
}
exports.timerInterval = timerInterval;
//# sourceMappingURL=ix.timer.js.map