1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-17658] Fix persist route to clear if service worker dies (#13382)

* Add way to convert TaskSchedulerService to RX Scheduler

* Add docs to `toScheduler`

* Rollback combined subscription change.

* Move to barrel file

* Expand `toScheduler` documentation

* Add TaskName to Doc Example

* Ensure register is called on service worker start
This commit is contained in:
Justin Baur
2025-02-19 16:23:01 -05:00
committed by GitHub
parent 8912fe8187
commit 4e95c033d8
5 changed files with 85 additions and 4 deletions

View File

@@ -1,3 +1,3 @@
export { TaskSchedulerService } from "./task-scheduler.service";
export { TaskSchedulerService, toScheduler } from "./task-scheduler.service";
export { DefaultTaskSchedulerService } from "./default-task-scheduler.service";
export { ScheduledTaskNames, ScheduledTaskName } from "./scheduled-task-name.enum";

View File

@@ -7,6 +7,7 @@ export const ScheduledTaskNames = {
scheduleNextSyncInterval: "scheduleNextSyncInterval",
eventUploadsInterval: "eventUploadsInterval",
vaultTimeoutCheckInterval: "vaultTimeoutCheckInterval",
clearPopupViewCache: "clearPopupViewCache",
} as const;
export type ScheduledTaskName = (typeof ScheduledTaskNames)[keyof typeof ScheduledTaskNames];

View File

@@ -1,9 +1,68 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Subscription } from "rxjs";
import { asyncScheduler, SchedulerLike, Subscription } from "rxjs";
import { ScheduledTaskName } from "./scheduled-task-name.enum";
/**
* Creates a RXJS scheduler based on a {@link TaskSchedulerService}.
*
* @description This API defers to `TaskSchedulerService` to schedule a task to be ran
* in the future but the task that is ran is NOT the remainder of your RXJS pipeline. The
* task you want ran must instead be registered in a location reachable on a service worker
* startup (on browser). An example of an acceptible location is the constructor of a service
* you know is created in `MainBackground`. Uses of this API is other clients _can_ have the
* `registerTaskHandler` call in more places, but in order to have it work across clients
* it is recommended to register it according to the rules of browser.
*
* @link https://rxjs.dev/guide/scheduler#using-schedulers
*
* @example
* ```ts
* class MyService {
* constructor(messageListener: MessageListener, taskScheduler: TaskSchedulerService) {
* // VERY IMPORTANT!
* this.taskSchedulerService.registerTaskHandler(SchedulerTaskNames.myTaskName, async () => {
* await this.runEvent();
* });
*
* messageListener.messages$(MY_MESSAGE).pipe(
* debounceTime(
* 10 * 1000,
* toScheduler(taskScheduler, ShedulerTaskNames.myTaskName),
* ),
* switchMap(() => this.runEvent()),
* )
* }
* }
* ```
*
* @param taskScheduler The task scheduler service to use to shedule RXJS work.
* @param taskName The name of the task that the handler should be registered and scheduled based on.
* @returns A SchedulerLike object that can be passed in to RXJS operators like `delay` and `timeout`.
*/
export function toScheduler(
taskScheduler: TaskSchedulerService,
taskName: ScheduledTaskName,
): SchedulerLike {
return new TaskSchedulerSheduler(taskScheduler, taskName);
}
class TaskSchedulerSheduler implements SchedulerLike {
constructor(
private readonly taskSchedulerService: TaskSchedulerService,
private readonly taskName: ScheduledTaskName,
) {}
schedule<T>(work: (state?: T) => void, delay?: number, state?: T): Subscription {
return this.taskSchedulerService.setTimeout(this.taskName, delay ?? 0);
}
now(): number {
return asyncScheduler.now();
}
}
export abstract class TaskSchedulerService {
protected taskHandlers: Map<string, () => void>;
abstract setTimeout(taskName: ScheduledTaskName, delayInMs: number): Subscription;