Add Retries to `get` (#11176)
This commit is contained in:
parent
08f0dadc2f
commit
073fd29206
|
@ -419,7 +419,7 @@ export default class MainBackground {
|
|||
this.logService = new ConsoleLogService(isDev);
|
||||
this.cryptoFunctionService = new WebCryptoFunctionService(self);
|
||||
this.keyGenerationService = new KeyGenerationService(this.cryptoFunctionService);
|
||||
this.storageService = new BrowserLocalStorageService();
|
||||
this.storageService = new BrowserLocalStorageService(this.logService);
|
||||
|
||||
this.intraprocessMessagingSubject = new Subject<Message<Record<string, unknown>>>();
|
||||
|
||||
|
|
|
@ -1,10 +1,67 @@
|
|||
import AbstractChromeStorageService from "./abstractions/abstract-chrome-storage-api.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
|
||||
import AbstractChromeStorageService, {
|
||||
SerializedValue,
|
||||
} from "./abstractions/abstract-chrome-storage-api.service";
|
||||
|
||||
export default class BrowserLocalStorageService extends AbstractChromeStorageService {
|
||||
constructor() {
|
||||
constructor(private readonly logService: LogService) {
|
||||
super(chrome.storage.local);
|
||||
}
|
||||
|
||||
override async get<T>(key: string): Promise<T> {
|
||||
return await this.getWithRetries<T>(key, 0);
|
||||
}
|
||||
|
||||
private async getWithRetries<T>(key: string, retryNum: number): Promise<T> {
|
||||
// See: https://github.com/EFForg/privacybadger/pull/2980
|
||||
const MAX_RETRIES = 5;
|
||||
const WAIT_TIME = 200;
|
||||
|
||||
const store = await this.getStore(key);
|
||||
|
||||
if (store == null) {
|
||||
if (retryNum >= MAX_RETRIES) {
|
||||
throw new Error(`Failed to get a value for key '${key}', see logs for more details.`);
|
||||
}
|
||||
|
||||
retryNum++;
|
||||
this.logService.warning(`Retrying attempt to get value for key '${key}' in ${WAIT_TIME}ms`);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, WAIT_TIME));
|
||||
return await this.getWithRetries(key, retryNum);
|
||||
}
|
||||
|
||||
// We have a store
|
||||
return this.processGetObject<T>(store[key] as T | SerializedValue);
|
||||
}
|
||||
|
||||
private async getStore(key: string) {
|
||||
if (this.chromeStorageApi == null) {
|
||||
this.logService.warning(
|
||||
`chrome.storage.local was not initialized while retrieving key '${key}'.`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Promise<{ [key: string]: unknown }>((resolve) => {
|
||||
this.chromeStorageApi.get(key, (store) => {
|
||||
if (chrome.runtime.lastError) {
|
||||
this.logService.warning(`Failed to get value for key '${key}'`, chrome.runtime.lastError);
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
this.logService.warning(`Store was empty while retrieving value for key '${key}'`);
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(store);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async fillBuffer() {
|
||||
// Write 4MB of data in chrome.storage.local, log files will hold 4MB of data (by default)
|
||||
// before forcing a compaction. To force a compaction and have it remove previously saved data,
|
||||
|
|
|
@ -304,7 +304,7 @@ const safeProviders: SafeProvider[] = [
|
|||
safeProvider({
|
||||
provide: AbstractStorageService,
|
||||
useClass: BrowserLocalStorageService,
|
||||
deps: [],
|
||||
deps: [LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: AutofillServiceAbstraction,
|
||||
|
|
Loading…
Reference in New Issue