Skip to content

feat: support max kB in upload batching #600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/core/src/__tests__/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,20 @@ describe('#chunk', () => {
it('handles remainders', () => {
expect(chunk([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]);
});

it('handles max kb', () => {
const almost1KBString =
'heisxxohwswnetphtpnwyhluoeariblrgbksynoricexcoylnpmkymrgxmtuslveckeoulxqfwmemyxqvgyjnnclrmzcsacxkpdwzdthtudexkphsshjhlplvgryuqbqecgpbyussbgwuearvcmmrnkghcmcmynzxcswkghgrkhumeswvmhnhvymohluqooxmlbqdtxmeyikacyxvdkntrlwggoyrldmeaezowghoyukeeuaulxohknbbpyxpotonrtwfhoevysrfonevjtpjfywpptklmshzobtyklrahpkqnjifqtnxbeleeqxjacnphcomsdplxqmkcvnpxwbbmnmmzqvxmvpdrqaytlybmyghuckxnqlkgzptowgycanrenlgsgtwwbyudctiqmlszpzczfoglfoeuvdkublajngfmgstufgaroktarkeydqpmrgspuhbsqxqebzhycttsxkfcbgdqgctjgkrahoubqrvscdowafwfbysqerxqmzmakqibepyrjxjgcsnabjmovsgothxcawjsqzprxdnolyyhjfujgcxvniupmffqkhzknkzglazjflnnloazwslomxpegluqywyuvalysliziukrunfprejkojyihjjfcqdgsundoinipuzoxkqthslqgminkwcqglrjuhbqcirmuowdvizfsyubnllxxtjxqrctlzqmbfunxwzzbovogpvgrzeunvucaniqmqhwzcwqwzqvjaaeuajxgdhgitsekkowqejuouhaguudfkbyyivkayzsyoiymvavbabvtrgwmoadkvxxvgenttbohzngbzqiguficxkqvbxlrvkpycotawgalfdpmnmcfligffhivuzjtuxrwjjmzqcvbaocxfdmhnrcwhdmnpccikjvrskojxwnoiskacbivzfmbwyqfrhzjtdsjomzifswvaqdlorszbasmskosoullyyzpzjjzzkuvgoqwrzasqiroyaomrrxyqgzdigcwde';
expect(
chunk([almost1KBString, almost1KBString, almost1KBString], 5, 1)
).toEqual([[almost1KBString], [almost1KBString], [almost1KBString]]);
});

it('handles max kb and count at the same time', () => {
const about500bString =
'jfywukefmafvjroiisrqxudmmkqibiwaknaywfberhhtiymwrzcyoitzemqhwqamkccbgccsinagjddhhnijndpqyejfaztdbmcunmdaewraamfzssfwyzddttjkdpwehphowxrbpohntfohxvmufgoyovfguxlghvoisbmtufpyxqgqylufzhvavjylkhavobvmzyqbojniyjhkgssmnujyicucskiaenpeutaqbxsnzuinhnvfqbkmmoxzxhangjxhnuhskmldksucmridbyacvhycxpdgkkibypdphhwrkpmwivtgbvnfkilxmwvxbxuxklqstjltilksgaaxqmhdtmublkwzobrcoofiyygahosrmbmgftybdmdpyptsrntukfyczdusqlfgyexyojcfuloyyuepgkyhivmiqruqxbvixfotvwzjbamrqopsjiyftiuwmhbcfsvkrmjpmwthpwwszgjarargfpmxxkuwaofahreb';
expect(
chunk([about500bString, about500bString, about500bString], 2, 1)
).toEqual([[about500bString, about500bString], [about500bString]]);
});
});
4 changes: 3 additions & 1 deletion packages/core/src/plugins/SegmentDestination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DestinationMetadataEnrichment } from './DestinationMetadataEnrichment';
import { QueueFlushingPlugin } from './QueueFlushingPlugin';

const MAX_EVENTS_PER_BATCH = 100;
const MAX_PAYLOAD_SIZE_IN_KB = 500;
export const SEGMENT_DESTINATION_KEY = 'Segment.io';

export class SegmentDestination extends DestinationPlugin {
Expand All @@ -21,7 +22,8 @@ export class SegmentDestination extends DestinationPlugin {

const chunkedEvents: SegmentEvent[][] = chunk(
events,
this.analytics?.getConfig().maxBatchSize ?? MAX_EVENTS_PER_BATCH
this.analytics?.getConfig().maxBatchSize ?? MAX_EVENTS_PER_BATCH,
MAX_PAYLOAD_SIZE_IN_KB
);

let sentEvents: SegmentEvent[] = [];
Expand Down
41 changes: 33 additions & 8 deletions packages/core/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
import type { EventPlugin } from './plugin';
import type { Timeline } from './timeline';

export const chunk = (array: any[], size: number) => {
if (!array.length || !size) {
const sizeOf = (obj: unknown): number => {
const size = encodeURI(JSON.stringify(obj)).split(/%..|./).length - 1;
return size / 1024;
};

export const chunk = (array: any[], count: number, maxKB?: number) => {
if (!array.length || !count) {
return [];
}

let index = 0;
let resIndex = 0;
const result = new Array(Math.ceil(array.length / size));
let currentChunk = 0;
let rollingKBSize = 0;
const result: any[] = array.reduce(
(chunks: any[][], item: any, index: number) => {
if (maxKB !== undefined) {
rollingKBSize += sizeOf(item);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wont this be more accurate to do in plain bytes rather than kb? we wont have to do the / 1024 everytime we add bytes that way

// If we overflow chunk until the previous index, else keep going
if (rollingKBSize >= maxKB) {
chunks[++currentChunk] = [item];
return chunks;
}
}

if (index !== 0 && index % count === 0) {
chunks[++currentChunk] = [item];
} else {
if (chunks[currentChunk] === undefined) {
chunks[currentChunk] = [];
}
chunks[currentChunk].push(item);
}

return chunks;
},
[]
);

while (index < array.length) {
result[resIndex++] = array.slice(index, (index += size));
}
return result;
};

Expand Down