import { groupBy, forOwn } from '../../utils/lang'; import SplitIO from '../../../types/splitio'; import { submitterFactory } from './submitter'; import { ImpressionsPayload } from './types'; import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants'; import { ISdkFactoryContextSync } from '../../sdkFactory/types'; /** * Converts `impressions` data from cache into request payload. */ export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.ImpressionDTO[]): ImpressionsPayload { let groupedByFeature = groupBy(data, 'feature'); let dto: ImpressionsPayload = []; forOwn(groupedByFeature, (value, name) => { dto.push({ f: name, // Test Name i: value.map(entry => { // Key Impressions const keyImpression = { k: entry.keyName, // Key t: entry.treatment, // Treatment m: entry.time, // Timestamp c: entry.changeNumber, // ChangeNumber r: sendLabels ? entry.label : undefined, // Rule b: entry.bucketingKey, // Bucketing Key pt: entry.pt, // Previous time properties: entry.properties // Properties }; return keyImpression; }) }); }); return dto; } /** * Submitter that periodically posts impressions data */ export function impressionsSubmitterFactory(params: ISdkFactoryContextSync) { const { settings: { log, scheduler: { impressionsRefreshRate }, core: { labelsEnabled } }, splitApi: { postTestImpressionsBulk }, storage: { impressions } } = params; // retry impressions only once. const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled), 1); // register impressions submitter to be executed when impressions cache is full impressions.setOnFullQueueCb(() => { if (syncTask.isRunning()) { log.info(SUBMITTERS_PUSH_FULL_QUEUE, [impressions.name]); syncTask.execute(); } // If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data. // Data will be sent when submitter is resumed. }); return syncTask; }