diff options
Diffstat (limited to 'packages/taler-wallet-core/src/observable-wrappers.ts')
-rw-r--r-- | packages/taler-wallet-core/src/observable-wrappers.ts | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/packages/taler-wallet-core/src/observable-wrappers.ts b/packages/taler-wallet-core/src/observable-wrappers.ts new file mode 100644 index 000000000..77839e047 --- /dev/null +++ b/packages/taler-wallet-core/src/observable-wrappers.ts @@ -0,0 +1,131 @@ +/* + This file is part of GNU Taler + (C) 2024 Taler Systems SA + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * @fileoverview Wrappers/proxies to make various interfaces observable. + */ + +/** + * Imports. + */ +import { + ObservabilityContext, + ObservabilityEventType, + RetryLoopOpts, + getErrorDetailFromException, +} from "@gnu-taler/taler-util"; +import { + HttpRequestLibrary, + HttpRequestOptions, + HttpResponse, +} from "@gnu-taler/taler-util/http"; +import { TaskIdStr } from "./common.js"; +import { TaskScheduler } from "./shepherd.js"; + +/** + * Task scheduler with extra observability events. + */ +export class ObservableTaskScheduler implements TaskScheduler { + constructor( + private impl: TaskScheduler, + private oc: ObservabilityContext, + ) {} + + private taskDepCache = new Set<string>(); + + private declareDep(taskId: TaskIdStr): void { + if (this.taskDepCache.size > 500) { + this.taskDepCache.clear(); + } + if (!this.taskDepCache.has(taskId)) { + this.taskDepCache.add(taskId); + this.oc.observe({ + type: ObservabilityEventType.TaskDependency, + taskId, + }); + } + } + + ensureRunning(): void { + return this.impl.ensureRunning(); + } + + run(opts?: RetryLoopOpts | undefined): Promise<void> { + return this.impl.run(opts); + } + startShepherdTask(taskId: TaskIdStr): void { + this.declareDep(taskId); + this.oc.observe({ + type: ObservabilityEventType.StartTask, + taskId, + }); + return this.impl.startShepherdTask(taskId); + } + stopShepherdTask(taskId: TaskIdStr): void { + this.declareDep(taskId); + this.oc.observe({ + type: ObservabilityEventType.StopTask, + taskId, + }); + return this.impl.stopShepherdTask(taskId); + } + resetTaskRetries(taskId: TaskIdStr): Promise<void> { + this.declareDep(taskId); + if (this.taskDepCache.size > 500) { + this.taskDepCache.clear(); + } + this.oc.observe({ + type: ObservabilityEventType.ResetTask, + taskId, + }); + return this.impl.resetTaskRetries(taskId); + } + reload(): void { + return this.impl.reload(); + } +} + +export class ObservableHttpClientLibrary implements HttpRequestLibrary { + constructor( + private impl: HttpRequestLibrary, + private oc: ObservabilityContext, + ) {} + async fetch( + url: string, + opt?: HttpRequestOptions | undefined, + ): Promise<HttpResponse> { + this.oc.observe({ + type: ObservabilityEventType.HttpFetchStart, + url: url, + }); + try { + const res = await this.impl.fetch(url, opt); + this.oc.observe({ + type: ObservabilityEventType.HttpFetchFinishSuccess, + url, + status: res.status, + }); + return res; + } catch (e) { + this.oc.observe({ + type: ObservabilityEventType.HttpFetchFinishError, + url, + error: getErrorDetailFromException(e), + }); + throw e; + } + } +} |