summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/middleware/batching.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/netmonitor/src/middleware/batching.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/netmonitor/src/middleware/batching.js')
-rw-r--r--devtools/client/netmonitor/src/middleware/batching.js146
1 files changed, 146 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/middleware/batching.js b/devtools/client/netmonitor/src/middleware/batching.js
new file mode 100644
index 0000000000..9d8c57084c
--- /dev/null
+++ b/devtools/client/netmonitor/src/middleware/batching.js
@@ -0,0 +1,146 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ BATCH_ACTIONS,
+ BATCH_ENABLE,
+ BATCH_RESET,
+ BATCH_FLUSH,
+} = require("resource://devtools/client/netmonitor/src/constants.js");
+
+const REQUESTS_REFRESH_RATE = 50; // ms
+
+/**
+ * Middleware that watches for actions with a "batch = true" value in their meta field.
+ * These actions are queued and dispatched as one batch after a timeout.
+ * Special actions that are handled by this middleware:
+ * - BATCH_ENABLE can be used to enable and disable the batching.
+ * - BATCH_RESET discards the actions that are currently in the queue.
+ */
+function batchingMiddleware(store) {
+ return next => {
+ let queuedActions = [];
+ let enabled = true;
+ let flushTask = null;
+
+ return action => {
+ if (action.type === BATCH_ENABLE) {
+ return setEnabled(action.enabled);
+ }
+
+ if (action.type === BATCH_RESET) {
+ return resetQueue();
+ }
+
+ if (action.type === BATCH_FLUSH) {
+ return flushQueue();
+ }
+
+ if (action.meta?.batch) {
+ if (!enabled) {
+ next(action);
+ return Promise.resolve();
+ }
+
+ queuedActions.push(action);
+
+ if (!flushTask) {
+ flushTask = new DelayedTask(flushActions, REQUESTS_REFRESH_RATE);
+ }
+
+ return flushTask.promise;
+ }
+
+ return next(action);
+ };
+
+ function setEnabled(value) {
+ enabled = value;
+
+ // If disabling the batching, flush the actions that have been queued so far
+ if (!enabled && flushTask) {
+ flushTask.runNow();
+ }
+ }
+
+ function resetQueue() {
+ queuedActions = [];
+
+ if (flushTask) {
+ flushTask.cancel();
+ flushTask = null;
+ }
+ }
+
+ function flushQueue() {
+ if (flushTask) {
+ flushTask.runNow();
+ }
+ }
+
+ function flushActions() {
+ const actions = queuedActions;
+ queuedActions = [];
+
+ next({
+ type: BATCH_ACTIONS,
+ actions,
+ });
+
+ flushTask = null;
+ }
+ };
+}
+
+/**
+ * Create a delayed task that calls the specified task function after a delay.
+ */
+function DelayedTask(taskFn, delay) {
+ this._promise = new Promise((resolve, reject) => {
+ this.runTask = cancel => {
+ if (cancel) {
+ reject("Task cancelled");
+ } else {
+ taskFn();
+ resolve();
+ }
+ this.runTask = null;
+ };
+ this.timeout = setTimeout(this.runTask, delay);
+ }).catch(console.error);
+}
+
+DelayedTask.prototype = {
+ /**
+ * Return a promise that is resolved after the task is performed or canceled.
+ */
+ get promise() {
+ return this._promise;
+ },
+
+ /**
+ * Cancel the execution of the task.
+ */
+ cancel() {
+ clearTimeout(this.timeout);
+ if (this.runTask) {
+ this.runTask(true);
+ }
+ },
+
+ /**
+ * Execute the scheduled task immediately, without waiting for the timeout.
+ * Resolves the promise correctly.
+ */
+ runNow() {
+ clearTimeout(this.timeout);
+ if (this.runTask) {
+ this.runTask();
+ }
+ },
+};
+
+module.exports = batchingMiddleware;