init
This commit is contained in:
160
node_modules/matrix-js-sdk/lib/pollingCachedValue.js
generated
vendored
Normal file
160
node_modules/matrix-js-sdk/lib/pollingCachedValue.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
||||
/*
|
||||
Copyright 2026 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { calculateRetryBackoff } from "./http-api/index.js";
|
||||
import { sleep } from "./utils.js";
|
||||
|
||||
/**
|
||||
* How to fetch and cache a given value, as passed to {@link PollingCachedValue}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines a generic mechanism to fetch and cache a value, refreshing it periodically.
|
||||
*/
|
||||
export class PollingCachedValue {
|
||||
/**
|
||||
* Build a generic mechanism allowing to fetch and cache a given value.
|
||||
* @param opts - Describes what to fetch and how to cache it, see {@link PollingCachedValueOptions}.
|
||||
*/
|
||||
constructor(opts) {
|
||||
_defineProperty(this, "cached", void 0);
|
||||
_defineProperty(this, "fetchPromise", void 0);
|
||||
_defineProperty(this, "ttlTimeoutHandle", void 0);
|
||||
_defineProperty(this, "isStopped", false);
|
||||
_defineProperty(this, "ttlMillis", void 0);
|
||||
_defineProperty(this, "logger", void 0);
|
||||
this.opts = opts;
|
||||
this.ttlMillis = opts.ttlMillis;
|
||||
this.logger = opts.logger.getChild(`PollingCachedValue<${opts.name}>`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cached value if any.
|
||||
*/
|
||||
get() {
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the value was fetched once before getting the actual cached value.
|
||||
*/
|
||||
async wait() {
|
||||
await this.doFetch();
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this as early as possible and when the value can already be fetched.
|
||||
* @param ttlMillis - The time-to-live before the value gets refreshed, overriding the one
|
||||
* given at construction. If omitted the configured default is kept.
|
||||
*/
|
||||
start(ttlMillis) {
|
||||
if (ttlMillis !== undefined) {
|
||||
this.ttlMillis = ttlMillis;
|
||||
}
|
||||
this.isStopped = false;
|
||||
// Request a fetch as soon as possible
|
||||
this.doFetch().catch(err => {
|
||||
this.logger.debug("Cached value fetch on start did fail", err);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Call when the client is stopped, or when the cached value is no longer needed.
|
||||
*/
|
||||
stop() {
|
||||
if (this.ttlTimeoutHandle) {
|
||||
clearTimeout(this.ttlTimeoutHandle);
|
||||
}
|
||||
this.isStopped = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force to refresh.
|
||||
* @throws
|
||||
*/
|
||||
async refresh() {
|
||||
await this.doFetch(true);
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal fetch method
|
||||
* @param force - if set to true will force a fetch of the value even if a fetch is already in progress.
|
||||
* @private
|
||||
*/
|
||||
async doFetch(force = false) {
|
||||
if (this.fetchPromise && !force) {
|
||||
await this.fetchPromise;
|
||||
return;
|
||||
}
|
||||
this.fetchPromise = this.fetchWithRetryPolicy();
|
||||
try {
|
||||
this.cached = await this.fetchPromise;
|
||||
if (this.isStopped) {
|
||||
this.fetchPromise = undefined;
|
||||
return;
|
||||
}
|
||||
this.logger.trace(`New cachedValue: ${this.cached}`);
|
||||
this.opts.onValueCached?.(this.cached);
|
||||
// The value is cached only for a given time.
|
||||
if (this.ttlMillis) {
|
||||
this.ttlTimeoutHandle = setTimeout(() => {
|
||||
this.fetchPromise = undefined;
|
||||
void this.doFetch();
|
||||
}, this.ttlMillis);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.debug(`Error fetching server value for ${error}`);
|
||||
if (this.isStopped) {
|
||||
this.fetchPromise = undefined;
|
||||
return;
|
||||
}
|
||||
if (!this.opts.shouldCacheError?.(error)) {
|
||||
// clear the promise, i.e next tentative will retry to fetch
|
||||
this.fetchPromise = undefined;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gracefully handle transient error retries, respect retry_after_millis for rate limits.
|
||||
* @private
|
||||
*/
|
||||
async fetchWithRetryPolicy() {
|
||||
let currentRetryCount = 0;
|
||||
while (true) {
|
||||
try {
|
||||
return await this.opts.fetch();
|
||||
} catch (e) {
|
||||
this.logger.trace(`Failed to fetch retry: ${e}`);
|
||||
if (this.isStopped) {
|
||||
throw e;
|
||||
}
|
||||
currentRetryCount++;
|
||||
const backoff = calculateRetryBackoff(e, currentRetryCount, true);
|
||||
if (backoff < 0) {
|
||||
// Max number of retries reached, or error is not retryable. rethrow the error
|
||||
throw e;
|
||||
}
|
||||
// wait for the specified time and then retry the request
|
||||
await sleep(backoff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=pollingCachedValue.js.map
|
||||
Reference in New Issue
Block a user