@@ -45,58 +45,6 @@ export class WebsocketCronService {
4545 private readonly apiConfigService : ApiConfigService ,
4646 ) { }
4747
48- @Cron ( '*/1 * * * * *' )
49- handleWebsocketMetrics ( ) {
50- const connectedClients = this . server . sockets . sockets . size ?? 0 ;
51-
52- // Efficient unique-listener counts per topic
53- const adapter = this . server . sockets . adapter as any ;
54- const sids : Map < string , Set < string > > = adapter ?. sids ?? new Map ( ) ;
55-
56- const topicPrefixes : Array < { key : string ; prefix ?: string ; room ?: string } > = [
57- { key : 'tx' , prefix : TransactionsGateway . keyPrefix } ,
58- { key : 'customTx' , prefix : TransactionsCustomGateway . keyPrefix } ,
59- { key : 'events' , prefix : EventsGateway . keyPrefix } ,
60- { key : 'customEvents' , prefix : EventsCustomGateway . keyPrefix } ,
61- { key : 'blocks' , prefix : BlocksGateway . keyPrefix } ,
62- { key : 'pool' , prefix : PoolGateway . keyPrefix } ,
63- { key : 'stats' , room : 'statsRoom' } ,
64- ] ;
65-
66- const topics : Record < string , number > = { } ;
67- for ( const { key } of topicPrefixes ) topics [ key ] = 0 ;
68-
69- // Count unique sockets per prefix-based topic by scanning socket -> rooms map once
70- if ( sids && sids . size > 0 ) {
71- for ( const [ , rooms ] of sids ) {
72- // Track whether this socket has been counted for a given topic key
73- const matched : Record < string , boolean > = { } ;
74-
75- for ( const roomName of rooms ) {
76- for ( const { key, prefix } of topicPrefixes ) {
77- if ( ! prefix || matched [ key ] ) continue ;
78- if ( roomName . startsWith ( prefix ) ) {
79- topics [ key ] += 1 ;
80- matched [ key ] = true ;
81- }
82- }
83- }
84- }
85- }
86-
87- // Handle exact-room topics (like statsRoom) directly from rooms map
88- const rooms : Map < string , Set < string > > = adapter ?. rooms ?? new Map ( ) ;
89- const statsRoomSet = rooms . get ( 'statsRoom' ) ;
90- if ( statsRoomSet ) {
91- topics [ 'stats' ] = statsRoomSet . size ;
92- }
93-
94- this . eventEmitter . emit ( MetricsEvents . SetWebsocketMetrics , {
95- connectedClients,
96- topics,
97- } ) ;
98- }
99-
10048 @Cron ( '*/6 * * * * *' )
10149 @Lock ( { name : 'Push transactions to subscribers' , verbose : true } )
10250 async handleTransactionsUpdate ( ) {
@@ -165,6 +113,59 @@ export class WebsocketCronService {
165113 ) ;
166114 }
167115
116+ @Cron ( '*/10 * * * * *' )
117+ @Lock ( { name : 'Push websocket subscriptions metrics' , verbose : true } )
118+ handleWebsocketMetrics ( ) {
119+ const connectedClients = this . server . sockets . sockets . size ?? 0 ;
120+
121+ // Efficient unique-listener counts per topic
122+ const adapter = this . server . sockets . adapter as any ;
123+ const sids : Map < string , Set < string > > = adapter ?. sids ?? new Map ( ) ;
124+
125+ const topicPrefixes : Array < { key : string ; prefix ?: string ; room ?: string } > = [
126+ { key : 'tx' , prefix : TransactionsGateway . keyPrefix } ,
127+ { key : 'customTx' , prefix : TransactionsCustomGateway . keyPrefix } ,
128+ { key : 'events' , prefix : EventsGateway . keyPrefix } ,
129+ { key : 'customEvents' , prefix : EventsCustomGateway . keyPrefix } ,
130+ { key : 'blocks' , prefix : BlocksGateway . keyPrefix } ,
131+ { key : 'pool' , prefix : PoolGateway . keyPrefix } ,
132+ { key : 'stats' , room : 'statsRoom' } ,
133+ ] ;
134+
135+ const topics : Record < string , number > = { } ;
136+ for ( const { key } of topicPrefixes ) topics [ key ] = 0 ;
137+
138+ // Count unique sockets per prefix-based topic by scanning socket -> rooms map once
139+ if ( sids && sids . size > 0 ) {
140+ for ( const [ , rooms ] of sids ) {
141+ // Track whether this socket has been counted for a given topic key
142+ const matched : Record < string , boolean > = { } ;
143+
144+ for ( const roomName of rooms ) {
145+ for ( const { key, prefix } of topicPrefixes ) {
146+ if ( ! prefix || matched [ key ] ) continue ;
147+ if ( roomName . startsWith ( prefix ) ) {
148+ topics [ key ] += 1 ;
149+ matched [ key ] = true ;
150+ }
151+ }
152+ }
153+ }
154+ }
155+
156+ // Handle exact-room topics (like statsRoom) directly from rooms map
157+ const rooms : Map < string , Set < string > > = adapter ?. rooms ?? new Map ( ) ;
158+ const statsRoomSet = rooms . get ( 'statsRoom' ) ;
159+ if ( statsRoomSet ) {
160+ topics [ 'stats' ] = statsRoomSet . size ;
161+ }
162+
163+ this . eventEmitter . emit ( MetricsEvents . SetWebsocketMetrics , {
164+ connectedClients,
165+ topics,
166+ } ) ;
167+ }
168+
168169 private async getLatestRoundOnChainData ( ) {
169170 const rounds = await this . roundService . getRounds ( new RoundFilter ( { size : 1 } ) ) ;
170171 return rounds [ 0 ] ;
0 commit comments