UNPKG

@yoroi/common

Version:

The Common package of Yoroi SDK

107 lines (102 loc) 3.86 kB
import { Api } from '@yoroi/types'; import { freeze } from 'immer'; import { cacheResolveRecordsSource } from './cache-resolve-records-source'; import { isRight } from '../utils/monads'; import { hasEntryValue } from '../utils/predicates'; export const cacheManageMultiRequest = async _ref => { let { cachedInfosWithoutRecord, ids, request, persistance, unknownRecordFactory } = _ref; // resolve the ids to be fetched and the ones that should be read from cache const { toFetch, fromCache } = 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 (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(_ref2 => { let [id] = _ref2; 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 === Api.HttpStatusCode.NotModified) { const [, maxAge] = recordFromApi; toRevalidateCache.set(id, baseDate + maxAge * 1_000); return; } // when internal server error, it skips the record if (statusCode === 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(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(_ref3 => { let [id, record] = _ref3; return 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 = 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; }; //# sourceMappingURL=cache-manage-multi-request.js.map