Skip to content

Commit

Permalink
Break calls to COMS object search from service layer
Browse files Browse the repository at this point in the history
  • Loading branch information
TimCsaky committed Aug 23, 2023
1 parent 5035b3f commit b7283cb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 42 deletions.
35 changes: 34 additions & 1 deletion frontend/src/services/objectService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { comsAxios } from './interceptors';
import { setDispositionHeader } from '@/utils/utils';
import { ConfigService } from './index';

import type { AxiosRequestConfig } from 'axios';
import type { GetMetadataOptions, GetObjectTaggingOptions, MetadataPair, SearchObjectsOptions, Tag } from '@/types';
Expand Down Expand Up @@ -227,7 +228,39 @@ export default {
searchObjects(params: SearchObjectsOptions = {}, headers: any = {},) {
// remove objectId array if its first element is undefined
if (params.objectId && params.objectId[0] === undefined) delete params.objectId;
return comsAxios().get(PATH, { params: params, headers: headers });

if (params.objectId) {

// --- split calls to `objectService.searchObjects()` if URL limit excedes 2000 characters
// recommended url limit (https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers)
const urlLimit = 2000;
// caculate number of characters taken by base url and query params other than objectId:
const { objectId: objectIds, ...otherParams } = params;
const url = new URL(`${new ConfigService().getConfig().coms.apiPath}${PATH}`);
url.search = new URLSearchParams(otherParams);
const otherCharacters = url.toString().length;
const space = urlLimit - otherCharacters;
// number of allowed objectId's in each group - 48 chars for each objectId (&objectId[]=<uuid>)
const groupSize = Math.floor(space / 48);

// loop through each group and push COMS result to `groups` array
const iterations = Math.ceil(objectIds.length / groupSize);
const groups = [];
for (let i = 0; i < iterations; i++) {
const ids = objectIds.slice(i * groupSize, ((i * groupSize) + groupSize));
groups.push(comsAxios().get(PATH, { params: { ...params, objectId: ids }, headers: headers }));
}

Promise.allSettled(groups)
.then((results) => {
return results.map((x) => {
return x.value.data;
}).flat();
});
}
else {
return comsAxios().get(PATH, { params: params, headers: headers });
}
},

/**
Expand Down
51 changes: 10 additions & 41 deletions frontend/src/store/objectStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const useObjectStore = defineStore('object', () => {
.filter((objectId: string) => !params.objectId || objectId === params.objectId))
];

const response = Array<COMSObject>();
let response = Array<COMSObject>();
if (uniqueIds.length) {
// If metadata specified, search for objects with matching metadata
const headers: Record<string, string> = {};
Expand All @@ -137,47 +137,16 @@ export const useObjectStore = defineStore('object', () => {
}
}

response = (await objectService.searchObjects({
bucketId: params.bucketId ? [params.bucketId] : undefined,
objectId: uniqueIds.slice(0,20),
tagset: tagset ? tagset.reduce((acc, cur) => ({ ...acc, [cur.key]: cur.value }), {}) : undefined,

/**
* split calls to `objectService.searchObjects()` if URL limit excedes 2000 characters
* ref: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
*/
let maxLength = 2000;
// minus deleteMarker=false
maxLength = maxLength - 19;
// minus latest=false
maxLength = maxLength - 13;
// minus a single bucketId (bucketId[]=<uuid>)
if(params.bucketId) { maxLength = maxLength - 48; }
// if tagset parameters passed
if(tagset){
for (const tag in tagset) {
maxLength = maxLength - 10 - tagset[tag].key.length - tagset[tag].value.length;
}
}

// 48 chars for each objectId (&objectId[]=<uuid>)
const numObjs = Math.floor(maxLength / 48);

// for array of unique object ID's
const arrLength = uniqueIds.length;
if(arrLength > numObjs) {
const iterations = Math.ceil(arrLength / numObjs);
for (let i=0; i < iterations; i++ ) {

const ids = uniqueIds.slice(i * numObjs, ((i * numObjs) + numObjs ));

const group = (await objectService.searchObjects({
bucketId: params.bucketId ? [params.bucketId] : undefined,
objectId: ids,
tagset: tagset ? tagset.reduce((acc, cur) => ({ ...acc, [cur.key]: cur.value }), {}) : undefined,
deleteMarker: false,
latest: true
}, headers)).data;

response.concat(group);
}
}
// Added to allow deletion of objects before versioning implementation
// TODO: Verify if needed after versioning implemented
deleteMarker: false,
latest: true
}, headers)).data;

// Remove old values matching search parameters
const matches = (x: COMSObject) => (
Expand Down

0 comments on commit b7283cb

Please sign in to comment.