surveillance.gateway.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /**
  2. * Lego 09 — Surveillance Gateway
  3. * Lego 11 — Socket Event Schema: monitor:subscribe / monitor:data
  4. *
  5. * Registers the Socket.io namespace on port 3000 (shared server).
  6. * On client subscribe → sends the latest snapshot immediately.
  7. * Every 500ms tick → SurveillanceService calls back → we broadcast to all.
  8. */
  9. import {
  10. WebSocketGateway,
  11. WebSocketServer,
  12. SubscribeMessage,
  13. OnGatewayInit,
  14. OnGatewayConnection,
  15. OnGatewayDisconnect,
  16. } from '@nestjs/websockets';
  17. import { Logger, OnModuleInit } from '@nestjs/common';
  18. import { Server, Socket } from 'socket.io';
  19. import { SurveillanceService, MonitorPayload } from './surveillance.service';
  20. @WebSocketGateway({
  21. cors: { origin: '*' }, // Angular dev server on any port
  22. namespace: '/monitor',
  23. })
  24. export class SurveillanceGateway
  25. implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect, OnModuleInit
  26. {
  27. @WebSocketServer()
  28. private server!: Server;
  29. private readonly logger = new Logger(SurveillanceGateway.name);
  30. constructor(private readonly surveillanceService: SurveillanceService) {}
  31. // ─── Lifecycle ─────────────────────────────────────────────────────────────
  32. onModuleInit() {
  33. // Wire the service callback → broadcasts to all connected clients
  34. this.surveillanceService.registerMetricsCallback((metrics: MonitorPayload[]) => {
  35. this.broadcast(metrics);
  36. });
  37. }
  38. afterInit(server: Server) {
  39. this.logger.log('🔌 SurveillanceGateway initialized on /monitor namespace');
  40. }
  41. handleConnection(client: Socket) {
  42. this.logger.log(`📡 Client connected: ${client.id}`);
  43. // Immediately push the current snapshot so the UI isn't blank on load
  44. const snapshot = this.surveillanceService.getLatestMetrics();
  45. if (snapshot.length > 0) {
  46. client.emit('monitor:data', snapshot);
  47. }
  48. }
  49. handleDisconnect(client: Socket) {
  50. this.logger.log(`🔌 Client disconnected: ${client.id}`);
  51. }
  52. // ─── Event Handlers ────────────────────────────────────────────────────────
  53. /**
  54. * Lego 11 — monitor:subscribe
  55. * UI emits this to start (or re-confirm) the resource tracking stream.
  56. * We acknowledge and immediately push the latest snapshot.
  57. */
  58. @SubscribeMessage('monitor:subscribe')
  59. handleSubscribe(client: Socket) {
  60. this.logger.log(`🟢 monitor:subscribe from ${client.id}`);
  61. const snapshot = this.surveillanceService.getLatestMetrics();
  62. client.emit('monitor:data', snapshot);
  63. return { event: 'monitor:subscribed', data: { ok: true } };
  64. }
  65. // ─── Broadcast ─────────────────────────────────────────────────────────────
  66. private broadcast(metrics: MonitorPayload[]) {
  67. if (this.server) {
  68. this.server.emit('monitor:data', metrics);
  69. }
  70. }
  71. }