mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
[PM-14999] Remove Sequentialize (#12113)
* Remove Sequentialize * Delete `clearCaches`
This commit is contained in:
@@ -115,7 +115,6 @@ import { Message, MessageListener, MessageSender } from "@bitwarden/common/platf
|
||||
// eslint-disable-next-line no-restricted-imports -- Used for dependency creation
|
||||
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
|
||||
import { Lazy } from "@bitwarden/common/platform/misc/lazy";
|
||||
import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize";
|
||||
import { Account } from "@bitwarden/common/platform/models/domain/account";
|
||||
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
@@ -1442,8 +1441,6 @@ export default class MainBackground {
|
||||
await this.popupViewCacheBackgroundService.clearState();
|
||||
await this.accountService.switchAccount(userId);
|
||||
await switchPromise;
|
||||
// Clear sequentialized caches
|
||||
clearCaches();
|
||||
|
||||
if (userId == null) {
|
||||
await this.refreshBadge();
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
AbstractStorageService,
|
||||
StorageUpdate,
|
||||
} from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { sequentialize } from "@bitwarden/common/platform/misc/sequentialize";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { NodeUtils } from "@bitwarden/node/node-utils";
|
||||
|
||||
@@ -44,7 +43,6 @@ export class LowdbStorageService implements AbstractStorageService {
|
||||
this.updates$ = this.updatesSubject.asObservable();
|
||||
}
|
||||
|
||||
@sequentialize(() => "lowdbStorageInit")
|
||||
async init() {
|
||||
if (this.ready) {
|
||||
return;
|
||||
|
||||
@@ -49,7 +49,6 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { SystemService } from "@bitwarden/common/platform/abstractions/system.service";
|
||||
import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { StateEventRunnerService } from "@bitwarden/common/platform/state";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
@@ -406,8 +405,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.router.navigate(["/remove-password"]);
|
||||
break;
|
||||
case "switchAccount": {
|
||||
// Clear sequentialized caches
|
||||
clearCaches();
|
||||
if (message.userId != null) {
|
||||
await this.accountService.switchAccount(message.userId);
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
import { clearCaches, sequentialize } from "./sequentialize";
|
||||
|
||||
describe("sequentialize decorator", () => {
|
||||
it("should call the function once", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
|
||||
it("should call the function once for each instance of the object", async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
promises.push(foo2.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
expect(foo2.calls).toBe(1);
|
||||
});
|
||||
|
||||
it("should call the function once with key function", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
|
||||
it("should call the function again when already resolved", async () => {
|
||||
const foo = new Foo();
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
|
||||
it("should call the function again when already resolved with a key function", async () => {
|
||||
const foo = new Foo();
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
|
||||
it("should call the function for each argument", async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([foo.bar(1), foo.bar(1), foo.bar(2), foo.bar(2), foo.bar(3), foo.bar(3)]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
|
||||
it("should call the function for each argument with key function", async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([foo.baz(1), foo.baz(1), foo.baz(2), foo.baz(2), foo.baz(3), foo.baz(3)]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
|
||||
it("should return correct result for each call", async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
|
||||
await Promise.all([
|
||||
foo.bar(1).then((res) => allRes.push(res)),
|
||||
foo.bar(1).then((res) => allRes.push(res)),
|
||||
foo.bar(2).then((res) => allRes.push(res)),
|
||||
foo.bar(2).then((res) => allRes.push(res)),
|
||||
foo.bar(3).then((res) => allRes.push(res)),
|
||||
foo.bar(3).then((res) => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([2, 2, 4, 4, 6, 6]);
|
||||
});
|
||||
|
||||
it("should return correct result for each call with key function", async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
|
||||
await Promise.all([
|
||||
foo.baz(1).then((res) => allRes.push(res)),
|
||||
foo.baz(1).then((res) => allRes.push(res)),
|
||||
foo.baz(2).then((res) => allRes.push(res)),
|
||||
foo.baz(2).then((res) => allRes.push(res)),
|
||||
foo.baz(3).then((res) => allRes.push(res)),
|
||||
foo.baz(3).then((res) => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([3, 3, 6, 6, 9, 9]);
|
||||
});
|
||||
|
||||
describe("clearCaches", () => {
|
||||
it("should clear all caches", async () => {
|
||||
const foo = new Foo();
|
||||
const promise = Promise.all([foo.bar(1), foo.bar(1)]);
|
||||
clearCaches();
|
||||
await foo.bar(1);
|
||||
await promise;
|
||||
// one call for the first two, one for the third after the cache was cleared
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class Foo {
|
||||
calls = 0;
|
||||
|
||||
@sequentialize((args) => "bar" + args[0])
|
||||
bar(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(a * 2);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
|
||||
@sequentialize((args) => "baz" + args[0])
|
||||
baz(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(a * 3);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
const caches = new Map<any, Map<string, Promise<any>>>();
|
||||
|
||||
const getCache = (obj: any) => {
|
||||
let cache = caches.get(obj);
|
||||
if (cache != null) {
|
||||
return cache;
|
||||
}
|
||||
cache = new Map<string, Promise<any>>();
|
||||
caches.set(obj, cache);
|
||||
return cache;
|
||||
};
|
||||
|
||||
export function clearCaches() {
|
||||
caches.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use as a Decorator on async functions, it will prevent multiple 'active' calls as the same time
|
||||
*
|
||||
* If a promise was returned from a previous call to this function, that hasn't yet resolved it will
|
||||
* be returned, instead of calling the original function again
|
||||
*
|
||||
* Results are not cached, once the promise has returned, the next call will result in a fresh call
|
||||
*
|
||||
* Read more at https://github.com/bitwarden/jslib/pull/7
|
||||
*/
|
||||
export function sequentialize(cacheKey: (args: any[]) => string) {
|
||||
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
||||
const originalMethod: () => Promise<any> = descriptor.value;
|
||||
|
||||
return {
|
||||
value: function (...args: any[]) {
|
||||
const cache = getCache(this);
|
||||
const argsCacheKey = cacheKey(args);
|
||||
let response = cache.get(argsCacheKey);
|
||||
if (response != null) {
|
||||
return response;
|
||||
}
|
||||
|
||||
const onFinally = () => {
|
||||
cache.delete(argsCacheKey);
|
||||
if (cache.size === 0) {
|
||||
caches.delete(this);
|
||||
}
|
||||
};
|
||||
response = originalMethod
|
||||
.apply(this, args)
|
||||
.then((val: any) => {
|
||||
onFinally();
|
||||
return val;
|
||||
})
|
||||
.catch((err: any) => {
|
||||
onFinally();
|
||||
throw err;
|
||||
});
|
||||
|
||||
cache.set(argsCacheKey, response);
|
||||
return response;
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { sequentialize } from "./sequentialize";
|
||||
import { throttle } from "./throttle";
|
||||
|
||||
describe("throttle decorator", () => {
|
||||
@@ -51,17 +50,6 @@ describe("throttle decorator", () => {
|
||||
expect(foo.calls).toBe(10);
|
||||
expect(foo2.calls).toBe(10);
|
||||
});
|
||||
|
||||
it("should work together with sequentialize", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.qux(Math.floor(i / 2) * 2));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
class Foo {
|
||||
@@ -94,7 +82,6 @@ class Foo {
|
||||
});
|
||||
}
|
||||
|
||||
@sequentialize((args) => "qux" + args[0])
|
||||
@throttle(1, () => "qux")
|
||||
qux(a: number) {
|
||||
this.calls++;
|
||||
|
||||
@@ -51,7 +51,6 @@ import { FolderResponse } from "../../vault/models/response/folder.response";
|
||||
import { LogService } from "../abstractions/log.service";
|
||||
import { StateService } from "../abstractions/state.service";
|
||||
import { MessageSender } from "../messaging";
|
||||
import { sequentialize } from "../misc/sequentialize";
|
||||
import { StateProvider } from "../state";
|
||||
|
||||
import { CoreSyncService } from "./core-sync.service";
|
||||
@@ -103,7 +102,6 @@ export class DefaultSyncService extends CoreSyncService {
|
||||
);
|
||||
}
|
||||
|
||||
@sequentialize(() => "fullSync")
|
||||
override async fullSync(forceSync: boolean, allowThrowOnError = false): Promise<boolean> {
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||
this.syncStarted();
|
||||
|
||||
@@ -31,7 +31,6 @@ import { View } from "../../models/view/view";
|
||||
import { ConfigService } from "../../platform/abstractions/config/config.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { StateService } from "../../platform/abstractions/state.service";
|
||||
import { sequentialize } from "../../platform/misc/sequentialize";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import Domain from "../../platform/models/domain/domain-base";
|
||||
import { EncArrayBuffer } from "../../platform/models/domain/enc-array-buffer";
|
||||
@@ -390,7 +389,6 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
* cached, the cached ciphers are returned.
|
||||
* @deprecated Use `cipherViews$` observable instead
|
||||
*/
|
||||
@sequentialize(() => "getAllDecrypted")
|
||||
async getAllDecrypted(userId: UserId): Promise<CipherView[]> {
|
||||
const decCiphers = await this.getDecryptedCiphers(userId);
|
||||
if (decCiphers != null && decCiphers.length !== 0) {
|
||||
|
||||
Reference in New Issue
Block a user