feat: TR-069 Exchange Viewer - structured MongoDB storage with SSE streaming and sequence diagram UI
- MongoDB storage: cwmp_exchanges collection with indexes (deviceId+timestamp, deviceId+sequenceNumber unique, TTL 24h) - ExchangeStoreService: CWMP method extraction, per-device queue for ordering, retry logic, message cap (5000/device) - Exchange API: GET/DELETE/SSE stream endpoints with Last-Event-ID reconnection - CwmpLoggerMiddleware: dual-write (MongoDB + legacy files) with fire-and-forget - Frontend: SequenceViewer (CPE↔ACS lifelines, arrows, auto-scroll, virtual scroll) + InspectorPanel (formatted XML, copy, syntax highlighting) - Tr069Trace page: integrated new viewer with col-6/col-6 layout - DeviceDetail page: collapsible exchange section when device is traced - 14 property-based tests, 40+ unit tests, 5 integration tests - Health check includes index verification - Config: feature flags, SSE timeouts, retry policy
This commit is contained in:
1 parent
3fefbf6c40
commit
0c83a4ccb2
50 files changed
+15731
-43
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import { MongoMigration } from '../mongo_migrator.js'
|
||||
|
||||
export default class CreateCwmpExchangesCollection extends MongoMigration {
|
||||
async up(): Promise<void> {
|
||||
const exchanges = this.db.collection('cwmp_exchanges')
|
||||
|
||||
// Compound index for efficient retrieval by device, ordered by time
|
||||
await exchanges.createIndex(
|
||||
{ deviceId: 1, timestamp: 1 },
|
||||
{ name: 'idx_deviceId_timestamp' }
|
||||
)
|
||||
|
||||
// Unique index for atomic sequence numbering and Last-Event-ID queries
|
||||
await exchanges.createIndex(
|
||||
{ deviceId: 1, sequenceNumber: 1 },
|
||||
{ unique: true, name: 'idx_deviceId_sequenceNumber' }
|
||||
)
|
||||
|
||||
// TTL index to auto-remove exchanges older than 24h
|
||||
await exchanges.createIndex(
|
||||
{ createdAt: 1 },
|
||||
{ expireAfterSeconds: 86400, name: 'idx_createdAt_ttl' }
|
||||
)
|
||||
|
||||
// Create counters collection for atomic sequence number generation
|
||||
this.db.collection('cwmp_exchange_counters')
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
await this.db.dropCollection('cwmp_exchanges').catch(() => {})
|
||||
await this.db.dropCollection('cwmp_exchange_counters').catch(() => {})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user