@leaddreamer/inventorylogic 0.0.3-beta.82 → 0.0.3-beta.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,231 +0,0 @@
1
- /**
2
- * Typedefs, constants, support functions and database operations related to Promise getQueueSize
3
- * Thes are useful for scheduling large serial asynchronous operations
4
- * @module PromiseQueue
5
- */
6
- (function () {
7
- /**
8
- * Creates a new rate limited queue. The queue is created with stopped state, i.e. you have to call start() to run jobs.
9
- * @param {number} maxCallsPerSecond=1 - The rate limit of this queue in maximum calls per seconds which may be executed at any time. Pass values less than 1 to have less than one call per second, e.g. 1/3 for 3 one call in three seconds at maximum.
10
- * @param logger
11
- * @constructor
12
- */
13
- function PromiseQueue(maxCallsPerSecond, logger) {
14
- this.maxCallsPerSecond =
15
- typeof maxCallsPerSecond === "undefined" ? 1 : maxCallsPerSecond;
16
- this.logger = logger;
17
-
18
- this.tasks = [];
19
- this.isActive = false;
20
- this.jobIntervalMillis = 1000 / maxCallsPerSecond;
21
-
22
- this.lastTaskTimestamp = null;
23
- this.currentTaskTimeoutId = null;
24
- }
25
-
26
- /**
27
- * Processes the next task and returns the id of the time used to wait for the next invocation of this method.
28
- * @private
29
- */
30
- PromiseQueue.prototype.updateTaskSchedule = function () {
31
- if (this.logger && this.logger.debug) {
32
- this.logger.debug("PromiseQueue.updateTaskSchedule");
33
- }
34
-
35
- if (this.isEmpty() || this.isStopped()) {
36
- return;
37
- }
38
-
39
- const queue = this;
40
-
41
- function processNextTask() {
42
- if (queue.logger && queue.logger.debug) {
43
- queue.logger.debug("PromiseQueue.processNextTask", queue.tasks.length);
44
- }
45
-
46
- var nextTaskItem = queue.tasks.shift();
47
- if (nextTaskItem) {
48
- try {
49
- const result = nextTaskItem.task.call();
50
-
51
- if (queue.logger && queue.logger.debug) {
52
- queue.logger.debug(
53
- "Resolving queued promise",
54
- result,
55
- result instanceof Promise
56
- );
57
- }
58
-
59
- nextTaskItem.resolve(result);
60
- } catch (e) {
61
- queue.logger.info("rejecting queued promise result", e);
62
- nextTaskItem.reject(e);
63
- }
64
- }
65
- }
66
-
67
- function scheduleNext(timeoutMillisOverride) {
68
- if (queue.logger && queue.logger.debug) {
69
- queue.logger.debug("PromiseQueue.scheduleNext", timeoutMillisOverride);
70
- }
71
-
72
- if (queue.isEmpty()) {
73
- queue.currentTaskTimeoutId = null;
74
- return;
75
- }
76
-
77
- queue.currentTaskTimeoutId = setTimeout(function () {
78
- queue.lastTaskTimestamp = Date.now();
79
- processNextTask();
80
-
81
- scheduleNext(queue.jobIntervalMillis);
82
- }, timeoutMillisOverride);
83
- }
84
-
85
- if (this.currentTaskTimeoutId == null) {
86
- if (this.lastTaskTimestamp) {
87
- let passedTime = Date.now() - this.lastTaskTimestamp;
88
- if (passedTime > this.jobIntervalMillis) {
89
- scheduleNext(this.jobIntervalMillis);
90
- } else {
91
- scheduleNext(Math.max(0, this.jobIntervalMillis - passedTime));
92
- }
93
- } else {
94
- scheduleNext(0);
95
- }
96
- }
97
- };
98
-
99
- /**
100
- * Starts the task processing of this queue.
101
- *
102
- * If it is already started, then false will be returned.
103
- * If it is not yet started then the first task will be processed in the background and true will be returned.
104
- *
105
- * @return {boolean} true if this queue wasn't started before and now started to process tasks.
106
- */
107
- PromiseQueue.prototype.start = function () {
108
- if (this.isActive) {
109
- return false;
110
- }
111
-
112
- this.isActive = true;
113
-
114
- this.updateTaskSchedule();
115
-
116
- return true;
117
- };
118
-
119
- /**
120
- * Stops the processing of this queue.
121
- * @return true if the queue was started and is now stopped. false if it was already stopped.
122
- */
123
- PromiseQueue.prototype.stop = function () {
124
- if (this.isActive) {
125
- this.isActive = false;
126
-
127
- if (this.currentTaskTimeoutId) {
128
- clearInterval(this.currentTaskTimeoutId);
129
- this.currentTaskTimeoutId = null;
130
- this.lastTaskTimestamp = null;
131
- }
132
- }
133
- };
134
-
135
- PromiseQueue.prototype.getMaxCallsPerSecond = function () {
136
- return this.maxCallsPerSecond;
137
- };
138
-
139
- PromiseQueue.prototype.isStarted = function () {
140
- return this.isActive;
141
- };
142
-
143
- PromiseQueue.prototype.isStopped = function () {
144
- return !this.isStarted();
145
- };
146
-
147
- /**
148
- * @returns {boolean} true if this queue is currently empty, i.e. if it has no tasks in the queue.
149
- */
150
- PromiseQueue.prototype.isEmpty = function () {
151
- return this.tasks.length === 0;
152
- };
153
-
154
- /**
155
- * @returns {boolean} true if this queue has one or more entries.
156
- */
157
- PromiseQueue.prototype.isNotEmpty = function () {
158
- return !this.isEmpty();
159
- };
160
-
161
- /**
162
- * @param {function} task - The task to add.
163
- * @param {boolean} append - if the task should be appended or prepended to the list of queued tasks
164
- * @return {Promise} A promise which is resolved/rejected when the task was executed by the queue.
165
- */
166
- PromiseQueue.prototype.add = function (task, append) {
167
- var self = this;
168
-
169
- var promise = new Promise(function (resolve, reject) {
170
- var newTaskItem = { task: task, resolve: resolve, reject: reject };
171
-
172
- if (self.isEmpty() || append) {
173
- self.tasks.push(newTaskItem);
174
- } else {
175
- self.tasks.unshift(newTaskItem);
176
- }
177
- });
178
-
179
- self.updateTaskSchedule();
180
-
181
- return promise;
182
- };
183
-
184
- /**
185
- * Appends a new task at the end of the queue.
186
- * @param {function} task - The task to perform. This function will be called with no arguments.
187
- * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue
188
- */
189
- PromiseQueue.prototype.append = function (task) {
190
- return this.add(task, true);
191
- };
192
-
193
- /**
194
- * Adds a new task as first item in the queue.
195
- * @param task
196
- * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue
197
- */
198
- PromiseQueue.prototype.prepend = function (task) {
199
- return this.add(task, false);
200
- };
201
-
202
- /**
203
- * Removes the task from the qeueue. If the task is contained more than one time then all occurrences will be removed.
204
- * @param {function} task - The task to remove.
205
- * @return {number} - The number of items which were removed.
206
- */
207
- PromiseQueue.prototype.remove = function (task) {
208
- if (this.isEmpty()) {
209
- return 0;
210
- }
211
-
212
- var removedItems = 0;
213
- for (var i = this.tasks.length - 1; i >= 0; i--) {
214
- if (this.tasks[i].task === task) {
215
- this.tasks.splice(i, 1);
216
- removedItems++;
217
- }
218
- }
219
-
220
- return removedItems;
221
- };
222
-
223
- /**
224
- * @returns {Number} - The number of queued/waiting tasks in the queue.
225
- */
226
- PromiseQueue.prototype.getQueueSize = function () {
227
- return this.tasks.length;
228
- };
229
-
230
- module.exports = PromiseQueue;
231
- })();
@@ -1,127 +0,0 @@
1
- function createQueue(
2
- slidingWindowInterval,
3
- maxTasksInSlidingWindow,
4
- maxConcurrent = Infinity
5
- ) {
6
- const q = [];
7
-
8
- let runningTasks = 0;
9
-
10
- function enqueue(taskHandlers) {
11
- if ([].concat(taskHandlers).length === 0) {
12
- return Promise.resolve([]);
13
- }
14
-
15
- taskHandlers = Array.isArray(taskHandlers) ? taskHandlers : [taskHandlers];
16
- const newTasks = [];
17
- for (const handler of taskHandlers) {
18
- if (typeof handler !== "function") {
19
- throw "Task must be a function";
20
- }
21
- const newTask = {
22
- handler: handler,
23
- startedAt: -1,
24
- promise: undefined
25
- };
26
- q.push(newTask);
27
- newTasks.push(newTask);
28
- }
29
-
30
- const promise = promiseAll(newTasks);
31
-
32
- runNextTaskIfPossible();
33
-
34
- promise.finally(() => {
35
- if (runningTasks === 0 && pendingTasks().length === 0) {
36
- q.splice(0, q.length);
37
- }
38
- });
39
- return promise;
40
- }
41
-
42
- function pendingTasks() {
43
- return q.filter((task) => task.startedAt === -1);
44
- }
45
-
46
- function runNextTaskIfPossible() {
47
- if (runningTasks >= maxConcurrent) {
48
- return;
49
- }
50
-
51
- const tasksInSlidingWindow = q.filter(
52
- (task) =>
53
- task.startedAt >= 0 &&
54
- task.startedAt > Date.now() - slidingWindowInterval
55
- );
56
-
57
- const availableSlotsInSlidingWindow =
58
- maxTasksInSlidingWindow - tasksInSlidingWindow.length;
59
-
60
- const nextTask = pendingTasks()[0];
61
- if (!nextTask) {
62
- return;
63
- }
64
-
65
- function runNextTask() {
66
- ++runningTasks;
67
- nextTask.startedAt = Date.now();
68
- nextTask.promise = Promise.resolve(nextTask.handler())
69
- .catch((e) => e)
70
- .finally(() => {
71
- --runningTasks;
72
- runNextTaskIfPossible();
73
- });
74
- }
75
-
76
- if (availableSlotsInSlidingWindow > 0) {
77
- runNextTask();
78
- runNextTaskIfPossible();
79
- } else {
80
- setTimeout(
81
- runNextTaskIfPossible,
82
- slidingWindowInterval -
83
- (Date.now() - tasksInSlidingWindow[0].startedAt) +
84
- 1
85
- );
86
- }
87
- }
88
-
89
- if (process.env.NODE_ENV === "TEST") {
90
- enqueue.internals = () => ({
91
- q,
92
- runningTasks
93
- });
94
- }
95
-
96
- return enqueue;
97
- }
98
-
99
- function promiseAll(newTasks) {
100
- let batchPromiseCreated = false;
101
-
102
- return new Promise((batchResolve, batchReject) => {
103
- for (const task of newTasks) {
104
- const originalHandler = task.handler;
105
- task.handler = () =>
106
- new Promise((resolve, reject) => {
107
- Promise.resolve(originalHandler())
108
- .then(resolve)
109
- .catch(reject)
110
- .finally(() => {
111
- if (batchPromiseCreated) {
112
- return;
113
- }
114
- const pendingTasks = newTasks.filter((t) => !t.promise);
115
- if (pendingTasks.length === 0) {
116
- batchPromiseCreated = true;
117
- return Promise.all(newTasks.map((t) => t.promise))
118
- .then(batchResolve)
119
- .catch(batchReject);
120
- }
121
- });
122
- });
123
- }
124
- });
125
- }
126
-
127
- module.exports = createQueue;