feat: complete Ancestor quote bot with production-ready Docker support
This commit is contained in:
58
node_modules/matrix-js-sdk/src/scheduler.ts
generated
vendored
58
node_modules/matrix-js-sdk/src/scheduler.ts
generated
vendored
@@ -18,18 +18,18 @@ limitations under the License.
|
||||
* This is an internal module which manages queuing, scheduling and retrying
|
||||
* of requests.
|
||||
*/
|
||||
import { logger } from "./logger.ts";
|
||||
import { type MatrixEvent } from "./models/event.ts";
|
||||
import { EventType } from "./@types/event.ts";
|
||||
import { removeElement } from "./utils.ts";
|
||||
import { calculateRetryBackoff, type MatrixError } from "./http-api/index.ts";
|
||||
import { type ISendEventResponse } from "./@types/requests.ts";
|
||||
import { logger } from "./logger";
|
||||
import { MatrixEvent } from "./models/event";
|
||||
import { EventType } from "./@types/event";
|
||||
import { defer, IDeferred, removeElement } from "./utils";
|
||||
import { ConnectionError, MatrixError } from "./http-api";
|
||||
import { ISendEventResponse } from "./@types/requests";
|
||||
|
||||
const DEBUG = false; // set true to enable console logging.
|
||||
|
||||
interface IQueueEntry<T> {
|
||||
event: MatrixEvent;
|
||||
resolvers: PromiseWithResolvers<T>;
|
||||
defer: IDeferred<T>;
|
||||
attempts: number;
|
||||
}
|
||||
|
||||
@@ -40,14 +40,41 @@ interface IQueueEntry<T> {
|
||||
*/
|
||||
type ProcessFunction<T> = (event: MatrixEvent) => Promise<T>;
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export class MatrixScheduler<T = ISendEventResponse> {
|
||||
/**
|
||||
* Default retry algorithm for the matrix scheduler. Retries events up to 4 times with exponential backoff.
|
||||
* Retries events up to 4 times using exponential backoff. This produces wait
|
||||
* times of 2, 4, 8, and 16 seconds (30s total) after which we give up. If the
|
||||
* failure was due to a rate limited request, the time specified in the error is
|
||||
* waited before being retried.
|
||||
* @param attempts - Number of attempts that have been made, including the one that just failed (ie. starting at 1)
|
||||
* @see retryAlgorithm
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
public static RETRY_BACKOFF_RATELIMIT(event: MatrixEvent | null, attempts: number, err: MatrixError): number {
|
||||
return calculateRetryBackoff(err, attempts, false);
|
||||
if (err.httpStatus === 400 || err.httpStatus === 403 || err.httpStatus === 401) {
|
||||
// client error; no amount of retrying with save you now.
|
||||
return -1;
|
||||
}
|
||||
if (err instanceof ConnectionError) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if event that we are trying to send is too large in any way then retrying won't help
|
||||
if (err.name === "M_TOO_LARGE") {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (err.name === "M_LIMIT_EXCEEDED") {
|
||||
const waitTime = err.data.retry_after_ms;
|
||||
if (waitTime > 0) {
|
||||
return waitTime;
|
||||
}
|
||||
}
|
||||
if (attempts > 4) {
|
||||
return -1; // give up
|
||||
}
|
||||
return 1000 * Math.pow(2, attempts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +82,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
||||
* concurrently.
|
||||
* @see queueAlgorithm
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
public static QUEUE_MESSAGES(event: MatrixEvent): string | null {
|
||||
// enqueue messages or events that associate with another event (redactions and relations)
|
||||
if (event.getType() === EventType.RoomMessage || event.hasAssociation()) {
|
||||
@@ -67,7 +95,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
||||
|
||||
// queueName: [{
|
||||
// event: MatrixEvent, // event to send
|
||||
// defer: PromiseWithResolvers, // defer to resolve/reject at the END of the retries
|
||||
// defer: Deferred, // defer to resolve/reject at the END of the retries
|
||||
// attempts: Number // number of times we've called processFn
|
||||
// }, ...]
|
||||
private readonly queues: Record<string, IQueueEntry<T>[]> = {};
|
||||
@@ -185,15 +213,15 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
||||
if (!this.queues[queueName]) {
|
||||
this.queues[queueName] = [];
|
||||
}
|
||||
const eventResolvers = Promise.withResolvers<T>();
|
||||
const deferred = defer<T>();
|
||||
this.queues[queueName].push({
|
||||
event: event,
|
||||
resolvers: eventResolvers,
|
||||
defer: deferred,
|
||||
attempts: 0,
|
||||
});
|
||||
debuglog("Queue algorithm dumped event %s into queue '%s'", event.getId(), queueName);
|
||||
this.startProcessingQueues();
|
||||
return eventResolvers.promise;
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
private startProcessingQueues(): void {
|
||||
@@ -236,7 +264,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
||||
// remove this from the queue
|
||||
this.removeNextEvent(queueName);
|
||||
debuglog("Queue '%s' sent event %s", queueName, obj.event.getId());
|
||||
obj.resolvers.resolve(res);
|
||||
obj.defer.resolve(res);
|
||||
// keep processing
|
||||
this.processQueue(queueName);
|
||||
},
|
||||
@@ -276,7 +304,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
||||
logger.info("clearing queue '%s'", queueName);
|
||||
let obj: IQueueEntry<T> | undefined;
|
||||
while ((obj = this.removeNextEvent(queueName))) {
|
||||
obj.resolvers.reject(err);
|
||||
obj.defer.reject(err);
|
||||
}
|
||||
this.disableQueue(queueName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user