Skip to content

Commit

Permalink
batchFn to eventMapping
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderkirtzel committed Jun 13, 2024
1 parent 9e7ce1c commit ec01784
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 27 deletions.
60 changes: 47 additions & 13 deletions packages/clients/walkerjs/src/__tests__/destination.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,49 +660,83 @@ describe('Destination', () => {
jest.useFakeTimers();
const mockBatch = jest.fn();

elb('walker run');
elb('walker destination', {
push: mockPush,
pushBatch: mockBatch,
config: {
mapping: {
// @TODO
product: {
click: { batch: 50 },
visible: { batch: 2000 },
},
promotion: {
click: { batch: 50 },
visible: { batch: 2000 },
},
'*': {
click: { batch: 50 },
visible: { batch: 2000 },
click: { batch: 2000 },
},
},
},
});
elb('walker run');

elb('foo visible');
elb('bar visible');
elb('foo click');
elb('foo important');
elb('product visible', { id: 1 });
elb('product visible', { id: 2 });
elb('promotion visible', { id: 3 });
elb('rage click', { id: 4 });
elb('rage click', { id: 5 });
elb('rage click', { id: 6 });
elb('product important', { id: 7 });

expect(mockPush).toHaveBeenCalledTimes(1); // Push important immediately
// Push important immediately
expect(mockPush).toHaveBeenCalledTimes(1);
expect(mockBatch).toHaveBeenCalledTimes(0);
jest.runAllTimers();

// Rage clicks
jest.advanceTimersByTime(50);
expect(mockBatch).toHaveBeenCalledTimes(1);

jest.clearAllMocks();
jest.advanceTimersByTime(2000);

expect(mockBatch).toHaveBeenCalledTimes(2);

// product visible
expect(mockBatch).toHaveBeenNthCalledWith(
1,
[
{
event: expect.objectContaining({
event: 'foo visible',
event: 'product visible',
data: { id: 1 },
}),
mapping: expect.objectContaining({ batch: 2000 }),
},
{
event: expect.objectContaining({
event: 'bar visible',
event: 'product visible',
data: { id: 2 },
}),
mapping: expect.objectContaining({ batch: 2000 }),
},
expect.objectContaining({
],
expect.anything(),
expect.anything(),
);

// promotion visible
expect(mockBatch).toHaveBeenNthCalledWith(
2,
[
{
event: expect.objectContaining({
event: 'foo click',
event: 'promotion visible',
}),
}),
mapping: expect.objectContaining({ batch: 2000 }),
},
],
expect.anything(),
expect.anything(),
Expand Down
31 changes: 20 additions & 11 deletions packages/clients/walkerjs/src/lib/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,21 +158,30 @@ export function pushToDestination(

// Debounce the event if needed
const batch = mappingEvent?.batch;
if (batch && destination.pushBatch) {
destination.batch = destination.batch || [];
destination.batch.push({ event, mapping: mappingEvent });
if (mappingEvent && batch && destination.pushBatch) {
mappingEvent.name;
mappingEvent.events = mappingEvent.events || [];
mappingEvent.events.push({ event, mapping: mappingEvent });

destination.batchFn =
destination.batchFn ||
mappingEvent.batchFn =
mappingEvent.batchFn ||
debounce((destination, instance) => {
useHooks(destination.pushBatch!, 'DestinationPush', instance.hooks)(
destination.batch || [],
destination.config,
instance,
);
// Create a copy of the events to prevent mutation
const events = [...(mappingEvent.events || [])];

if (events.length) {
// Reset the batched events queue
mappingEvent.events = [];

useHooks(destination.pushBatch!, 'DestinationPush', instance.hooks)(
events,
destination.config,
instance,
);
}
}, batch);

destination.batchFn!(destination, instance);
mappingEvent.batchFn(destination, instance);
} else {
// It's time to go to the destination's side now
useHooks(destination.push, 'DestinationPush', instance.hooks)(
Expand Down
5 changes: 3 additions & 2 deletions packages/clients/walkerjs/src/types/destination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export interface Destination<Custom = never, EventCustom = never>
init?: (config: Config<Custom, EventCustom>) => void | boolean;
push: Push<Custom, EventCustom>;
pushBatch?: PushBatch<Custom, EventCustom>;
batchFn?: (destination: Destination, instance: WalkerOS.Instance) => void;
}

export type DestinationInit = Partial<Omit<Destination, 'push'>> &
Expand All @@ -34,4 +33,6 @@ export interface Mapping<EventCustom = unknown>
extends WalkerOSDestination.Mapping<EventCustom> {}

export interface EventConfig<EventCustom = never>
extends WalkerOSDestination.EventConfig<EventCustom> {}
extends WalkerOSDestination.EventConfig<EventCustom> {
batchFn?: (destination: Destination, instance: WalkerOS.Instance) => void;
}
2 changes: 1 addition & 1 deletion packages/types/src/destination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Handler, On, WalkerOS } from '.';

export interface Destination<Custom = unknown, EventCustom = unknown> {
config: Config<Custom, EventCustom>; // Configuration settings for the destination
batch?: Batch<EventCustom>; // Batch of events to be processed
queue?: Queue; // Non processed events yet and reset with each new run
type?: string; // The type of the destination
}
Expand Down Expand Up @@ -38,6 +37,7 @@ export type Meta = {

export interface EventConfig<EventCustom = unknown> {
batch?: number; // Bundle events for batch processing
events?: Batch<EventCustom>; // Batch of events to be processed
consent?: WalkerOS.Consent; // Required consent states to init and push events
custom?: EventCustom; // Arbitrary but protected configurations for custom event config
ignore?: boolean; // Choose to no process an event when set to true
Expand Down

0 comments on commit ec01784

Please sign in to comment.