/*!
* Convert JS SDK
* Version 1.0.0
* Copyright(c) 2020 Convert Insights, Inc
* License Apache-2.0
*/
import {objectDeepMerge} from './utils/object-utils';
import {DataStoreManagerInterface} from './interfaces/data-store-manager';
import {LogManagerInterface} from './interfaces/log-manager';
import {EventManagerInterface} from './interfaces/event-manager';
import {Config} from './types/Config';
import {SystemEvents} from './enums/system-events';
import {ERROR_MESSAGES} from './enums/dictionary';
const DEFAULT_BATCH_SIZE = 1;
const DEFAULT_RELEASE_INTERVAL = 5000;
/**
* Data Store wrapper
* @category Modules
* @constructor
* @implements {DataStoreManagerInterface}
*/
export class DataStoreManager implements DataStoreManagerInterface {
private _requestsQueue: Record<string, any>;
private _requestsQueueTimerID: number;
private _loggerManager: LogManagerInterface | null;
private _eventManager: EventManagerInterface | null;
readonly batchSize: number = DEFAULT_BATCH_SIZE;
readonly releaseInterval: number = DEFAULT_RELEASE_INTERVAL;
private _dataStore;
/**
* @param {Config=} config
* @param {Object=} dependencies
* @param {Object=} dependencies.dataStore
* @param {EventManagerInterface=} dependencies.eventManager
* @param {LogManagerInterface=} dependencies.loggerManager
*/
constructor(
config?: Config,
{
dataStore,
eventManager,
loggerManager
}: {
dataStore?;
eventManager?: EventManagerInterface;
loggerManager?: LogManagerInterface;
} = {}
) {
this._loggerManager = loggerManager;
this._eventManager = eventManager;
// TODO: Make this be configurable by config
this.batchSize =
// Number(objectDeepValue(config, 'events.batch_size')).valueOf() ||
DEFAULT_BATCH_SIZE;
this.releaseInterval =
// Number(objectDeepValue(config, 'events.release_interval')).valueOf() ||
DEFAULT_RELEASE_INTERVAL;
this.dataStore = dataStore;
this._requestsQueue = {};
}
set(key: string, data: any) {
try {
this.dataStore?.set?.(key, data);
} catch (error) {
this._loggerManager?.error?.('DataStoreManager.set()', {
error: error.message
});
}
}
get(key: string): any {
try {
return this.dataStore?.get?.(key);
} catch (error) {
this._loggerManager?.error?.('DataStoreManager.get()', {
error: error.message
});
}
return null;
}
enqueue(key: string, data: any) {
this._loggerManager?.trace?.('DataStoreManager.enqueue()', {
key: key,
data: data
});
const addData = {};
addData[key] = data;
this._requestsQueue = objectDeepMerge(this._requestsQueue, addData);
if (Object.keys(this._requestsQueue).length >= this.batchSize) {
this.releaseQueue('size');
} else {
if (Object.keys(this._requestsQueue).length === 1) {
this.startQueue();
}
}
}
releaseQueue(reason?: string): any {
this._loggerManager?.trace?.('DataStoreManager.releaseQueue()', {
reason: reason || ''
});
this.stopQueue();
for (const key in this._requestsQueue) {
this.set(key, this._requestsQueue[key]);
}
this._eventManager?.fire?.(SystemEvents.DATA_STORE_QUEUE_RELEASED, {
reason: reason || ''
});
}
stopQueue() {
clearTimeout(this._requestsQueueTimerID);
}
startQueue() {
this._requestsQueueTimerID = setTimeout(() => {
this.releaseQueue('timeout');
}, this.releaseInterval) as any;
}
/**
* dataStore setter
* @param {any=} dataStore
*/
set dataStore(dataStore: any) {
if (dataStore) {
if (this.isValidDataStore(dataStore)) {
this._dataStore = dataStore;
} else {
this._loggerManager?.error?.(ERROR_MESSAGES.DATA_STORE_NOT_VALID);
}
}
}
/**
* dataStore getter
*/
get dataStore() {
return this._dataStore;
}
/**
* Validates dataStore object
* @param {any=} dataStore
* @return {boolean}
*/
isValidDataStore(dataStore: any): boolean {
return (
dataStore &&
typeof dataStore === 'object' &&
typeof dataStore['get'] === 'function' &&
typeof dataStore['set'] === 'function'
);
}
}
Source