Stop Logger being a singleton

This commit is contained in:
Andras Schmelczer 2025-02-22 15:11:59 +00:00
parent d965265709
commit 3471a9c498
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
12 changed files with 147 additions and 138 deletions

View file

@ -1,47 +1,45 @@
import type { Syncer } from "sync-client";
import type { SyncClient, Syncer } from "sync-client";
import { Logger } from "sync-client";
import type { TAbstractFile } from "obsidian";
import { TFile } from "obsidian";
export class ObsidianFileEventHandler {
public constructor(private readonly syncer: Syncer) {}
public constructor(private readonly client: SyncClient) {}
public async onCreate(file: TAbstractFile): Promise<void> {
if (file instanceof TFile) {
Logger.getInstance().info(`File created: ${file.path}`);
this.client.logger.info(`File created: ${file.path}`);
await this.syncer.syncLocallyCreatedFile(
await this.client.syncer.syncLocallyCreatedFile(
file.path,
new Date(file.stat.ctime)
);
} else {
Logger.getInstance().debug(`Folder created: ${file.path}, ignored`);
this.client.logger.debug(`Folder created: ${file.path}, ignored`);
}
}
public async onDelete(file: TAbstractFile): Promise<void> {
if (file instanceof TFile) {
Logger.getInstance().info(`File deleted: ${file.path}`);
this.client.logger.info(`File deleted: ${file.path}`);
await this.syncer.syncLocallyDeletedFile(file.path);
await this.client.syncer.syncLocallyDeletedFile(file.path);
} else {
Logger.getInstance().debug(`Folder deleted: ${file.path}, ignored`);
this.client.logger.debug(`Folder deleted: ${file.path}, ignored`);
}
}
public async onRename(file: TAbstractFile, oldPath: string): Promise<void> {
if (file instanceof TFile) {
Logger.getInstance().info(
`File renamed: ${oldPath} -> ${file.path}`
);
this.client.logger.info(`File renamed: ${oldPath} -> ${file.path}`);
await this.syncer.syncLocallyUpdatedFile({
await this.client.syncer.syncLocallyUpdatedFile({
oldPath,
relativePath: file.path,
updateTime: new Date(file.stat.ctime)
});
} else {
Logger.getInstance().debug(
this.client.logger.debug(
`Folder renamed: ${oldPath} -> ${file.path}, ignored`
);
}
@ -53,16 +51,14 @@ export class ObsidianFileEventHandler {
return;
}
Logger.getInstance().info(`File modified: ${file.path}`);
this.client.logger.info(`File modified: ${file.path}`);
await this.syncer.syncLocallyUpdatedFile({
await this.client.syncer.syncLocallyUpdatedFile({
relativePath: file.path,
updateTime: new Date(file.stat.ctime)
});
} else {
Logger.getInstance().debug(
`Folder modified: ${file.path}, ignored`
);
this.client.logger.debug(`Folder modified: ${file.path}, ignored`);
}
}
}

View file

@ -10,7 +10,7 @@ import { StatusBar } from "./views/status-bar";
import { LogsView } from "./views/logs-view";
import { StatusDescription } from "./views/status-description";
import { Logger, SyncClient } from "sync-client";
import { SyncClient } from "sync-client";
import { ObsidianFileSystemOperations } from "./obsidian-file-system";
export default class VaultLinkPlugin extends Plugin {
@ -18,8 +18,6 @@ export default class VaultLinkPlugin extends Plugin {
private client!: SyncClient;
public async onload(): Promise<void> {
Logger.getInstance().info("Starting plugin");
this.client = await SyncClient.create(
new ObsidianFileSystemOperations(this.app.vault),
{
@ -28,6 +26,8 @@ export default class VaultLinkPlugin extends Plugin {
}
);
this.client.logger.info("Starting plugin");
const statusDescription = new StatusDescription(this.client);
this.settingsTab = new SyncSettingsTab({
@ -42,12 +42,11 @@ export default class VaultLinkPlugin extends Plugin {
this.registerView(
HistoryView.TYPE,
(leaf) =>
new HistoryView(leaf, this.client.settings, this.client.history)
(leaf) => new HistoryView(leaf, this.client)
);
this.registerView(
LogsView.TYPE,
(leaf) => new LogsView(this, this.client.settings, leaf)
(leaf) => new LogsView(this, this.client, leaf)
);
this.addRibbonIcon(
@ -61,11 +60,10 @@ export default class VaultLinkPlugin extends Plugin {
async (_: MouseEvent) => this.activateView(LogsView.TYPE)
);
const eventHandler = new ObsidianFileEventHandler(this.client.syncer);
const eventHandler = new ObsidianFileEventHandler(this.client);
this.app.workspace.onLayoutReady(async () => {
Logger.getInstance().info("Initialising sync handlers");
this.client.logger.info("Initialising sync handlers");
[
this.app.vault.on(
"create",
@ -87,7 +85,7 @@ export default class VaultLinkPlugin extends Plugin {
this.registerEvent(event);
});
Logger.getInstance().info("Sync handlers initialised");
this.client.logger.info("Sync handlers initialised");
void this.client.syncer.scheduleSyncForOfflineChanges();
});

View file

@ -2,7 +2,7 @@ import type { IconName, WorkspaceLeaf } from "obsidian";
import { ItemView, setIcon } from "obsidian";
import { intlFormatDistance } from "date-fns";
import type { SyncHistory, HistoryEntry, Settings } from "sync-client";
import type { HistoryEntry, SyncClient } from "sync-client";
import { SyncType, SyncSource, SyncStatus, Logger } from "sync-client";
export class HistoryView extends ItemView {
@ -12,15 +12,14 @@ export class HistoryView extends ItemView {
public constructor(
leaf: WorkspaceLeaf,
private readonly settings: Settings,
private readonly history: SyncHistory
private readonly client: SyncClient
) {
super(leaf);
this.icon = HistoryView.ICON;
history.addSyncHistoryUpdateListener(() => {
this.client.history.addSyncHistoryUpdateListener(() => {
this.updateView().catch((_error: unknown) => {
Logger.getInstance().error("Failed to update history view");
this.client.logger.error("Failed to update history view");
});
});
}
@ -94,13 +93,13 @@ export class HistoryView extends ItemView {
container.empty();
container.createEl("h4", { text: "VaultLink History" });
const entries = this.history
const entries = this.client.history
.getEntries()
.reverse()
.filter(
(entry) =>
entry.status !== SyncStatus.NO_OP ||
this.settings.getSettings().displayNoopSyncEvents
this.client.settings.getSettings().displayNoopSyncEvents
);
entries.forEach((entry) => {

View file

@ -1,8 +1,7 @@
import type { WorkspaceLeaf } from "obsidian";
import { ItemView } from "obsidian";
import type VaultLinkPlugin from "src/vault-link-plugin";
import type { Settings } from "sync-client";
import { Logger } from "sync-client";
import type { SyncClient } from "sync-client";
export class LogsView extends ItemView {
public static readonly TYPE = "logs-view";
@ -10,20 +9,24 @@ export class LogsView extends ItemView {
public constructor(
private readonly plugin: VaultLinkPlugin,
private readonly settings: Settings,
private readonly client: SyncClient,
leaf: WorkspaceLeaf
) {
super(leaf);
this.icon = LogsView.ICON;
Logger.getInstance().addOnMessageListener(() => {
this.client.logger.addOnMessageListener(() => {
this.updateView();
});
settings.addOnSettingsChangeHandlers((newSettings, oldSettings) => {
if (newSettings.minimumLogLevel !== oldSettings.minimumLogLevel) {
this.updateView();
this.client.settings.addOnSettingsChangeHandlers(
(newSettings, oldSettings) => {
if (
newSettings.minimumLogLevel !== oldSettings.minimumLogLevel
) {
this.updateView();
}
}
});
);
}
private static formatTimestamp(timestamp: Date): string {
@ -78,8 +81,8 @@ export class LogsView extends ItemView {
}
);
const logs = Logger.getInstance().getMessages(
this.settings.getSettings().minimumLogLevel
const logs = this.client.logger.getMessages(
this.client.settings.getSettings().minimumLogLevel
);
if (logs.length === 0) {

View file

@ -4,16 +4,19 @@ import { RelativePath } from "src/persistence/database";
import { isBinary, isFileTypeMergable, mergeText } from "sync_lib";
export class FileOperations {
public constructor(private readonly fs: FileSystemOperations) {}
public constructor(
private readonly logger: Logger,
private readonly fs: FileSystemOperations
) {}
public async listAllFiles(): Promise<RelativePath[]> {
const files = await this.fs.listAllFiles();
Logger.getInstance().debug(`Listing all files, found ${files.length}`);
this.logger.debug(`Listing all files, found ${files.length}`);
return files;
}
public async read(path: RelativePath): Promise<Uint8Array> {
Logger.getInstance().debug(`Reading file: ${path}`);
this.logger.debug(`Reading file: ${path}`);
const content = await this.fs.read(path);
if (isBinary(content)) {
@ -30,17 +33,17 @@ export class FileOperations {
}
public async getFileSize(path: RelativePath): Promise<number> {
Logger.getInstance().debug(`Getting file size: ${path}`);
this.logger.debug(`Getting file size: ${path}`);
return this.fs.getFileSize(path);
}
public async getModificationTime(path: RelativePath): Promise<Date> {
Logger.getInstance().debug(`Getting modification time: ${path}`);
this.logger.debug(`Getting modification time: ${path}`);
return this.fs.getModificationTime(path);
}
public async exists(path: RelativePath): Promise<boolean> {
Logger.getInstance().debug(`Checking existance of ${path}`);
this.logger.debug(`Checking existance of ${path}`);
return this.fs.exists(path);
}
@ -50,9 +53,9 @@ export class FileOperations {
path: RelativePath,
newContent: Uint8Array
): Promise<void> {
Logger.getInstance().debug(`Creating file: ${path}`);
this.logger.debug(`Creating file: ${path}`);
if (await this.fs.exists(path)) {
Logger.getInstance().debug(
this.logger.debug(
`Didn't expect ${path} to exist, when trying to create it, merging instead`
);
await this.write(path, new Uint8Array(0), newContent);
@ -71,9 +74,9 @@ export class FileOperations {
expectedContent: Uint8Array,
newContent: Uint8Array
): Promise<Uint8Array> {
Logger.getInstance().debug(`Writing file: ${path}`);
this.logger.debug(`Writing file: ${path}`);
if (!(await this.fs.exists(path))) {
Logger.getInstance().debug(
this.logger.debug(
`The caller assumed ${path} exists, but it no longer, so we wont recreate it`
);
return new Uint8Array(0);
@ -84,7 +87,7 @@ export class FileOperations {
isBinary(expectedContent) ||
isBinary(newContent)
) {
Logger.getInstance().debug(
this.logger.debug(
`The expected content is not mergable, so we won't perform a 3-way merge, just overwrite it`
);
await this.fs.write(path, newContent);
@ -99,14 +102,14 @@ export class FileOperations {
(currentText) => {
currentText = currentText.replace(/\r\n/g, "\n");
if (currentText !== expectedText) {
Logger.getInstance().debug(
this.logger.debug(
`Performing a 3-way merge for ${path} with the expected content`
);
return mergeText(expectedText, currentText, newText);
}
Logger.getInstance().debug(
this.logger.debug(
`The current content of ${path} is the same as the expected content, so we will just write the new content`
);
@ -117,7 +120,7 @@ export class FileOperations {
}
public async remove(path: RelativePath): Promise<void> {
Logger.getInstance().debug(`Removing file: ${path}`);
this.logger.debug(`Removing file: ${path}`);
return this.fs.delete(path);
}
@ -125,7 +128,7 @@ export class FileOperations {
oldPath: RelativePath,
newPath: RelativePath
): Promise<void> {
Logger.getInstance().debug(`Moving file: ${oldPath} -> ${newPath}`);
this.logger.debug(`Moving file: ${oldPath} -> ${newPath}`);
if (oldPath === newPath) {
return;

View file

@ -20,6 +20,7 @@ export class Database {
private lastSeenUpdateId: VaultUpdateId | undefined;
public constructor(
private readonly logger: Logger,
initialState: Partial<StoredDatabase> | undefined,
private readonly saveData: (data: unknown) => Promise<void>
) {
@ -32,10 +33,10 @@ export class Database {
this.documents.set(relativePath, metadata as DocumentMetadata);
}
}
Logger.getInstance().debug(`Loaded ${this.documents.size} documents`);
this.logger.debug(`Loaded ${this.documents.size} documents`);
this.lastSeenUpdateId = initialState.lastSeenUpdateId;
Logger.getInstance().debug(
this.logger.debug(
`Loaded last seen update id: ${this.lastSeenUpdateId}`
);
}

View file

@ -33,6 +33,7 @@ export class Settings {
) => void)[] = [];
public constructor(
private readonly logger: Logger,
initialState: Partial<SyncSettings> | undefined,
private readonly saveData: (data: unknown) => Promise<void>
) {
@ -41,7 +42,7 @@ export class Settings {
...(initialState ?? {})
};
Logger.getInstance().debug(
this.logger.debug(
`Loaded settings: ${JSON.stringify(this.settings, null, 2)}`
);
}
@ -70,7 +71,7 @@ export class Settings {
value: SyncSettings[T]
): Promise<void> {
const newSettings = { ...this.settings, [key]: value };
Logger.getInstance().debug(
this.logger.debug(
`Setting ${key} to ${value}, new settings: ${JSON.stringify(
newSettings,
null,

View file

@ -7,7 +7,7 @@ import type {
VaultUpdateId
} from "../persistence/database";
import { Logger } from "src/tracing/logger";
import { retriedFetch } from "src/utils/retried-fetch";
import { retriedFetchFactory } from "src/utils/retried-fetch";
import type { SyncSettings } from "dist/types";
import type { Settings } from "src/persistence/settings";
@ -19,7 +19,10 @@ export class SyncService {
private client!: Client<paths>;
private clientWithoutRetries!: Client<paths>;
public constructor(private readonly settings: Settings) {
public constructor(
private readonly settings: Settings,
private readonly logger: Logger
) {
this.createClient(settings.getSettings());
settings.addOnSettingsChangeHandlers(this.createClient.bind(this));
@ -73,7 +76,7 @@ export class SyncService {
);
}
Logger.getInstance().debug(
this.logger.debug(
`Created document ${JSON.stringify(response.data)} with id ${
response.data.documentId
}`
@ -124,7 +127,7 @@ export class SyncService {
);
}
Logger.getInstance().debug(
this.logger.debug(
`Updated document ${JSON.stringify(response.data)} with id ${
response.data.documentId
}`
@ -165,7 +168,7 @@ export class SyncService {
throw new Error(`Failed to delete document`);
}
Logger.getInstance().debug(
this.logger.debug(
`Deleted document ${relativePath} with id ${documentId}`
);
@ -198,7 +201,7 @@ export class SyncService {
);
}
Logger.getInstance().debug(
this.logger.debug(
`Get document ${response.data.relativePath} with id ${response.data.documentId}`
);
@ -229,7 +232,7 @@ export class SyncService {
);
}
Logger.getInstance().debug(
this.logger.debug(
`Got ${response.data.latestDocuments.length} document metadata`
);
@ -267,9 +270,7 @@ export class SyncService {
}
});
Logger.getInstance().debug(
`Ping response: ${JSON.stringify(response.data)}`
);
this.logger.debug(`Ping response: ${JSON.stringify(response.data)}`);
if (!response.data) {
throw new Error(
@ -283,7 +284,7 @@ export class SyncService {
private createClient(settings: SyncSettings): void {
this.client = createClient<paths>({
baseUrl: settings.remoteUri,
fetch: retriedFetch
fetch: retriedFetchFactory(this.logger)
});
this.clientWithoutRetries = createClient<paths>({

View file

@ -12,14 +12,15 @@ import { FileSystemOperations } from "./file-operations/filesystem-operations";
import { FileOperations } from "./file-operations/file-operations";
export class SyncClient {
private remoteListenerIntervalId: number | null = null;
private remoteListenerIntervalId: NodeJS.Timeout | null = null;
private constructor(
private readonly _history: SyncHistory,
private readonly _settings: Settings,
private readonly _database: Database,
private readonly _syncer: Syncer,
private readonly _syncService: SyncService
private readonly _syncService: SyncService,
private readonly _logger: Logger
) {}
public get history(): SyncHistory {
@ -34,12 +35,17 @@ export class SyncClient {
return this._syncer;
}
public get logger(): Logger {
return this._logger;
}
public static async create(
fs: FileSystemOperations,
persistence: PersistenceProvider
): Promise<SyncClient> {
const history = new SyncHistory();
Logger.getInstance().info("Starting SyncClient");
const logger = new Logger();
const history = new SyncHistory(logger);
logger.info("Starting SyncClient");
await init(
// eslint-disable-next-line
@ -54,6 +60,7 @@ export class SyncClient {
database: undefined
};
const database = new Database(
logger,
state.database,
async (data: unknown): Promise<void> => {
state = { ...state, database: data };
@ -62,6 +69,7 @@ export class SyncClient {
);
const settings = new Settings(
logger,
state.settings,
async (data: unknown): Promise<void> => {
state = { ...state, settings: data };
@ -69,13 +77,14 @@ export class SyncClient {
}
);
const syncService = new SyncService(settings);
const syncService = new SyncService(settings, logger);
const syncer = new Syncer(
logger,
database,
settings,
syncService,
new FileOperations(fs),
new FileOperations(logger, fs),
history
);
@ -84,7 +93,8 @@ export class SyncClient {
settings,
database,
syncer,
syncService
syncService,
logger
);
void syncer.scheduleSyncForOfflineChanges();
@ -102,14 +112,14 @@ export class SyncClient {
syncer
.scheduleSyncForOfflineChanges()
.catch((_error: unknown) => {
Logger.getInstance().error(
logger.error(
"Failed to schedule sync for offline changes"
);
});
}
});
Logger.getInstance().info("SyncClient loaded");
logger.info("SyncClient loaded");
return client;
}
@ -125,21 +135,21 @@ export class SyncClient {
public async reset(): Promise<void> {
await this._syncer.reset();
this._history.reset();
Logger.getInstance().reset();
this.logger.reset();
}
public onunload(): void {
if (this.remoteListenerIntervalId !== null) {
window.clearInterval(this.remoteListenerIntervalId);
clearInterval(this.remoteListenerIntervalId);
}
}
private registerRemoteEventListener(intervalMs: number): void {
if (this.remoteListenerIntervalId !== null) {
window.clearInterval(this.remoteListenerIntervalId);
clearInterval(this.remoteListenerIntervalId);
}
this.remoteListenerIntervalId = window.setInterval(
this.remoteListenerIntervalId = setInterval(
() => void this._syncer.applyRemoteChangesLocally(),
intervalMs
);

View file

@ -29,6 +29,7 @@ export class Syncer {
undefined;
public constructor(
private readonly logger: Logger,
private readonly database: Database,
private readonly settings: Settings,
private readonly syncService: SyncService,
@ -91,16 +92,14 @@ export class Syncer {
public async scheduleSyncForOfflineChanges(): Promise<void> {
if (!this.settings.getSettings().isSyncEnabled) {
Logger.getInstance().debug(
this.logger.debug(
`Syncing is disabled, not uploading local changes`
);
return;
}
if (this.runningScheduleSyncForOfflineChanges != null) {
Logger.getInstance().debug(
"Uploading local changes is already in progress"
);
this.logger.debug("Uploading local changes is already in progress");
return this.runningScheduleSyncForOfflineChanges;
}
@ -108,11 +107,9 @@ export class Syncer {
this.runningScheduleSyncForOfflineChanges =
this.internalScheduleSyncForOfflineChanges();
await this.runningScheduleSyncForOfflineChanges;
Logger.getInstance().info(
`All local changes have been applied remotely`
);
this.logger.info(`All local changes have been applied remotely`);
} catch (e) {
Logger.getInstance().error(
this.logger.error(
`Not all local changes have been applied remotely: ${e}`
);
throw e;
@ -150,7 +147,7 @@ export class Syncer {
(item) => item != originalFile
);
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} was not found under its current path in the database but was found under a different path ${originalFile[0]}, scheduling sync to move it`
);
return this.internalSyncLocallyUpdatedFile({
@ -167,7 +164,7 @@ export class Syncer {
});
}
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} not found in database, scheduling sync to create it`
);
return this.internalSyncLocallyCreatedFile(
@ -178,7 +175,7 @@ export class Syncer {
);
}
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} has been updated locally, scheduling sync to update it`
);
return this.internalSyncLocallyUpdatedFile({
@ -194,12 +191,12 @@ export class Syncer {
await Promise.all(
locallyDeletedFiles.map(async ([relativePath, _]) => {
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} has been deleted locally, scheduling sync to delete it`
);
if (await this.operations.exists(relativePath)) {
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} actually exists locally, skipping`
);
return Promise.resolve();
@ -212,14 +209,14 @@ export class Syncer {
public async applyRemoteChangesLocally(): Promise<void> {
if (!this.settings.getSettings().isSyncEnabled) {
Logger.getInstance().debug(
this.logger.debug(
`Syncing is disabled, not fetching remote changes`
);
return;
}
if (this.runningApplyRemoteChangesLocally != null) {
Logger.getInstance().debug(
this.logger.debug(
"Applying remote changes locally is already in progress"
);
return this.runningApplyRemoteChangesLocally;
@ -229,13 +226,9 @@ export class Syncer {
this.runningApplyRemoteChangesLocally =
this.internalApplyRemoteChangesLocally();
await this.runningApplyRemoteChangesLocally;
Logger.getInstance().info(
"All remote changes have been applied locally"
);
this.logger.info("All remote changes have been applied locally");
} catch (e) {
Logger.getInstance().error(
`Failed to apply remote changes locally: ${e}`
);
this.logger.error(`Failed to apply remote changes locally: ${e}`);
throw e;
} finally {
this.runningApplyRemoteChangesLocally = undefined;
@ -248,11 +241,11 @@ export class Syncer {
);
if (remote.latestDocuments.length === 0) {
Logger.getInstance().debug("No remote changes to apply");
this.logger.debug("No remote changes to apply");
return;
}
Logger.getInstance().info("Applying remote changes locally");
this.logger.info("Applying remote changes locally");
await Promise.all(
remote.latestDocuments.map(async (remoteDocument) =>
@ -317,7 +310,7 @@ export class Syncer {
const localMetadata = this.database.getDocument(relativePath);
if (localMetadata) {
Logger.getInstance().debug(
this.logger.debug(
`Document metadata already exists for ${relativePath}, it must have been downloaded from the server`
);
@ -631,7 +624,7 @@ export class Syncer {
const [relativePath, metadata] = localMetadata;
if (metadata.parentVersionId === remoteVersion.vaultUpdateId) {
Logger.getInstance().debug(
this.logger.debug(
`Document ${relativePath} is already up to date`
);
return;
@ -658,7 +651,7 @@ export class Syncer {
const currentHash = hash(currentContent);
if (currentHash !== metadata.hash) {
Logger.getInstance().info(
this.logger.info(
`Document ${relativePath} has been updated both remotely and locally, letting the local file update event handle it`
);
return;
@ -716,18 +709,18 @@ export class Syncer {
fn: () => Promise<void>
): Promise<void> {
if (!this.settings.getSettings().isSyncEnabled) {
Logger.getInstance().info(
this.logger.info(
`Syncing is disabled, not syncing ${relativePath}`
);
return;
}
if (!this.operations.isFileEligibleForSync(relativePath)) {
Logger.getInstance().info(
this.logger.info(
`File ${relativePath} is not eligible for syncing`
);
return;
}
Logger.getInstance().debug(`Syncing ${relativePath}`);
this.logger.debug(`Syncing ${relativePath}`);
await waitForDocumentLock(relativePath);
try {

View file

@ -47,6 +47,8 @@ export class SyncHistory {
error: 0
};
public constructor(private logger: Logger) {}
public getEntries(): HistoryEntry[] {
return [...this.entries];
}
@ -78,16 +80,16 @@ export class SyncHistory {
if (entry.status === SyncStatus.SUCCESS) {
this.status.success++;
Logger.getInstance().info(
this.logger.info(
`History entry: ${entry.relativePath} - ${entry.message}`
);
} else if (entry.status === SyncStatus.ERROR) {
this.status.error++;
Logger.getInstance().error(
this.logger.error(
`Error syncing file: ${entry.relativePath} - ${entry.message}`
);
} else {
Logger.getInstance().debug(
this.logger.debug(
`No-op syncing file: ${entry.relativePath} - ${entry.message}`
);
}

View file

@ -14,23 +14,25 @@ function getUrlFromInput(input: RequestInfo | URL): string {
return input.url;
}
export async function retriedFetch(
input: RequestInfo | URL,
init: RequestInitRetryParams<typeof fetch> = {}
): Promise<Response> {
return fetchWithRetry(input, {
retryOn: function (attempt, error, response) {
if (error !== null || !response || response.status >= 500) {
Logger.getInstance().warn(
`Retrying fetch for ${getUrlFromInput(input)}, attempt ${attempt}`
);
export function retriedFetchFactory(logger: Logger) {
return (
input: RequestInfo | URL,
init: RequestInitRetryParams<typeof fetch> = {}
): Promise<Response> => {
return fetchWithRetry(input, {
retryOn: function (attempt, error, response) {
if (error !== null || !response || response.status >= 500) {
logger.warn(
`Retrying fetch for ${getUrlFromInput(input)}, attempt ${attempt}`
);
return true;
}
return false;
},
retries: 6,
retryDelay: (attempt) => Math.pow(1.5, attempt) * 500,
...init
});
return true;
}
return false;
},
retries: 6,
retryDelay: (attempt) => Math.pow(1.5, attempt) * 500,
...init
});
};
}