signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
91 lines • 3.34 kB
JavaScript
"use strict";
/**
* LatestValuesAccumulator - Accumulates Signal K delta values during backpressure,
* keeping only the latest value for each unique context:path:$source combination.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.accumulateLatestValue = accumulateLatestValue;
exports.buildFlushDeltas = buildFlushDeltas;
const server_api_1 = require("@signalk/server-api");
/**
* Accumulate latest value per context:path:$source during backpressure.
* Only keeps the most recent value for each unique combination, dropping intermediate updates.
*
* @param accumulator - Map to store accumulated values, keyed by context:path:$source
* @param delta - Signal K delta to accumulate
*/
function accumulateLatestValue(accumulator, delta) {
if (!delta.updates)
return;
for (const update of delta.updates) {
if (!(0, server_api_1.hasValues)(update))
continue;
for (const pv of update.values) {
const key = `${delta.context}:${pv.path}:${update.$source || 'unknown'}`;
accumulator.set(key, {
context: delta.context,
path: pv.path,
value: pv.value,
$source: update.$source,
timestamp: update.timestamp
});
}
}
}
/**
* Convert accumulated values to spec-compliant deltas.
* Groups values by context and $source for proper delta structure.
*
* @param accumulator - Map of accumulated values
* @param duration - How long backpressure was active in milliseconds
* @returns Array of deltas, one per context, with $backpressure indicator
*/
function buildFlushDeltas(accumulator, duration) {
if (accumulator.size === 0)
return [];
const countBefore = accumulator.size;
// Group by context
const byContext = new Map();
for (const [, item] of accumulator) {
if (!byContext.has(item.context)) {
byContext.set(item.context, new Map());
}
// Group by $source within context
const bySource = byContext.get(item.context);
const sourceKey = item.$source || 'unknown';
if (!bySource.has(sourceKey)) {
bySource.set(sourceKey, {
$source: item.$source,
timestamp: item.timestamp,
values: []
});
}
const update = bySource.get(sourceKey);
if ((0, server_api_1.hasValues)(update)) {
update.values.push({
path: item.path,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: item.value
});
// Use the most recent timestamp for this source
if (item.timestamp &&
(!update.timestamp || item.timestamp > update.timestamp)) {
update.timestamp = item.timestamp;
}
}
}
// Build one delta per context with backpressure indicator
const deltas = [];
for (const [context, bySourceTime] of byContext) {
deltas.push({
context,
updates: Array.from(bySourceTime.values()),
$backpressure: {
accumulated: countBefore,
duration
}
});
}
return deltas;
}
//# sourceMappingURL=LatestValuesAccumulator.js.map