amberflo-metering-typescript
Version:
Amberflo metering client for TypeScript
114 lines • 4.81 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoIngestClient = void 0;
const ingestOptions_1 = require("../model/ingestOptions");
const ingestApiClient_1 = require("./ingestApiClient");
const uuid_1 = require("uuid");
class AutoIngestClient {
constructor(apiKey, ingestOptions, debug = false) {
this.debug = false;
this.apiKey = apiKey;
this.queue = [];
this.promises = new Map();
//options
const options = ingestOptions || new ingestOptions_1.IngestOptions();
this.batchSize = (options.batchSize) ? Math.max(options.batchSize, 1) : 100;
this.frequencyMillis = (options.frequencyMillis) ? Math.max(options.frequencyMillis, 1) : 1000;
this.signature = '[amberflo-metering AsyncIngestClient]:';
this.debug = debug;
}
start() {
this.apiClient = new ingestApiClient_1.IngestApiClient(this.apiKey, this.debug);
console.log(`${this.signature} start client with batch size: ${this.batchSize} frequency in ms ${this.frequencyMillis} debug ${this.debug}`);
this.timer = setTimeout(this.dequeueTimer.bind(this), this.frequencyMillis);
}
ingestMeter(meter) {
if (this.debug) {
console.log(this.signature, 'adding meter message to queue: ', meter);
}
this.queue.push(meter);
if (this.queue.length >= this.batchSize) {
if (this.debug) {
console.log(this.signature, 'queue exceeded batch size, so flushing before timer');
}
this.dequeue();
}
}
done(requestId) {
if (this.debug) {
console.log(new Date(), this.signature, 'request completed:', requestId);
}
this.promises.delete(requestId);
}
dequeue() {
if (this.debug) {
console.log(new Date(), this.signature, 'dequeuing ...');
}
if (this.queue.length < 1) {
if (this.debug) {
console.log(new Date(), this.signature, 'no records in the queue to flush');
}
return;
}
const snapshot = this.queue.splice(0, this.queue.length);
let iteration = 0;
while (snapshot.length > 0) {
if (this.debug) {
console.log(this.signature, 'call ingest API, iteration: ', iteration++);
}
const items = snapshot.splice(0, this.batchSize);
if (this.debug) {
console.log(new Date(), this.signature, 'spliced items and payload:', items);
}
//make asynchronous call
const requestId = (0, uuid_1.v1)();
if (this.debug) {
console.log(new Date(), this.signature, 'starting request', requestId);
}
const promise = this.apiClient.post(items, requestId, () => { this.done(requestId); });
this.promises.set(requestId, promise);
}
}
dequeueTimer() {
//re-schedule
clearTimeout(this.timer);
this.timer = setTimeout(this.dequeueTimer.bind(this), this.frequencyMillis);
this.dequeue();
}
flush() {
return __awaiter(this, void 0, void 0, function* () {
this.dequeue();
if (this.debug) {
console.log(new Date(), this.signature, 'waiting for all requests to complete');
}
return Promise
.all(this.promises.values())
.then(() => {
if (this.debug) {
console.log(new Date(), this.signature, 'all pending requests completed');
}
})
.catch(error => {
console.log(new Date(), this.signature, 'waiting for all promises errored', error);
});
});
}
shutdown() {
if (this.debug) {
console.log(new Date(), this.signature, 'shutting down the client');
}
clearTimeout(this.timer);
return this.flush();
}
}
exports.AutoIngestClient = AutoIngestClient;
//# sourceMappingURL=autoIngestClient.js.map