From 6d07670bce7744fc968a66cc199245c02189efcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Klocek?= Date: Sat, 5 Oct 2024 15:14:04 +0200 Subject: [PATCH] [lib] Use batch Blob service endpoints in processHolders action Summary: Address [[ https://linear.app/comm/issue/ENG-9355/update-processholdersaction-to-use-batched-blob-endpoints | ENG-9355 ]]. When processing holders, we can make 1-2 batch Blob HTTP calls instead of M+N calls for every single processed holder. Depends on D13656 Test Plan: Start a DM thread, set image thread avatar, then reset back to emoji. With Redux devtools and console logs verify that actions are successful. Reviewers: kamil, tomek Reviewed By: kamil Subscribers: ashoat Differential Revision: https://phab.comm.dev/D13657 --- lib/actions/holder-actions.js | 72 +++++++++++++++-------------------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/lib/actions/holder-actions.js b/lib/actions/holder-actions.js index 31e6186dcf..fb84daec1a 100644 --- a/lib/actions/holder-actions.js +++ b/lib/actions/holder-actions.js @@ -3,7 +3,6 @@ import invariant from 'invariant'; import * as React from 'react'; -import blobService from '../facts/blob-service.js'; import { type AuthMetadata, IdentityClientContext, @@ -14,8 +13,9 @@ import type { } from '../types/holder-types.js'; import { toBase64URL } from '../utils/base64.js'; import { - makeBlobServiceEndpointURL, generateBlobHolder, + assignMultipleHolders, + removeMultipleHolders, } from '../utils/blob-service.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -50,8 +50,6 @@ type BlobServiceActionsResult = { +failed: MultipleBlobHolders, }; -// This function can be simplified when batch holders operations -// are implemented on Blob Service async function performBlobServiceHolderActions( action: 'establish' | 'remove', inputs: MultipleBlobHolders, @@ -61,53 +59,43 @@ async function performBlobServiceHolderActions( return { succeeded: [], failed: [] }; } - const endpoint = - action === 'establish' - ? blobService.httpEndpoints.ASSIGN_HOLDER - : blobService.httpEndpoints.DELETE_BLOB; - const endpointURL = makeBlobServiceEndpointURL(endpoint); const defaultHeaders = createDefaultHTTPRequestHeaders(authMetadata); + const blobServiceCall = + action === 'establish' ? assignMultipleHolders : removeMultipleHolders; + + const requestInputs = inputs.map(({ blobHash, ...rest }) => ({ + ...rest, + blobHash: toBase64URL(blobHash), + })); + const response = await blobServiceCall(requestInputs, defaultHeaders); + if (response.result === 'success') { + return { succeeded: inputs, failed: [] }; + } + if (response.result === 'error') { + return { succeeded: [], failed: inputs }; + } - const promises = inputs.map(async input => { - const blobHash = toBase64URL(input.blobHash); - try { - const response = await fetch(endpointURL, { - method: endpoint.method, - body: JSON.stringify({ - holder: input.holder, - blob_hash: blobHash, - }), - headers: { - ...defaultHeaders, - 'content-type': 'application/json', - }, - }); - const holderAlreadyEstablishedResponse = - action === 'establish' && response.status === 409; - if (response.ok || holderAlreadyEstablishedResponse) { - return { ...input, success: true }; - } - return { ...input, success: false }; - } catch (e) { - return { ...input, success: false }; - } - }); + const failedRequestsSet = new Set( + response.failedRequests.map(({ blobHash, holder }) => + JSON.stringify({ blobHash, holder }), + ), + ); - const results = await Promise.all(promises); const succeeded = [], failed = []; - for (const { success, ...holderEntry } of results) { - if (success) { - succeeded.push(holderEntry); + for (const item of inputs) { + const stringifiedItem = JSON.stringify({ + blobHash: toBase64URL(item.blobHash), + holder: item.holder, + }); + if (failedRequestsSet.has(stringifiedItem)) { + failed.push(item); } else { - failed.push(holderEntry); + succeeded.push(item); } } - return { - succeeded, - failed, - }; + return { succeeded, failed }; } async function processHoldersAction(