UNPKG

@openade/pel

Version:

Punto di Elaborazione (Elaboration Point) - Server library for managing PEMs and communicating with ADE

131 lines 5.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AnomalyManager = exports.AnomalyType = void 0; var AnomalyType; (function (AnomalyType) { AnomalyType["CONNECTION_ERROR"] = "ERR_CONN"; AnomalyType["PEM_BLOCKED"] = "ERR_BLOCK"; AnomalyType["INTEGRITY_ERROR"] = "ERR_INTEG"; AnomalyType["VALIDATION_ERROR"] = "ERR_VALID"; AnomalyType["MISSING_JOURNAL"] = "ERR_MISS_J"; AnomalyType["MISSING_DOCUMENTS"] = "ERR_MISS_DC"; })(AnomalyType || (exports.AnomalyType = AnomalyType = {})); class AnomalyManager { constructor(config) { this.pendingAnomalies = new Map(); this.config = { autoTransmit: true, batchSize: 10, ...config, }; } async reportAnomaly(anomaly) { const anomalyId = this.generateAnomalyId(anomaly); console.warn('Anomaly reported:', { id: anomalyId, type: anomaly.type, pemId: anomaly.pemId, details: anomaly.details, }); const path = `anomalies/${anomaly.pemId}/${anomaly.timestamp.replace(/[:.]/g, '-')}.json`; await this.config.storage.store(path, new TextEncoder().encode(JSON.stringify(anomaly, null, 2))); this.pendingAnomalies.set(anomalyId, anomaly); if (this.config.autoTransmit && this.config.adeClient) { await this.transmitPendingAnomalies(); } } async reportConnectionError(taxpayerFiscalCode, pemId, pemLocation, startedAt, operationsWithoutNetwork, networkRestoredAt) { await this.reportAnomaly({ type: AnomalyType.CONNECTION_ERROR, taxpayerFiscalCode, pemId, pemLocation, details: `PEM-PEL connection failure. ${operationsWithoutNetwork} operations registered without network.`, timestamp: new Date().toISOString(), startedAt, resolvedAt: networkRestoredAt, metadata: { operationsWithoutNetwork, networkRestoredAt, }, }); } async reportPEMBlocked(taxpayerFiscalCode, pemId, pemLocation, blockedAt, operationsCount) { await this.reportAnomaly({ type: AnomalyType.PEM_BLOCKED, taxpayerFiscalCode, pemId, pemLocation, details: `PEM blocked due to transmission threshold exceeded. ${operationsCount} operations not transmitted.`, timestamp: blockedAt, startedAt: blockedAt, metadata: { operationsWithoutNetwork: operationsCount, }, }); } async reportIntegrityError(taxpayerFiscalCode, pemId, pemLocation, expectedHash, actualHash, details) { await this.reportAnomaly({ type: AnomalyType.INTEGRITY_ERROR, taxpayerFiscalCode, pemId, pemLocation, details: `Hash chain integrity error: ${details}`, timestamp: new Date().toISOString(), metadata: { expectedHash, actualHash, }, }); } async transmitPendingAnomalies() { if (this.pendingAnomalies.size === 0) { return; } if (!this.config.adeClient) { console.warn('ADE client not configured, cannot transmit anomalies'); return; } const anomalies = Array.from(this.pendingAnomalies.values()); const batchSize = this.config.batchSize || 10; console.log(`Transmitting ${anomalies.length} anomalies to ADE...`); for (let i = 0; i < anomalies.length; i += batchSize) { const batch = anomalies.slice(i, i + batchSize); try { const result = await this.config.adeClient.trasmissioneAnomalie(batch); console.log(`✓ Transmitted batch ${Math.floor(i / batchSize) + 1} (${batch.length} anomalies) - ${result.success ? 'SUCCESS' : 'FAILED'}`); for (const anomaly of batch) { const id = this.generateAnomalyId(anomaly); this.pendingAnomalies.delete(id); } } catch (error) { console.error(`Error transmitting anomaly batch:`, error); } } console.log(`Anomaly transmission complete. ${this.pendingAnomalies.size} remaining in queue.`); } getPendingCount() { return this.pendingAnomalies.size; } getPendingAnomalies() { return Array.from(this.pendingAnomalies.values()); } clearResolved() { const before = this.pendingAnomalies.size; for (const [id, anomaly] of this.pendingAnomalies.entries()) { if (anomaly.resolvedAt) { this.pendingAnomalies.delete(id); } } const cleared = before - this.pendingAnomalies.size; if (cleared > 0) { console.log(`Cleared ${cleared} resolved anomalies`); } } generateAnomalyId(anomaly) { return `${anomaly.type}_${anomaly.pemId}_${anomaly.timestamp}`; } } exports.AnomalyManager = AnomalyManager; //# sourceMappingURL=anomaly.manager.js.map