import { syncTaskFactory } from '../syncTask'; import { ISyncTask } from '../types'; import { IRecorderCacheSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; import { SUBMITTERS_PUSH, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY } from '../../logger/constants'; import { IResponse } from '../../services/types'; /** * Base function to create submitters, such as ImpressionsSubmitter and EventsSubmitter */ export function submitterFactory( log: ILogger, postClient: (body: string) => Promise, sourceCache: IRecorderCacheSync, postRate: number, fromCacheToPayload?: (cacheData: T) => any, maxRetries: number = 0, debugLogs?: boolean // true for telemetry submitters ): ISyncTask<[], void> { const dataName = sourceCache.name; let retries = 0; let data: any; function postData(): Promise { if (sourceCache.isEmpty() && !data) return Promise.resolve(); data = sourceCache.pop(data); const dataCountMessage = typeof data.length === 'number' ? `${data.length} ${dataName}` : dataName; log[debugLogs ? 'debug' : 'info'](SUBMITTERS_PUSH, [dataCountMessage]); const jsonPayload = JSON.stringify(fromCacheToPayload ? fromCacheToPayload(data) : data); if (!maxRetries) data = undefined; return postClient(jsonPayload).then(() => { retries = 0; data = undefined; }).catch(err => { if (!maxRetries) { log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]); } else if (retries === maxRetries) { retries = 0; data = undefined; log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]); } else { retries++; log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]); } }); } return syncTaskFactory(log, postData, postRate, dataName + ' submitter'); } /** * Decorates a provided submitter with a first execution window */ export function firstPushWindowDecorator(submitter: ISyncTask, firstPushWindow: number) { let running = false; let stopEventPublisherTimeout: ReturnType; const originalStart = submitter.start; submitter.start = () => { running = true; stopEventPublisherTimeout = setTimeout(originalStart, firstPushWindow); }; const originalStop = submitter.stop; submitter.stop = () => { running = false; clearTimeout(stopEventPublisherTimeout); originalStop(); }; submitter.isRunning = () => { return running; }; return submitter; }