From 42ecff3d66904189c098f226c9456f17749c3a03 Mon Sep 17 00:00:00 2001 From: Leandro Boscariol Date: Wed, 29 Jun 2022 02:37:43 -0700 Subject: [PATCH] Refactor: Replaced map upload queue with arrary (#747) * Refactor: Replaced map upload queue with arrary * Refactor: Using slice(0) to clone array instead of spread operator * Refactor: using Array.some instead of Array.find As I do not need to the stored element --- src/custom/state/appData/atoms.ts | 62 +++++++++++------------------ src/custom/state/appData/types.tsx | 10 ++--- src/custom/state/appData/updater.ts | 14 +++---- src/custom/state/appData/utils.ts | 14 +++---- 4 files changed, 40 insertions(+), 60 deletions(-) diff --git a/src/custom/state/appData/atoms.ts b/src/custom/state/appData/atoms.ts index 0700c823c2..70869a8eeb 100644 --- a/src/custom/state/appData/atoms.ts +++ b/src/custom/state/appData/atoms.ts @@ -5,11 +5,10 @@ import { AddAppDataToUploadQueueParams, AppDataPendingToUpload, AppDataInfo, - FlattenedAppDataFromUploadQueue, RemoveAppDataFromUploadQueueParams, UpdateAppDataOnUploadQueueParams, } from 'state/appData/types' -import { buildAppDataRecordKey, parseAppDataRecordKey } from 'state/appData/utils' +import { buildDocFilterFn, buildInverseDocFilterFn } from 'state/appData/utils' /** * Base atom that store the current appDataInfo @@ -21,7 +20,7 @@ export const appDataInfoAtom = atom(null) */ export const appDataUploadQueueAtom = atomWithStorage( 'appDataUploadQueue', // local storage key - {} + [] ) /** @@ -32,12 +31,13 @@ export const addAppDataToUploadQueueAtom = atom( (get, set, { chainId, orderId, appData }: AddAppDataToUploadQueueParams) => { set(appDataUploadQueueAtom, () => { const docs = get(appDataUploadQueueAtom) - const key = buildAppDataRecordKey({ chainId, orderId }) - return { - ...docs, - [key]: { ...appData, uploading: false, failedAttempts: 0 }, + if (docs.some(buildDocFilterFn(chainId, orderId))) { + // Entry already in the queue, ignore + return docs } + + return [...docs, { chainId, orderId, ...appData, uploading: false, failedAttempts: 0 }] }) } ) @@ -50,23 +50,28 @@ export const updateAppDataOnUploadQueueAtom = atom( (get, set, { chainId, orderId, uploading, lastAttempt, failedAttempts }: UpdateAppDataOnUploadQueueParams) => { set(appDataUploadQueueAtom, () => { const docs = get(appDataUploadQueueAtom) - const key = buildAppDataRecordKey({ chainId, orderId }) + const existingDocIndex = docs.findIndex(buildDocFilterFn(chainId, orderId)) - if (!docs[key]) { + if (existingDocIndex === -1) { + // Entry doesn't exist in the queue, ignore return docs } - const current = docs[key] + // Create a copy of original docs + const updateDocs = docs.slice(0) + + // Using the index, get the value + const existingDoc = docs[existingDocIndex] - return { - ...docs, - [key]: { - ...current, - uploading: uploading ?? current.uploading, - lastAttempt: lastAttempt ?? current.lastAttempt, - failedAttempts: failedAttempts ?? current.failedAttempts, - }, + // Replace existing doc at index with the updated version + updateDocs[existingDocIndex] = { + ...existingDoc, + uploading: uploading ?? existingDoc.uploading, + lastAttempt: lastAttempt ?? existingDoc.lastAttempt, + failedAttempts: failedAttempts ?? existingDoc.failedAttempts, } + + return updateDocs }) } ) @@ -77,25 +82,6 @@ export const updateAppDataOnUploadQueueAtom = atom( export const removeAppDataFromUploadQueueAtom = atom( null, (get, set, { chainId, orderId }: RemoveAppDataFromUploadQueueParams) => { - set(appDataUploadQueueAtom, () => { - const docs = { ...get(appDataUploadQueueAtom) } - const key = buildAppDataRecordKey({ chainId, orderId }) - - delete docs[key] - - return docs - }) + set(appDataUploadQueueAtom, () => get(appDataUploadQueueAtom).filter(buildInverseDocFilterFn(chainId, orderId))) } ) - -/** - * Read only atom to flatten pending list of appData into a list - */ -export const flattenedAppDataFromUploadQueueAtom = atom((get) => { - const docs = get(appDataUploadQueueAtom) - - return Object.keys(docs).map((key) => ({ - ...docs[key], - ...parseAppDataRecordKey(key), - })) -}) diff --git a/src/custom/state/appData/types.tsx b/src/custom/state/appData/types.tsx index f78a98c31e..55ce584320 100644 --- a/src/custom/state/appData/types.tsx +++ b/src/custom/state/appData/types.tsx @@ -11,19 +11,17 @@ type AppDataUploadStatus = { uploading: boolean } -export type AppDataRecord = AppDataInfo & AppDataUploadStatus - -export type AppDataPendingToUpload = Record - export type AppDataKeyParams = { chainId: SupportedChainId orderId: string } +export type AppDataRecord = AppDataInfo & AppDataUploadStatus & AppDataKeyParams + +export type AppDataPendingToUpload = Array + export type AddAppDataToUploadQueueParams = AppDataKeyParams & { appData: AppDataInfo } export type UpdateAppDataOnUploadQueueParams = AppDataKeyParams & Partial export type RemoveAppDataFromUploadQueueParams = AppDataKeyParams - -export type FlattenedAppDataFromUploadQueue = AppDataKeyParams & AppDataRecord diff --git a/src/custom/state/appData/updater.ts b/src/custom/state/appData/updater.ts index dd434495f5..08107a7c67 100644 --- a/src/custom/state/appData/updater.ts +++ b/src/custom/state/appData/updater.ts @@ -6,15 +6,11 @@ import { AppDataDoc } from '@cowprotocol/cow-sdk' import { COW_SDK } from 'constants/index' import { - flattenedAppDataFromUploadQueueAtom, + appDataUploadQueueAtom, removeAppDataFromUploadQueueAtom, updateAppDataOnUploadQueueAtom, } from 'state/appData/atoms' -import { - AppDataKeyParams, - FlattenedAppDataFromUploadQueue, - UpdateAppDataOnUploadQueueParams, -} from 'state/appData/types' +import { AppDataKeyParams, AppDataRecord, UpdateAppDataOnUploadQueueParams } from 'state/appData/types' const UPLOAD_CHECK_INTERVAL = ms`10s` const BASE_FOR_EXPONENTIAL_BACKOFF = 2 // in seconds, converted to milliseconds later @@ -22,7 +18,7 @@ const ONE_SECOND = ms`1s` const MAX_TIME_TO_WAIT = ms`5 minutes` export function UploadToIpfsUpdater(): null { - const toUpload = useAtomValue(flattenedAppDataFromUploadQueueAtom) + const toUpload = useAtomValue(appDataUploadQueueAtom) const removePending = useSetAtom(removeAppDataFromUploadQueueAtom) const updatePending = useSetAtom(updateAppDataOnUploadQueueAtom) @@ -47,7 +43,7 @@ export function UploadToIpfsUpdater(): null { } async function _uploadToIpfs( - appDataRecord: FlattenedAppDataFromUploadQueue, + appDataRecord: AppDataRecord, updatePending: (params: UpdateAppDataOnUploadQueueParams) => void, removePending: (params: AppDataKeyParams) => void ) { @@ -82,7 +78,7 @@ function _canUpload(uploading: boolean, attempts: number, lastAttempt?: number): } async function _actuallyUploadToIpfs( - appDataRecord: FlattenedAppDataFromUploadQueue, + appDataRecord: AppDataRecord, updatePending: (params: UpdateAppDataOnUploadQueueParams) => void, removePending: (params: AppDataKeyParams) => void ) { diff --git a/src/custom/state/appData/utils.ts b/src/custom/state/appData/utils.ts index 05c73e9805..3aac5f5bcb 100644 --- a/src/custom/state/appData/utils.ts +++ b/src/custom/state/appData/utils.ts @@ -1,11 +1,11 @@ -import { AppDataKeyParams } from 'state/appData/types' +import { SupportedChainId } from '@cowprotocol/cow-sdk' -export function buildAppDataRecordKey({ chainId, orderId }: AppDataKeyParams): string { - return `${chainId}-${orderId}` -} +import { AppDataRecord } from 'state/appData/types' -export function parseAppDataRecordKey(key: string): AppDataKeyParams { - const [chainId, orderId] = key.split('-') +export function buildDocFilterFn(chainId: SupportedChainId, orderId: string) { + return (doc: AppDataRecord) => doc.chainId === chainId && doc.orderId === orderId +} - return { chainId, orderId } as unknown as AppDataKeyParams +export function buildInverseDocFilterFn(chainId: SupportedChainId, orderId: string) { + return (doc: AppDataRecord) => doc.chainId !== chainId && doc.orderId !== orderId }