Convert RequestScheduler.js to ts

This commit is contained in:
RMidhunSuresh 2021-11-23 11:58:15 +05:30
parent 0aae31a450
commit cf54b78af7
2 changed files with 52 additions and 32 deletions

View File

@ -23,7 +23,7 @@ import {HomeServerApi} from "./net/HomeServerApi.js";
import {Reconnector, ConnectionStatus} from "./net/Reconnector"; import {Reconnector, ConnectionStatus} from "./net/Reconnector";
import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay";
import {MediaRepository} from "./net/MediaRepository"; import {MediaRepository} from "./net/MediaRepository";
import {RequestScheduler} from "./net/RequestScheduler.js"; import {RequestScheduler} from "./net/RequestScheduler";
import {Sync, SyncStatus} from "./Sync.js"; import {Sync, SyncStatus} from "./Sync.js";
import {Session} from "./Session.js"; import {Session} from "./Session.js";
import {PasswordLoginMethod} from "./login/PasswordLoginMethod"; import {PasswordLoginMethod} from "./login/PasswordLoginMethod";

View File

@ -19,33 +19,43 @@ import {AbortError} from "../../utils/error";
import {HomeServerError} from "../error.js"; import {HomeServerError} from "../error.js";
import {HomeServerApi} from "./HomeServerApi.js"; import {HomeServerApi} from "./HomeServerApi.js";
import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import {ExponentialRetryDelay} from "./ExponentialRetryDelay";
import {Clock} from "../../platform/web/dom/Clock.js";
import type {HomeServerRequest} from "./HomeServerRequest.js";
class Request { class Request {
constructor(methodName, args) { public readonly methodName: string;
this._methodName = methodName; public readonly args: any[];
this._args = args; public resolve: (result: Response) => void;
public reject: (error: AbortError) => void;
public requestResult?: HomeServerRequest;
private readonly _responsePromise: Promise<Response>;
constructor(methodName: string, args: any[]) {
this.methodName = methodName;
this.args = args;
this._responsePromise = new Promise((resolve, reject) => { this._responsePromise = new Promise((resolve, reject) => {
this._resolve = resolve; this.resolve = resolve;
this._reject = reject; this.reject = reject;
}); });
this._requestResult = null;
} }
abort() { abort(): void {
if (this._requestResult) { if (this.requestResult) {
this._requestResult.abort(); this.requestResult.abort();
} else { } else {
this._reject(new AbortError()); this.reject(new AbortError());
} }
} }
response() { response(): Promise<Response> {
return this._responsePromise; return this._responsePromise;
} }
} }
class HomeServerApiWrapper { class HomeServerApiWrapper {
constructor(scheduler) { private readonly _scheduler: RequestScheduler;
constructor(scheduler: RequestScheduler) {
this._scheduler = scheduler; this._scheduler = scheduler;
} }
} }
@ -60,21 +70,22 @@ for (const methodName of Object.getOwnPropertyNames(HomeServerApi.prototype)) {
} }
export class RequestScheduler { export class RequestScheduler {
constructor({hsApi, clock}) { private readonly _hsApi: HomeServerApi;
private readonly _clock: Clock;
private readonly _requests: Set<Request> = new Set();
private _stopped = false;
private _wrapper = new HomeServerApiWrapper(this);
constructor({ hsApi, clock }: { hsApi: HomeServerApi; clock: Clock }) {
this._hsApi = hsApi; this._hsApi = hsApi;
this._clock = clock; this._clock = clock;
this._requests = new Set();
this._isRateLimited = false;
this._isDrainingRateLimit = false;
this._stopped = true;
this._wrapper = new HomeServerApiWrapper(this);
} }
get hsApi() { get hsApi(): HomeServerApiWrapper {
return this._wrapper; return this._wrapper;
} }
stop() { stop(): void {
this._stopped = true; this._stopped = true;
for (const request of this._requests) { for (const request of this._requests) {
request.abort(); request.abort();
@ -82,40 +93,49 @@ export class RequestScheduler {
this._requests.clear(); this._requests.clear();
} }
start() { start(): void {
this._stopped = false; this._stopped = false;
} }
_hsApiRequest(name, args) { _hsApiRequest(name: string, args: any[]): Request {
const request = new Request(name, args); const request = new Request(name, args);
this._doSend(request); this._doSend(request);
return request; return request;
} }
async _doSend(request) { private async _doSend(request: Request): Promise<void> {
this._requests.add(request); this._requests.add(request);
try { try {
let retryDelay; let retryDelay: ExponentialRetryDelay | undefined;
while (!this._stopped) { while (!this._stopped) {
try { try {
const requestResult = this._hsApi[request._methodName].apply(this._hsApi, request._args); const requestResult = this._hsApi[
request.methodName
].apply(this._hsApi, request.args);
// so the request can be aborted // so the request can be aborted
request._requestResult = requestResult; request.requestResult = requestResult;
const response = await requestResult.response(); const response = await requestResult.response();
request._resolve(response); request.resolve(response);
return; return;
} catch (err) { } catch (err) {
if (err instanceof HomeServerError && err.errcode === "M_LIMIT_EXCEEDED") { if (
err instanceof HomeServerError &&
err.errcode === "M_LIMIT_EXCEEDED"
) {
if (Number.isSafeInteger(err.retry_after_ms)) { if (Number.isSafeInteger(err.retry_after_ms)) {
await this._clock.createTimeout(err.retry_after_ms).elapsed(); await this._clock
.createTimeout(err.retry_after_ms)
.elapsed();
} else { } else {
if (!retryDelay) { if (!retryDelay) {
retryDelay = new ExponentialRetryDelay(this._clock.createTimeout); retryDelay = new ExponentialRetryDelay(
this._clock.createTimeout
);
} }
await retryDelay.waitForRetry(); await retryDelay.waitForRetry();
} }
} else { } else {
request._reject(err); request.reject(err);
return; return;
} }
} }