UNPKG

@yoroi/common

Version:
109 lines (103 loc) 4.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cacheManageMultiRequest = void 0; var _types = require("@yoroi/types"); var _immer = require("immer"); var _monads = require("../utils/monads"); var _predicates = require("../utils/predicates"); var _cacheResolveRecordsSource = require("./cache-resolve-records-source"); const cacheManageMultiRequest = async ({ cachedInfosWithoutRecord, ids, request, persistance, unknownRecordFactory }) => { // resolve the ids to be fetched and the ones that should be read from cache const { toFetch, fromCache } = (0, _cacheResolveRecordsSource.cacheResolveRecordsSource)({ ids, cachedInfosWithoutRecord }); let updatedIds = []; let toSaveRevalidatingCache = new Map(); let toRevalidateCache = new Map(); let toResolveLocally = new Set(fromCache); let cachedRecords = new Map(); let unknownIds = []; let unknownEmptyRecords = []; let toSaveNewUnknownRecord = new Map(); let toSaveNewFromApi = new Map(); let recordsFromApi = {}; if (toFetch.length > 0) { const apiResponse = await request(toFetch); // if the request fails, we will show unknown tokens and wont block the user if ((0, _monads.isRight)(apiResponse)) recordsFromApi = apiResponse.value.data; } // to make same request time for all records, to avoid ms of difference const baseDate = Date.now(); toFetch.forEach(([id]) => { const recordFromApi = recordsFromApi[id]; if (!recordFromApi) { toResolveLocally.add(id); return; } const [statusCode] = recordFromApi; // when not-modified add to revalidate cache by updating expires if (statusCode === _types.Api.HttpStatusCode.NotModified) { const [, maxAge] = recordFromApi; toRevalidateCache.set(id, baseDate + maxAge * 1_000); return; } // when internal server error, it skips the record if (statusCode === _types.Api.HttpStatusCode.InternalServerError) { toResolveLocally.add(id); return; } const [, record, eTag, maxAge] = recordFromApi; toSaveNewFromApi.set(id, { hash: eTag, expires: baseDate + maxAge * 1_000, record }); }); updatedIds = [...toSaveNewFromApi.keys()]; // if there are empties (not-found) by the api and to refresh cache (not-modified) if (toResolveLocally.size > 0 || toRevalidateCache.size > 0) { const idsToReadFromPersistance = [...toResolveLocally.keys(), ...toRevalidateCache.keys()]; // WARN: should be the only reading operation cachedRecords = new Map(persistance.read(idsToReadFromPersistance).filter(_predicates.hasEntryValue)); toRevalidateCache.forEach((expires, id) => { const recordFromApi = cachedRecords.get(id); if (recordFromApi != null) toSaveRevalidatingCache.set(id, { ...recordFromApi, expires }); }); // ids not found at this point should create an unknown record if factory is provided unknownIds = idsToReadFromPersistance.filter(id => !cachedRecords.has(id)); if (unknownRecordFactory) { unknownIds.map(id => [id, unknownRecordFactory(id)]).forEach(([id, record]) => toSaveNewUnknownRecord.set(id, record)); } else { unknownEmptyRecords = unknownIds.map(id => [id, null]); } } // WARN: should be the only writing operation const toSave = [...toSaveNewFromApi.entries(), ...toSaveRevalidatingCache.entries(), ...toSaveNewUnknownRecord.entries()]; if (toSave.length > 0) persistance.save(toSave); const result = (0, _immer.freeze)({ records: new Map([...cachedRecords.entries(), ...toSave, ...unknownEmptyRecords]), updatedIds, unknownIds, revalidatedIds: [...toSaveRevalidatingCache.keys()], fromCacheIds: fromCache.filter(id => cachedRecords.has(id)), isInvalidated: updatedIds.length > 0 || toSaveNewUnknownRecord.size > 0 }); return result; }; exports.cacheManageMultiRequest = cacheManageMultiRequest; //# sourceMappingURL=cache-manage-multi-request.js.map