@hestia-earth/ui-components 0.43.33 → 0.43.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -7334,16 +7334,16 @@ const groupLog = (group, { logger, term, model, key, should_run, should_merge, r
|
|
|
7334
7334
|
};
|
|
7335
7335
|
const groupLogSubValue = (group, log, key) => {
|
|
7336
7336
|
const id = log[key];
|
|
7337
|
-
|
|
7338
|
-
group
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
}
|
|
7346
|
-
}
|
|
7337
|
+
group[id] = groupLog(group[id] || {}, log);
|
|
7338
|
+
return group;
|
|
7339
|
+
};
|
|
7340
|
+
// add each subValue to the same term/model on the parent group
|
|
7341
|
+
const linkSubValues = (group, subValues) => {
|
|
7342
|
+
subValues.forEach(([key, id]) => Object.entries(group[id]).forEach(([term, models]) => Object.keys(models).forEach(model => {
|
|
7343
|
+
if (typeof group?.[term]?.[model] === 'object') {
|
|
7344
|
+
group[term][model][key] = unique([...(group[term][model][key] || []), id]);
|
|
7345
|
+
}
|
|
7346
|
+
})));
|
|
7347
7347
|
return group;
|
|
7348
7348
|
};
|
|
7349
7349
|
const csvValue = (value) => (value || '').replace('[', '').replace(']', '');
|
|
@@ -7353,50 +7353,64 @@ const parseLogMessage = (message) => {
|
|
|
7353
7353
|
// Split on a comma (and optional space) ONLY if it's followed by "key="
|
|
7354
7354
|
// \w+ matches alphanumeric characters and underscores (standard log keys)
|
|
7355
7355
|
const pairs = data.message.split(/,\s*(?=\w+=)/);
|
|
7356
|
-
return
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
...prev,
|
|
7366
|
-
...(key && val ? { [key]: val } : {})
|
|
7367
|
-
};
|
|
7368
|
-
}, { logger: data.logger });
|
|
7356
|
+
return Object.fromEntries([
|
|
7357
|
+
['logger', data.logger],
|
|
7358
|
+
...pairs
|
|
7359
|
+
// Use indexOf instead of split('=') just in case your values ever contain an '='
|
|
7360
|
+
.map((parts) => [parts, parts.indexOf('=')])
|
|
7361
|
+
.filter(([, index]) => index !== -1)
|
|
7362
|
+
.map(([parts, index]) => [parts.substring(0, index).trim(), csvValue(parts.substring(index + 1).trim())])
|
|
7363
|
+
.filter(([key, value]) => key && value)
|
|
7364
|
+
]);
|
|
7369
7365
|
}
|
|
7370
7366
|
catch {
|
|
7371
7367
|
// make sure it works even if one log is malformed
|
|
7372
7368
|
return {};
|
|
7373
7369
|
}
|
|
7374
7370
|
};
|
|
7375
|
-
const
|
|
7376
|
-
.
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7371
|
+
const subValueOf = (log, groupBySubValue) => {
|
|
7372
|
+
const key = groupBySubValue && !log.cycle ? subValueKeys.find(v => !!log[v] && log[v] != noValue) : undefined;
|
|
7373
|
+
return key ? [key, log[key]] : undefined;
|
|
7374
|
+
};
|
|
7375
|
+
const groupLogsByModel = (data = '', groupBySubValue = false, groupByAnimal = false) => {
|
|
7376
|
+
const logs = data
|
|
7377
|
+
.trim()
|
|
7378
|
+
.split('\n')
|
|
7379
|
+
.map(parseLogMessage)
|
|
7380
|
+
.filter(v => [hasValue(v?.model), ['term', 'key', 'animalId'].some(k => hasValue(v?.[k]))].every(Boolean));
|
|
7381
|
+
const subValues = logs.map(log => subValueOf(log, groupBySubValue));
|
|
7382
|
+
const group = logs.reduce((prev, log, index) => subValues[index] ? groupLogSubValue(prev, log, subValues[index][0]) : groupLog(prev, log, groupByAnimal), {});
|
|
7383
|
+
const uniqueSubValues = [...new Map(subValues.filter(Boolean).map(v => [v.join('.'), v])).values()];
|
|
7384
|
+
return linkSubValues(group, uniqueSubValues);
|
|
7385
|
+
};
|
|
7386
7386
|
const logNodeFor = (node) => ({
|
|
7387
7387
|
'@type': node['@type'],
|
|
7388
7388
|
'@id': node['@id'],
|
|
7389
7389
|
dataState: node.aggregated && node['@type'] !== NodeType.ImpactAssessment ? DataState.original : DataState.recalculated,
|
|
7390
7390
|
dataVersion: node.dataVersion
|
|
7391
7391
|
});
|
|
7392
|
+
const logsCacheSize = 3;
|
|
7393
|
+
const logsCacheKey = ({ '@type': type, '@id': id, dataState, dataVersion }, groupByAnimal) => [type, id, dataState, dataVersion, groupByAnimal].join('/');
|
|
7394
|
+
/**
|
|
7395
|
+
* Store `value` as the most recent entry, dropping the oldest ones beyond `size`.
|
|
7396
|
+
*/
|
|
7397
|
+
const lruSet = (cache, key, value, size) => new Map([...[...cache].filter(([k]) => k !== key), [key, value]].slice(-size));
|
|
7392
7398
|
class NodeLogsModelsService {
|
|
7393
7399
|
constructor() {
|
|
7394
7400
|
this.nodeService = inject(HeNodeService);
|
|
7401
|
+
// parsing a large text log takes seconds, so keep the last few parsed logs for components showing the same node
|
|
7402
|
+
this.logsCache = new Map();
|
|
7395
7403
|
}
|
|
7396
7404
|
getNodeLogs$(node, groupByAnimal = false) {
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7405
|
+
const key = logsCacheKey(logNodeFor(node), groupByAnimal);
|
|
7406
|
+
const logs$ = this.logsCache.get(key) ?? this.fetchNodeLogs$(node, groupByAnimal, key);
|
|
7407
|
+
this.logsCache = lruSet(this.logsCache, key, logs$, logsCacheSize);
|
|
7408
|
+
return logs$;
|
|
7409
|
+
}
|
|
7410
|
+
fetchNodeLogs$(node, groupByAnimal, key) {
|
|
7411
|
+
return this.nodeService.getLog$(logNodeFor(node)).pipe(map(logs => logs ? groupLogsByModel(logs, node['@type'] === NodeType.Cycle, groupByAnimal) : {}),
|
|
7412
|
+
// a failed request also ends up empty: do not keep it, so the next component retries
|
|
7413
|
+
tap(logs => isEmpty(logs) && this.logsCache.delete(key)), shareReplay(1));
|
|
7400
7414
|
}
|
|
7401
7415
|
/**
|
|
7402
7416
|
* Fetch the new `.jlog` (JSON) recalculation logs, following the representation of the node.
|