Files
adam-acs/providers/mongodb_provider.ts
T
Kevin L'Hereec 0c83a4ccb2 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
2026-06-03 15:52:44 +02:00

65 lines
1.6 KiB
TypeScript

import type { ApplicationService } from '@adonisjs/core/types'
import { Db, MongoClient } from 'mongodb'
declare module '@adonisjs/core/types' {
interface ContainerBindings {
mongodb: Db
}
}
/**
* Singleton reference to the MongoDB Db instance.
* Set during provider boot, used synchronously by BaseModel.
*/
let dbInstance: Db | null = null
export function getMongoDb(): Db {
if (!dbInstance) {
throw new Error('MongoDB is not connected. Ensure MongodbProvider has booted.')
}
return dbInstance
}
export default class MongodbProvider {
private client: MongoClient | null = null
constructor(protected app: ApplicationService) {}
async boot() {
const config = await import('#config/database')
const { uri, dbName } = config.default
this.client = new MongoClient(uri, {
monitorCommands: true,
serverSelectionTimeoutMS: 5000,
})
await this.client.connect()
const db = this.client.db(dbName)
dbInstance = db
this.app.container.bindValue('mongodb', db)
// Verify cwmp_exchanges indexes after boot
const { verifyIndexesAtStartup } = await import('#services/exchange_index_checker')
await verifyIndexesAtStartup(db, {
warn: (msg: string) => console.warn(msg),
info: (msg: string) => console.info(msg),
}).catch((err) => {
console.warn(`[ExchangeIndexCheck] Failed to verify indexes: ${(err as Error).message}`)
})
}
async shutdown() {
if (this.client) {
try {
await this.client.close()
} catch {
// Connection may already be closed
}
this.client = null
dbInstance = null
}
}
}