feat: complete Ancestor quote bot with production-ready Docker support

This commit is contained in:
unfunny
2026-09-13 14:14:38 -04:00
parent f2016da05a
commit fe7351a7dc
1145 changed files with 30890 additions and 97684 deletions

View File

@@ -1,4 +1,17 @@
import _defineProperty from "@babel/runtime/helpers/defineProperty";
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ToDeviceMessageQueue = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _event = require("./@types/event");
var _logger = require("./logger");
var _client = require("./client");
var _scheduler = require("./scheduler");
var _sync = require("./sync");
var _utils = require("./utils");
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
@@ -15,28 +28,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { ToDeviceMessageId } from "./@types/event.js";
import { ClientEvent } from "./client.js";
import { MatrixScheduler } from "./scheduler.js";
import { SyncState } from "./sync.js";
import { MapWithDefault } from "./utils.js";
const MAX_BATCH_SIZE = 20;
/**
* Maintains a queue of outgoing to-device messages, sending them
* as soon as the homeserver is reachable.
*/
export class ToDeviceMessageQueue {
constructor(client, logger) {
_defineProperty(this, "sending", false);
_defineProperty(this, "running", true);
_defineProperty(this, "retryTimeout", null);
_defineProperty(this, "retryAttempts", 0);
_defineProperty(this, "sendQueue", async () => {
class ToDeviceMessageQueue {
constructor(client) {
this.client = client;
(0, _defineProperty2.default)(this, "sending", false);
(0, _defineProperty2.default)(this, "running", true);
(0, _defineProperty2.default)(this, "retryTimeout", null);
(0, _defineProperty2.default)(this, "retryAttempts", 0);
(0, _defineProperty2.default)(this, "sendQueue", async () => {
if (this.retryTimeout !== null) clearTimeout(this.retryTimeout);
this.retryTimeout = null;
if (this.sending || !this.running) return;
this.logger.debug("Attempting to send queued to-device messages");
_logger.logger.debug("Attempting to send queued to-device messages");
this.sending = true;
let headBatch;
try {
@@ -50,22 +59,24 @@ export class ToDeviceMessageQueue {
// Make sure we're still running after the async tasks: if not, stop.
if (!this.running) return;
this.logger.debug("All queued to-device messages sent");
_logger.logger.debug("All queued to-device messages sent");
} catch (e) {
++this.retryAttempts;
const retryDelay = MatrixScheduler.RETRY_BACKOFF_RATELIMIT(null, this.retryAttempts, e);
// eslint-disable-next-line @typescript-eslint/naming-convention
// eslint-disable-next-line new-cap
const retryDelay = _scheduler.MatrixScheduler.RETRY_BACKOFF_RATELIMIT(null, this.retryAttempts, e);
if (retryDelay === -1) {
// the scheduler function doesn't differentiate between fatal errors and just getting
// bored and giving up for now
if (Math.floor(e.httpStatus / 100) === 4) {
this.logger.error("Fatal error when sending to-device message - dropping to-device batch!", e);
_logger.logger.error("Fatal error when sending to-device message - dropping to-device batch!", e);
await this.client.store.removeToDeviceBatch(headBatch.id);
} else {
this.logger.info("Automatic retry limit reached for to-device messages.");
_logger.logger.info("Automatic retry limit reached for to-device messages.");
}
return;
}
this.logger.info(`Failed to send batch of to-device messages. Will retry in ${retryDelay}ms`, e);
_logger.logger.info(`Failed to send batch of to-device messages. Will retry in ${retryDelay}ms`, e);
this.retryTimeout = setTimeout(this.sendQueue, retryDelay);
} finally {
this.sending = false;
@@ -75,25 +86,23 @@ export class ToDeviceMessageQueue {
* Listen to sync state changes and automatically resend any pending events
* once syncing is resumed
*/
_defineProperty(this, "onResumedSync", (state, oldState) => {
if (state === SyncState.Syncing && oldState !== SyncState.Syncing) {
this.logger.info(`Resuming queue after resumed sync`);
void this.sendQueue();
(0, _defineProperty2.default)(this, "onResumedSync", (state, oldState) => {
if (state === _sync.SyncState.Syncing && oldState !== _sync.SyncState.Syncing) {
_logger.logger.info(`Resuming queue after resumed sync`);
this.sendQueue();
}
});
this.client = client;
this.logger = logger;
}
start() {
this.running = true;
this.sendQueue();
this.client.on(ClientEvent.Sync, this.onResumedSync);
this.client.on(_client.ClientEvent.Sync, this.onResumedSync);
}
stop() {
this.running = false;
if (this.retryTimeout !== null) clearTimeout(this.retryTimeout);
this.retryTimeout = null;
this.client.removeListener(ClientEvent.Sync, this.onResumedSync);
this.client.removeListener(_client.ClientEvent.Sync, this.onResumedSync);
}
async queueBatch(batch) {
const batches = [];
@@ -104,22 +113,23 @@ export class ToDeviceMessageQueue {
txnId: this.client.makeTxnId()
};
batches.push(batchWithTxnId);
const msgmap = batchWithTxnId.batch.map(msg => `${msg.userId}/${msg.deviceId} (msgid ${msg.payload[ToDeviceMessageId]})`);
this.logger.info(`Enqueuing batch of to-device messages. type=${batch.eventType} txnid=${batchWithTxnId.txnId}`, msgmap);
const msgmap = batchWithTxnId.batch.map(msg => `${msg.userId}/${msg.deviceId} (msgid ${msg.payload[_event.ToDeviceMessageId]})`);
_logger.logger.info(`Enqueuing batch of to-device messages. type=${batch.eventType} txnid=${batchWithTxnId.txnId}`, msgmap);
}
await this.client.store.saveToDeviceBatches(batches);
void this.sendQueue();
this.sendQueue();
}
/**
* Attempts to send a batch of to-device messages.
*/
async sendBatch(batch) {
const contentMap = new MapWithDefault(() => new Map());
const contentMap = new _utils.MapWithDefault(() => new Map());
for (const item of batch.batch) {
contentMap.getOrCreate(item.userId).set(item.deviceId, item.payload);
}
this.logger.info(`Sending batch of ${batch.batch.length} to-device messages with ID ${batch.id} and txnId ${batch.txnId}`);
_logger.logger.info(`Sending batch of ${batch.batch.length} to-device messages with ID ${batch.id} and txnId ${batch.txnId}`);
await this.client.sendToDevice(batch.eventType, contentMap, batch.txnId);
}
}
exports.ToDeviceMessageQueue = ToDeviceMessageQueue;
//# sourceMappingURL=ToDeviceMessageQueue.js.map