@resolveio/server-lib 20.7.29 → 20.7.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/managers/method.manager.d.ts +2 -1
- package/managers/method.manager.js +1 -1
- package/managers/method.manager.js.map +1 -1
- package/managers/subscription.manager.js.map +1 -1
- package/managers/worker-dispatcher.manager.d.ts +50 -0
- package/managers/worker-dispatcher.manager.js +2 -0
- package/managers/worker-dispatcher.manager.js.map +1 -0
- package/managers/worker-server.manager.d.ts +13 -0
- package/managers/worker-server.manager.js +2 -0
- package/managers/worker-server.manager.js.map +1 -0
- package/models/method.model.d.ts +1 -0
- package/models/server-message.model.d.ts +27 -0
- package/models/{server-response.model.js → server-message.model.js} +1 -1
- package/models/server-message.model.js.map +1 -0
- package/package.json +1 -1
- package/public_api.d.ts +1 -1
- package/public_api.js +1 -1
- package/public_api.js.map +1 -1
- package/server-app.d.ts +6 -24
- package/server-app.js +1 -1
- package/server-app.js.map +1 -1
- package/models/server-response.model.d.ts +0 -5
- package/models/server-response.model.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/managers/subscription.manager.ts"],"names":["NodeCache","require","os_1","flag_collection_1","logged_in_users_collection_1","app_status_1","cron_jobs_1","files_1","flags_1","flags_update_1","logs_1","notifications_1","report_builder_dashboard_builders_1","report_builder_libraries_1","report_builder_reports_1","super_admin_1","user_groups_1","user_guides_1","resolveio_server_app_1","common_1","numCPUs","cpus","length","v8","SubscriptionManager","this","_publications","_subscriptions","_loggedInUsers","_mongoQueue","_mongoQueueId","_cacheId","_heapSize","getHeapStatistics","_enableDebug","_debugOplogCollections","_debugOplogHits","_debugSubCollections","_debugSubHits","_debugUnSubHits","_debugUnSubAllHits","_debugMongoQueueHits","_debugMongoQueueCollections","_debugSendQueueHits","_debugRemoveCacheHits","_oplogRetryCount","latencyBuffer","Map","LATENCY_UPDATE_INTERVAL","LATENCY_UPDATE_THRESHOLD_MS","_invalidationDebounceTimers","_invalidationPendingTimestamps","DEBOUNCE_DELAY","MAX_WAIT_TIME","create","wss","serverConfig","monitorManagerFunction","_this","subscriptionManager","setImmediate","__awaiter","initialize","_a","sent","prototype","_websocketManager","ResolveIOServer","getMainServer","getWebSocketManager","_monitorManagerFunction","_nodeCache","stdTTL","checkperiod","setInterval","flushThrottledLatencyUpdates","_wss","loadSuperAdminPublications","loadAppStatusPublications","loadLogPublications","loadFilePublications","loadCronJobPublications","loadFlagsUpdatePublications","loadFlagsPublications","loadNotificationPublications","loadReportBuilderReportPublications","loadReportBuilderLibraryPublications","loadUserGroupPublications","loadUserGuidePublications","loadReportBuilderDashboardBuilderPublications","tailOpLog","getEnableDebug","console","log","Date","JSON","stringify","sort","a","b","collection","localeCompare","publication","type","LoggedInUsers","find","_b","userCopy","deepCopy","i","loggedInUser","date","now","getTime","this_1","getWebSocket","id_ws","unsubscribeAll","_c","forEach","sub","j","clients","id_socket","splice","deleteOne","_id","findIndex","client","this_2","some","Flags","findOne","flag","value","setCacheLimit","process","env","IS_WORKERS_ENABLED","_heapLimit","invalidatePubsCache","debounceKey","firstInvalidationTime","get","set","has","clearTimeout","delete","_executeInvalidation","setTimeout","getMongoManager","invalidateQueryCache","collSubs","filter","collections","includes","collSubs_1","__values","collSubs_1_1","next","running","runAgain","user_specific","e_1","ws","readyState","OPEN","sendDataToOneWithRetry","messageId","_f","sendDataToAllWithRetry","delay","ms","Promise","resolve","sendDataToAll","sendDataToOne","publications","method","Object","assign","loggedInLatency","existingEntry","newLatency","lastUpdate","Math","abs","latency","size","updates","Array","from","entries","map","__read","updateOne","update","$set","bulkWrite","clear","error","error_1","subscribe","messageRoute","messageDate","subscriptionData","hits","push","pub","check","_schema","valObj","valKeys","keys","rootKeys","validate","errors","urlData","split","urlModule_1","urlNext","otherRouteSubs","startsWith","otherSub","unsubscribe","id_user","getPublicationCollections","cacheId","processSubscription","createLoggedInUser","user","objectIdHexString","__v","insertOne","Error","indexOf","userSubs","removeWebSocket","getActiveSubscriptions","resumeToken","_oplog$","closed","removeAllListeners","close","exit","pipeline","$match","$and","ns.coll","$nin","$not","lastResumeToken_1","getMainDB","watch","resumeAfter","on","doc","ns","coll","operationType","getMethodManager","callMethod","call","documentKey","NODE_APP_INSTANCE","IS_WORKER_INSTANCE","WORKER_INDEX","cacheData","parse","dateReviver","serverRes","hasError","data","sendWS","del","monitor","startMonitorFunction","function","apply","__spreadArray","res","err_1","sendEmail","finishMonitorFunction","subIndex","_g","res_1","_l","done","getBinarySize","endsWith","_m","_d","nodeCacheSize","getStats","vsize","deleteCount","subArr","zz","_e","err_2","send","exports"],"mappings":"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","file":"subscription.manager.js","sourcesContent":["import { ChangeStream, ChangeStreamDeleteDocument, ChangeStreamInsertDocument, ChangeStreamReplaceDocument, ChangeStreamUpdateDocument, ResumeToken } from 'mongodb';\nimport * as NodeCache from 'node-cache';\nimport { cpus } from 'os';\nimport * as WebSocket from 'ws';\nimport { Flags } from '../collections/flag.collection';\nimport { LoggedInUsers } from '../collections/logged-in-users.collection';\nimport { LoggedInUserModel } from '../models/logged-in-users.model';\nimport { ServerResponseModel } from '../models/server-response.model';\nimport { ActiveSubscriptionModel, SubscriptionModel } from '../models/subscription.model';\nimport { loadAppStatusPublications } from '../publications/app-status';\nimport { loadCronJobPublications } from '../publications/cron-jobs';\nimport { loadFilePublications } from '../publications/files';\nimport { loadFlagsPublications } from '../publications/flags';\nimport { loadFlagsUpdatePublications } from '../publications/flags-update';\nimport { loadLogPublications } from '../publications/logs';\nimport { loadNotificationPublications } from '../publications/notifications';\nimport { loadReportBuilderDashboardBuilderPublications } from '../publications/report-builder-dashboard-builders';\nimport { loadReportBuilderLibraryPublications } from '../publications/report-builder-libraries';\nimport { loadReportBuilderReportPublications } from '../publications/report-builder-reports';\nimport { loadSuperAdminPublications } from '../publications/super-admin';\nimport { loadUserGroupPublications } from '../publications/user-groups';\nimport { loadUserGuidePublications } from '../publications/user-guides';\nimport { ResolveIOServer } from '../resolveio-server-app';\nimport { dateReviver, deepCopy, getBinarySize, objectIdHexString } from '../util/common';\nimport { MonitorManagerFunction } from './monitor.manager';\nimport { WebSocketManager } from './websocket.manager';\nconst numCPUs = cpus().length;\nconst v8 = require('v8');\n\n// Performance Dependencies\n// import * as path from 'path';\n// import { Worker } from 'worker_threads';\n\ninterface MongoQueueModel {\n\t_id: number,\n\ttype: string;\n\tcollection: string;\n\tsubscription: ActiveSubscriptionModel;\n\trunning: boolean;\n\trun_again: boolean;\n}\n\n// interface CurrentPerformanceMonitor {\n// \t_id: number;\n// \tfunction: string;\n// \tpublication: string;\n// \tsubscriptionData: any[];\n// \tdate_start: Date;\n// \tdate_end: Date;\n// \tduration: number;\n// \tresult: string;\n// }\n\nexport class SubscriptionManager {\n\tprivate _websocketManager: WebSocketManager;\n\tprivate _publications: SubscriptionModel = {};\n\tprivate _subscriptions: ActiveSubscriptionModel[] = [];\n\tprivate _wss: WebSocket.Server;\n\tprivate _loggedInUsers: LoggedInUserModel[] = [];\n\n\tprivate _mongoQueue: MongoQueueModel[] = [];\n\tprivate _mongoQueueId = 0;\n\t\n\tprivate _oplog$: ChangeStream;\n\n\tprivate _nodeCache;\n\tprivate _cacheId = 1;\n\n\tprivate _heapSize = v8.getHeapStatistics() / numCPUs;\n\tprivate _heapLimit: number;\n\n\tprivate serverConfig;\n\n\tprivate _monitorManagerFunction: MonitorManagerFunction;\n\n\tprivate _enableDebug = false;\n\tprivate _debugOplogCollections = [];\n\tprivate _debugOplogHits = 0;\n\tprivate _debugSubCollections = [];\n\tprivate _debugSubHits = 0;\n\tprivate _debugUnSubHits = 0;\n\tprivate _debugUnSubAllHits = 0;\n\tprivate _debugMongoQueueHits = 0;\n\tprivate _debugMongoQueueCollections = [];\n\tprivate _debugSendQueueHits = 0;\n\tprivate _debugRemoveCacheHits = 0;\n\n\tprivate _oplogRetryCount = 0;\n\n\t// Buffer to store throttled latency updates with timestamps\n\tprivate latencyBuffer = new Map<string, { latency: number, lastUpdate: Date }>();\n\n\t// Interval to flush latency updates in MongoDB\n\tprivate readonly LATENCY_UPDATE_INTERVAL = 60000;\n\n\t// Minimum time difference between two latency updates for the same user\n\tprivate readonly LATENCY_UPDATE_THRESHOLD_MS = 30000;\n\n\t// private currentPerfomanceMonitor: CurrentPerformanceMonitor[] = [];\n\t// private idPerformance: number = 0;\n\t// private performanceThread;\n\n\tprivate _invalidationDebounceTimers = new Map<string, NodeJS.Timeout>();\n\tprivate _invalidationPendingTimestamps = new Map<string, number>();\n\tprivate readonly DEBOUNCE_DELAY = 100; // 100ms debounce window\n\tprivate readonly MAX_WAIT_TIME = 500; // 500ms maximum delay\n\n\n\tconstructor() {}\n\t\n\tstatic create(wss: WebSocket.Server, serverConfig, monitorManagerFunction: MonitorManagerFunction) {\n\t\tconst subscriptionManager = new SubscriptionManager();\n\t\tsetImmediate(async () => {\n\t\t\tawait subscriptionManager.initialize(wss, serverConfig, monitorManagerFunction);\n\t\t});\n\t\treturn subscriptionManager;\n\t}\n\t\n\tprivate async initialize(wss: WebSocket.Server, serverConfig, monitorManagerFunction: MonitorManagerFunction) {\n\t\tthis._websocketManager = ResolveIOServer.getMainServer().getWebSocketManager();\n\t\tthis._monitorManagerFunction = monitorManagerFunction;\n\n\t\tthis._nodeCache = new NodeCache( { stdTTL: 0, checkperiod: 0 } );\n\n\t\tsetInterval(() => this.flushThrottledLatencyUpdates(), this.LATENCY_UPDATE_INTERVAL);\n\n\t\t// setTimeout(() => {\n\t\t// \tconsole.log('Setting up performance thread');\n\n\t\t// \tthis.performanceThread = new Worker(path.join(__dirname, './subscription.performance.js'));\n\n\t\t// \tthis.performanceThread.on('exit', code => {\n\t\t// \t\tconsole.error(new Date(), 'THREAD EXITED!!!!!!!!!!!!!!!!!!', code);\n\t\t// \t});\n\n\t\t// \tthis.performanceThread.on('error', code => {\n\t\t// \t\tconsole.error(new Date(), 'THREAD RECV ERROR !!!!!!!!!!!!!!!!!!', code);\n\t\t// \t});\n\t\t// }, 5000);\n\n\t\t// setInterval(() => {\n\t\t// \tconsole.log('Post thread msg');\n\t\t// \tthis.performanceThread.postMessage(this.currentPerfomanceMonitor);\n\t\t// \tthis.currentPerfomanceMonitor = [];\n\t\t// }, 10000);\n\n\t\tthis.serverConfig = serverConfig;\n\t\tthis._wss = wss;\n\n\t\t// Publications\n\t\tloadSuperAdminPublications(this);\n\t\tloadAppStatusPublications(this);\n\t\tloadLogPublications(this);\n\t\tloadFilePublications(this);\n\t\tloadCronJobPublications(this);\n\t\tloadFlagsUpdatePublications(this);\n\t\tloadFlagsPublications(this);\n\t\tloadNotificationPublications(this);\n\t\tloadReportBuilderReportPublications(this);\n\t\tloadReportBuilderLibraryPublications(this);\n\t\tloadUserGroupPublications(this);\n\t\tloadUserGuidePublications(this);\n\t\tloadReportBuilderDashboardBuilderPublications(this);\n\n\t\tawait this.tailOpLog();\n\n\t\tsetInterval(() => {\n\t\t\tthis._oplogRetryCount = 0;\n\t\t}, 15000);\n\n\t\tsetInterval(() => {\n\t\t\tif (this.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Subs', this._subscriptions.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Logged In Users', this._loggedInUsers.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue', this._mongoQueue.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue Hits', this._debugMongoQueueHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue Collections', JSON.stringify(this._debugMongoQueueCollections.sort((a, b) => a.collection.localeCompare(b.collection) || a.publication.localeCompare(b.publication)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Oplog Hits', this._debugOplogHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Oplog Collections', JSON.stringify(this._debugOplogCollections.sort((a, b) => a.collection.localeCompare(b.collection) || a.type.localeCompare(b.type)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Send Queue Hits', this._debugSendQueueHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Sub Hits', this._debugSubHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Sub Collections', JSON.stringify(this._debugSubCollections.sort((a, b) => a.publication.localeCompare(b.publication)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub Hits', this._debugUnSubHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub All Hits', this._debugUnSubAllHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Cache Cleanup Hits', this._debugRemoveCacheHits);\n\t\t\t}\n\t\t\t\n\t\t\tthis._debugOplogHits = 0;\n\t\t\tthis._debugOplogCollections = [];\n\t\t\tthis._debugSubCollections = [];\n\t\t\tthis._debugMongoQueueHits = 0;\n\t\t\tthis._debugMongoQueueCollections = [];\n\t\t\tthis._debugSendQueueHits = 0;\n\t\t\tthis._debugSubHits = 0;\n\t\t\tthis._debugUnSubHits = 0;\n\t\t\tthis._debugUnSubAllHits = 0;\n\t\t\tthis._debugRemoveCacheHits = 0;\n\t\t}, 60000);\n\n\t\tsetInterval(async () => {\n\t\t\tthis._loggedInUsers = await LoggedInUsers.find();\n\t\n\t\t\tlet userCopy = deepCopy(this._loggedInUsers);\n\t\t\tfor (let i = this._loggedInUsers.length - 1; i >= 0; i--) {\n\t\t\t\tlet loggedInUser = userCopy[i];\n\n\t\t\t\tif (!loggedInUser.date || Date.now() - loggedInUser.date.getTime() > 120000) {\n\t\t\t\t\tif (this._websocketManager.getWebSocket(loggedInUser.id_ws)) {\n\t\t\t\t\t\tif (this.getEnableDebug()) {\n\t\t\t\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub WS', this._websocketManager.getWebSocket(loggedInUser.id_ws)['user'], this._websocketManager.getWebSocket(loggedInUser.id_ws)['id_socket'], 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.unsubscribeAll(this._websocketManager.getWebSocket(loggedInUser.id_ws));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._subscriptions.forEach(sub => {\n\t\t\t\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\t\t\t\tlet client = sub.clients[j];\n\n\t\t\t\t\t\t\t\tif (client.id_socket === loggedInUser.id_ws) {\n\t\t\t\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait LoggedInUsers.deleteOne({_id: loggedInUser._id});\n\n\t\t\t\t\t\tif (this._loggedInUsers.findIndex(a => a._id === loggedInUser._id) >= 0) {\n\t\t\t\t\t\t\tthis._loggedInUsers.splice(this._loggedInUsers.findIndex(a => a._id === loggedInUser._id), 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < this._subscriptions.length; i++) {\n\t\t\t\tlet sub = this._subscriptions[i];\n\n\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\tlet client = sub.clients[j];\n\n\t\t\t\t\tif (!this._loggedInUsers.some(a => a.id_ws === client.id_socket)) {\n\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, 30000);\n\n\t\tlet flag = await Flags.findOne({type: 'Enable Debug'});\n\n\t\tif (flag && flag.value) {\n\t\t\tthis._enableDebug = true;\n\t\t}\n\t\telse {\n\t\t\tthis._enableDebug = false;\n\t\t}\n\n\t\tthis.setCacheLimit();\n\t}\n\n\tprivate setCacheLimit() {\t\n\t\tif (process.env.IS_WORKERS_ENABLED === 'true') {\n\t\t\tthis._heapLimit = this._heapSize * 0.4;\n\t\t}\n\t\telse {\n\t\t\tthis._heapLimit = this._heapSize * 0.3; // Use 50% of total heap size\n\t\t}\n\t}\n\n\tpublic async invalidatePubsCache(collection: string, type: string) {\n\t\tconst debounceKey = collection;\n\t\tconst now = Date.now();\n\t\n\t\t// Initialize or get existing timestamp\n\t\tconst firstInvalidationTime = this._invalidationPendingTimestamps.get(debounceKey) || now;\n\t\tthis._invalidationPendingTimestamps.set(debounceKey, firstInvalidationTime);\n\t\n\t\t// Clear any existing timer\n\t\tif (this._invalidationDebounceTimers.has(debounceKey)) {\n\t\t\tclearTimeout(this._invalidationDebounceTimers.get(debounceKey));\n\t\t}\n\t\n\t\t// Check if we've waited too long\n\t\tconst waitedTooLong = (now - firstInvalidationTime) >= this.MAX_WAIT_TIME;\n\t\t\n\t\tif (waitedTooLong) {\n\t\t\t// Immediate execution path\n\t\t\tthis._invalidationPendingTimestamps.delete(debounceKey);\n\t\t\tawait this._executeInvalidation(collection, type);\n\t\t} else {\n\t\t\t// Normal debounce path\n\t\t\tthis._invalidationDebounceTimers.set(\n\t\t\t\tdebounceKey,\n\t\t\t\tsetTimeout(async () => {\n\t\t\t\t\tthis._invalidationPendingTimestamps.delete(debounceKey);\n\t\t\t\t\tawait this._executeInvalidation(collection, type);\n\t\t\t\t}, this.DEBOUNCE_DELAY)\n\t\t\t);\n\t\t}\n\t}\n\t\n\tprivate async _executeInvalidation(collection: string, type: string) {\n\t\t// Clean up any existing timer (defensive)\n\t\tif (this._invalidationDebounceTimers.has(collection)) {\n\t\t\tclearTimeout(this._invalidationDebounceTimers.get(collection));\n\t\t\tthis._invalidationDebounceTimers.delete(collection);\n\t\t}\n\t\n\t\t// Original invalidation logic\n\t\tResolveIOServer.getMongoManager().invalidateQueryCache(collection);\n\t\n\t\tconst collSubs = this._subscriptions.filter(a => a.collections.includes(collection));\n\t\n\t\tfor (const sub of collSubs) {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Invalidate Sub', sub.publication, sub.running, sub.runAgain);\n\t\t\t}\n\t\n\t\t\tif (sub.running) {\n\t\t\t\tsub.runAgain = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\n\t\t\tif (this._publications[sub.publication].user_specific) {\n\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\tconst ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\tif (ws?.readyState === ws.OPEN) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch {\n\t\t\t\t\t\t\t// Error handling\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tawait this.sendDataToAllWithRetry(sub, collection, type);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async delay(ms: number) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\treturn new Promise(resolve => setTimeout(resolve, ms));\n\t}\n\n\tprivate async sendDataToAllWithRetry(sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tsub.running = true;\n\n\t\tdo {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Running sendDataToAll Sub', sub.publication);\n\t\t\t}\n\n\t\t\tsub.runAgain = false;\n\t\t\tawait this.sendDataToAll(sub, collection, type);\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Done sendDataToAll Sub', sub.publication, sub.runAgain);\n\t\t\t}\n\n\t\t\tif (sub.runAgain) {\n\t\t\t\tawait this.delay(500); // delay, adjust as needed\n\t\t\t}\n\t\t} while (sub.runAgain);\n\n\t\tsub.running = false;\n\t}\n\n\tprivate async sendDataToOneWithRetry(ws: WebSocket, messageId: number, sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tsub.running = true;\n\n\t\tdo {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Running sendDataToOne Sub', sub.publication);\n\t\t\t}\n\n\t\t\tsub.runAgain = false;\n\t\t\tawait this.sendDataToOne(ws, messageId, sub, collection, type);\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Done sendDataToOne Sub', sub.publication, sub.runAgain);\n\t\t\t}\n\n\t\t\tif (sub.runAgain) {\n\t\t\t\tawait this.delay(500); // delay, adjust as needed\n\t\t\t}\n\t\t} while (sub.runAgain);\n\t\tsub.running = false;\n\t}\n\n\t// Add all files to publications private object\n\tpublic publications(method: SubscriptionModel) {\n\t\tthis._publications = Object.assign(this._publications, method);\n\t}\n\n\t// Throttled `loggedInLatency` method\n\tpublic loggedInLatency(ws: WebSocket) {\n\t\tlet loggedInUser = this._loggedInUsers.find(a => a.id_ws === ws['id_socket']);\n\t\tif (!loggedInUser) return;\n\n\t\tconst now = new Date();\n\t\tconst existingEntry = this.latencyBuffer.get(ws['id_socket']);\n\t\tconst newLatency = ws['latency'];\n\n\t\t// Throttle updates: only update if time threshold has passed or latency has significantly changed\n\t\tif (\n\t\t\t!existingEntry || \n\t\t\t(now.getTime() - existingEntry.lastUpdate.getTime() >= this.LATENCY_UPDATE_THRESHOLD_MS) || \n\t\t\t(Math.abs(newLatency - existingEntry.latency) > 100) // Optional: log only significant changes\n\t\t) {\n\t\t\t// Update in-memory and buffer\n\t\t\tloggedInUser.date = now;\n\t\t\tthis.latencyBuffer.set(ws['id_socket'], { latency: newLatency, lastUpdate: now });\n\t\t}\n\t}\n\n\t// Method to flush buffered latency updates in bulk\n\tprivate async flushThrottledLatencyUpdates() {\n\t\tif (this.latencyBuffer.size === 0) return; // No updates to flush\n\n\t\tconst updates = Array.from(this.latencyBuffer.entries()).map(([id_ws, { latency, lastUpdate }]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { id_ws },\n\t\t\t\tupdate: { $set: { latency, date: lastUpdate } }\n\t\t\t}\n\t\t}));\n\n\t\ttry {\n\t\t\tawait LoggedInUsers.bulkWrite(updates);\n\t\t\tthis.latencyBuffer.clear(); // Clear buffer after successful update\n\n\t\t\tif (this.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Throttled latency batch update successful', updates.length);\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tconsole.error(new Date(), 'Sub Manager', 'Throttled latency batch update failed', error);\n\t\t\t// Optional: implement retry logic or logging for failed updates\n\t\t}\n\t}\n\n\t// Subscribe to publication\n\tpublic async subscribe(messageRoute: string, messageDate: Date, ws: WebSocket, messageId: number, publication: string, subscriptionData: any[]) {\n\t\tthis._debugSubHits += 1;\n\n\t\tif (!this._debugSubCollections.some(a => a.publication === publication)) {\n\t\t\tthis._debugSubCollections.push({\n\t\t\t\tpublication: publication,\n\t\t\t\thits: 1\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tthis._debugSubCollections.find(a => a.publication === publication).hits += 1;\n\t\t}\n\n\t\tlet pub = this._publications[publication];\n\n\t\tif (!pub) {\n\t\t\tconsole.error(new Date(), 'No Publication: ' + publication);\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tif (subscriptionData.length > 1 || subscriptionData[0]) {\n\t\t\t\tif (!pub.check) {\n\t\t\t\t\tconsole.error(new Date(), 'No Check Function For Pub ' + publication);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse if (!pub.check._schema) {\n\t\t\t\t\tconsole.error(new Date(), 'No Check Schema For Pub ' + publication);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlet valObj = {};\n\t\t\t\t\tlet valKeys = Object.keys(pub.check._schema);\n\n\t\t\t\t\tlet rootKeys = valKeys.filter(a => !a.includes('.'));\n\n\t\t\t\t\tfor (let i = 0; i < subscriptionData.length; i++) {\n\t\t\t\t\t\tvalObj[rootKeys[i]] = subscriptionData[i];\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpub.check.validate(valObj);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (errors) {\n\t\t\t\t\t\tif (errors) {\n\t\t\t\t\t\t\tconsole.error(new Date(), 'Error in Pub Check (' + publication + ')', errors);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (messageRoute !== 'Bypass') {\n\t\t\t\tlet urlData = messageRoute.split('/');\n\t\t\t\tlet urlModule = '';\n\t\t\t\tlet urlNext = urlData[0];\n\n\t\t\t\tif (urlData[0] === '') {\n\t\t\t\t\turlModule = '/';\n\t\t\t\t\turlNext = urlData[1];\n\t\t\t\t}\n\n\t\t\t\turlModule += urlNext;\n\n\t\t\t\tif (urlData.length > 1) {\n\t\t\t\t\turlModule += '/';\n\t\t\t\t}\n\n\t\t\t\tlet otherRouteSubs = this._subscriptions.filter(a => a.clients.some(b => b.id_socket === ws['id_socket'] && b.messageRoute !== 'Bypass' && b.messageRoute !== '/' && b.messageRoute !== messageRoute && !b.messageRoute.startsWith(urlModule)));\n\n\t\t\t\tif (otherRouteSubs.length) {\n\t\t\t\t\t// ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Detected Undestroyed Subscription - ' + this.serverConfig['CLIENT_NAME'], 'USER: ' + ws['user'] + ' (Socket: ' + ws['id_socket'] + ') ' + ' is on route: ' + messageRoute + ' but has the following subscriptions on other routes:' + JSON.stringify(otherRouteSubs, null, 2));\n\n\t\t\t\t\totherRouteSubs.forEach(otherSub => {\n\t\t\t\t\t\totherSub.clients.filter(a => a.id_socket === ws['id_socket']).forEach(client => {\n\t\t\t\t\t\t\tthis.unsubscribe(client.messageRoute, new Date(), ws, client.messageId, otherSub.publication, otherSub.subscriptionData);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\n\t\t\t// If sub found (another user watching same data), add client to same sub\n\t\t\tif (sub) {\n\t\t\t\tif (!sub.clients.some(a => a.id_socket === ws['id_socket'] && a.messageId === messageId)) {\n\t\t\t\t\tsub.clients.push({\n\t\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\tid_socket: ws['id_socket'],\n\t\t\t\t\t\tmessageRoute: messageRoute\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If sub not found, create new sub\n\t\t\telse {\n\t\t\t\tthis._subscriptions.push({\n\t\t\t\t\tpublication: publication,\n\t\t\t\t\tsubscriptionData: subscriptionData,\n\t\t\t\t\tcollections: this.getPublicationCollections(publication),\n\t\t\t\t\tclients: [{\n\t\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\tid_socket: ws['id_socket'],\n\t\t\t\t\t\tmessageRoute: messageRoute,\n\t\t\t\t\t}],\n\t\t\t\t\tcacheId: 0,\n\t\t\t\t\trunning: false,\n\t\t\t\t\trunAgain: false\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!sub) {\n\t\t\t\tsub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\t\t\t}\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'New Sub', sub.publication, sub.running, sub.runAgain, sub.clients.length);\n\t\t\t}\n\n\t\t\t// Immediately send data to the new client\n\t\t\tawait this.processSubscription(sub, ws, messageId);\n\t\t}\n\t}\n\n\tpublic async createLoggedInUser(id_ws: string): Promise<LoggedInUserModel> {\n\t\tlet ws = this._websocketManager.getWebSocket(id_ws);\n\n\t\tif (ws) {\n\t\t\tlet user = {\n\t\t\t\t_id: objectIdHexString(),\n\t\t\t\t__v: 0,\n\t\t\t\tdate: new Date(),\n\t\t\t\tid_user: ws['id_user'],\n\t\t\t\tuser: ws['user'],\n\t\t\t\tid_ws: ws['id_socket']\n\t\t\t};\n\t\t\t\n\t\t\tthis._loggedInUsers.push(user);\n\t\t\tawait LoggedInUsers.insertOne(user);\n\t\t\t\n\t\t\treturn user;\n\t\t}\n\t\telse {\n\t\t\tthrow new Error('Error in Create Logged In User: No WS');\n\t\t}\n\t}\n\n\t// Unsubscribe from publication \n\tpublic unsubscribe(messageRoute: string, messageDate: Date, ws: WebSocket, messageId: number, publication: string, subscriptionData: any[]) {\t\t\n\t\tthis._debugUnSubHits += 1;\n\n\t\tif (!this._publications[publication]) {\n\t\t\tconsole.log('No Publication: ' + publication);\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tlet sub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\n\t\t\tif (sub) {\n\t\t\t\tfor (let i = sub.clients.length - 1; i >= 0; i--) {\n\t\t\t\t\tif (sub.clients[i].id_user === ws['id_user'] && sub.clients[i].messageId === messageId && sub.clients[i].id_socket === ws['id_socket']) {\n\t\t\t\t\t\tsub.clients.splice(i, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\tconsole.log(new Date(), 'Unsub', sub.publication, sub.running, sub.runAgain, sub.clients.length);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// Unsubscribe from publication\n\tpublic async unsubscribeAll(ws: WebSocket) {\n\t\tthis._debugUnSubAllHits += 1;\n\n\t\tif (ws) {\n\t\t\t// Check if WebSocket has already been unsubscribed\n\t\t\tif (ws['isUnsubscribed']) {\n\t\t\t\treturn; // Skip if already unsubscribed\n\t\t\t}\n\t\t\t\n\t\t\t// Mark the WebSocket as unsubscribed to prevent further calls\n\t\t\tws['isUnsubscribed'] = true;\n\t\t\t\n\t\t\tif (this._loggedInUsers.map(a => a.id_ws).indexOf(ws['id_socket']) >= 0) {\n\t\t\t\tthis._loggedInUsers.splice(this._loggedInUsers.map(a => a.id_ws).indexOf(ws['id_socket']), 1);\n\t\t\t}\n\t\t\t\n\t\t\tawait LoggedInUsers.deleteOne({ id_ws: ws['id_socket'] });\n\n\t\t\tlet userSubs = this._subscriptions.filter(a => a.clients.some(b => b.id_user === ws['id_user'] && b.id_socket === ws['id_socket']));\n\n\t\t\tfor (let i = userSubs.length - 1; i >= 0; i--) {\n\t\t\t\tlet sub = userSubs[i];\n\n\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\tif (sub.clients[j].id_socket === ws['id_socket']) {\n\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._websocketManager.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic getActiveSubscriptions() {\n\t\treturn this._subscriptions;\n\t}\n\n\t// Get publication collection\n\tprivate getPublicationCollections(publication: string) {\n\t\treturn this._publications[publication].collections;\n\t}\n\n\t// Watch (tail) Mongo's operation log on the entire database (all insert/modify/delete will trigger this function)\n\tprivate async tailOpLog(resumeToken?: ResumeToken) {\n\t\tif (this._oplog$ && !this._oplog$.closed) {\n\t\t\tthis._oplog$.removeAllListeners();\n\t\t\tawait this._oplog$.close();\n\t\t\tthis._oplog$ = null;\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tawait new Promise(resolve => setTimeout(resolve, 1000));\n\n\t\tif (!this._oplog$ || this._oplog$.closed) {\n\t\t\tthis._oplogRetryCount += 1;\n\n\t\t\tif (this._oplogRetryCount > 5) {\n\t\t\t\tconsole.error('****************** TAIL OPLOG ERROR, RETRYING A BUNCH OF TIMES, KILLING PROCESS **************************');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst pipeline = [\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t{'ns.coll': { $nin: [\n\t\t\t\t\t\t\t\t'log-method-latencies', \n\t\t\t\t\t\t\t\t'log-subscriptions', \n\t\t\t\t\t\t\t\t'logs', \n\t\t\t\t\t\t\t\t'counters', \n\t\t\t\t\t\t\t\t'cron-job-histories', \n\t\t\t\t\t\t\t\t'email-histories',\n\t\t\t\t\t\t\t\t'qb-soap-request-histories', \n\t\t\t\t\t\t\t\t'qb-soap-request-responses', \n\t\t\t\t\t\t\t\t'qb-soap-requests',\n\t\t\t\t\t\t\t\t'qb-soap-retries'\n\t\t\t\t\t\t\t] }},\n\t\t\t\t\t\t\t{'ns.coll': { $not: /.*\\.versions$/ }},\n\t\t\t\t\t\t\t{'ns.coll': { $not: /^monitor-/ }},\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tlet lastResumeToken: ResumeToken;\n\n\t\t\tif (resumeToken) {\n\t\t\t\tlastResumeToken = resumeToken;\n\t\t\t\ttry {\n\t\t\t\t\tthis._oplog$ = ResolveIOServer.getMainDB().watch(pipeline, { resumeAfter: resumeToken });\n\t\t\t\t}\n\t\t\t\tcatch {\n\t\t\t\t\tif (this._oplog$) {\n\t\t\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\t\t\tawait this._oplog$.close();\n\t\t\t\t\t\tthis._oplog$ = null;\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.tailOpLog(resumeToken);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._oplog$ = ResolveIOServer.getMainDB().watch(pipeline);\n\t\t\t}\n\n\t\t\tconsole.log(new Date(), 'oplog started');\n\n\t\t\tthis._oplog$.on('change', async (doc: ChangeStreamInsertDocument | ChangeStreamUpdateDocument | ChangeStreamReplaceDocument | ChangeStreamDeleteDocument) => {\n\t\t\t\tif (doc.ns) {\n\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\tconsole.log(new Date(), 'Oplog Hit', doc.ns);\n\t\t\t\t\t}\n\n\t\t\t\t\tlet collection = doc.ns.coll;\n\n\t\t\t\t\tif (!this._debugOplogCollections.some(a => a.collection === doc.ns.coll && a.type === doc.operationType)) {\n\t\t\t\t\t\tthis._debugOplogCollections.push({\n\t\t\t\t\t\t\tcollection: doc.ns.coll,\n\t\t\t\t\t\t\ttype: doc.operationType,\n\t\t\t\t\t\t\thits: 1\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._debugOplogCollections.find(a => a.collection === doc.ns.coll && a.type === doc.operationType).hits += 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (collection) {\n\t\t\t\t\t\tthis._debugOplogHits += 1;\n\n\t\t\t\t\t\tif (doc.operationType === 'insert') {\n\t\t\t\t\t\t\tif (collection === 'support-tickets') {\n\t\t\t\t\t\t\t\tif (this.serverConfig['ROOT_URL'] === 'https://resolveio.com') {\n\t\t\t\t\t\t\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'sendSupportTicketEmail', doc.documentKey['_id']);\n\t\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'insert');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'insert');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (doc.operationType === 'update' || doc.operationType === 'replace') {\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'update');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (doc.operationType === 'delete') {\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'delete');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (collection === 'flags') {\n\t\t\t\t\t\tlet flag = await Flags.findOne({ type: 'Enable Debug' });\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (flag && flag.value) {\n\t\t\t\t\t\t\tthis._enableDebug = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis._enableDebug = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlastResumeToken = doc._id;\n\n\t\t\t\t\tif ((!process.env.NODE_APP_INSTANCE || process.env.NODE_APP_INSTANCE === '0') && (process.env.IS_WORKERS_ENABLED === 'false' || (process.env.IS_WORKER_INSTANCE === 'true' && process.env.WORKER_INDEX === '0'))) {\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis._oplog$.on('error', async error => {\n\t\t\t\tconsole.log(new Date(), 'oplog error', error);\n\t\t\t\tawait this._oplog$.close();\n\t\t\t});\n\n\t\t\tthis._oplog$.on('end', async () => {\n\t\t\t\tconsole.log(new Date(), 'oplog end');\n\t\t\t\tawait this._oplog$.close();\n\t\t\t});\n\n\t\t\tthis._oplog$.on('close', async () => {\n\t\t\t\tconsole.log(new Date(), 'oplog close');\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tawait this.tailOpLog(lastResumeToken);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async processSubscription(sub: ActiveSubscriptionModel, ws: WebSocket, messageId: number) {\n\t\tif (!this._publications[sub.publication].user_specific) {\t\t\t\n\t\t\tif (sub.cacheId) {\n\t\t\t\ttry {\n\t\t\t\t\tlet cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), dateReviver);\n\n\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tdata: cacheData\n\t\t\t\t\t};\n\n\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\tconsole.log(new Date(), 'Process Sub, Cache', sub.publication);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t}\n\t\t\t\tcatch {\n\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\t\tsub.cacheId = 0;\n\n\t\t\t\t\tawait this.sendDataToAllWithRetry(sub, '', 'newSub');\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\tconsole.log(new Date(), 'Process Sub, Non - Cache', sub.publication, sub.running);\n\t\t\t\t}\n\n\t\t\t\tif (sub.running) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait this.sendDataToAllWithRetry(sub, '', 'newSub');\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Process Sub Specific, Non - Cache', sub.publication, sub.running);\n\t\t\t}\n\n\t\t\tif (sub.running) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tawait this.sendDataToOneWithRetry(ws, messageId, sub, '', 'newSub');\n\t\t}\n\t}\n\n\tprivate async sendDataToOne(ws: WebSocket, messageId: number, sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tlet monitor = this._monitorManagerFunction.startMonitorFunction('User Specific Publication', sub.publication, '', '', sub.subscriptionData);\n\t\ttry {\n\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));\n\n\t\t\tlet res = await this._publications[sub.publication].function.call(Object.assign({}, this, SubscriptionManager.prototype), ws['id_user'], ...sub.subscriptionData);\n\n\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: false,\n\t\t\t\tdata: res\n\t\t\t};\n\n\t\t\tthis.sendWS(ws, serverRes);\n\t\t}\n\t\tcatch (err) {\n\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: true,\n\t\t\t\tdata: err\n\t\t\t};\n\t\t\t\n\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\n\t\t\tawait ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendDataToOne - WS)\\n\\nData \\n' + JSON.stringify(sub.subscriptionData, null, 2) + '\\n\\nErrors\\n' + JSON.stringify(err, null, 2));\n\t\t}\n\t\tfinally {\n\t\t\tawait this._monitorManagerFunction.finishMonitorFunction(monitor);\n\t\t}\n\t}\n\n\t// Fetch pub once, send to all clients linked to this pub\n\tprivate async sendDataToAll(sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tif (!sub.clients.length) {\n\t\t\tif (sub.cacheId) {\n\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\tsub.cacheId = 0;\n\t\t\t}\n\n\t\t\tlet subIndex = this._subscriptions.findIndex(a => a.publication === sub.publication && JSON.stringify(a.subscriptionData) === JSON.stringify(sub.subscriptionData));\n\t\t\tif (subIndex >= 0) {\n\t\t\t\tthis._subscriptions.splice(subIndex, 1);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tlet monitor = this._monitorManagerFunction.startMonitorFunction('Publication', sub.publication, '', '', sub.subscriptionData);\n\n\t\t\ttry {\n\t\t\t\tif (sub.publication !== 'superadminAPM' && sub.publication !== 'loggedInUsers') {\n\t\t\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));\n\t\t\t\t}\n\n\t\t\t\tlet res = await this._publications[sub.publication].function.call(Object.assign({}, this, SubscriptionManager.prototype), ...sub.subscriptionData);\n\n\t\t\t\tif (sub.cacheId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), dateReviver);\n\t\n\t\t\t\t\t\tif (JSON.stringify(cacheData) !== JSON.stringify(res)) {\n\t\t\t\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t\t};\n\t\t\n\t\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\n\t\t\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch {\n\t\t\t\t\t\tsub.clients.map(client => {\n\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t};\n\t\n\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\n\t\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t) {\n\t\t\t\t\t\tsub.cacheId = this._cacheId++;\n\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\n\t\t\t\t\t\tconst nodeCacheSize = this._nodeCache.getStats().vsize;\n\n\t\t\t\t\t\tif (nodeCacheSize > this._heapLimit) {\n\t\t\t\t\t\t\t// Evict cache entries as needed\n\t\t\t\t\t\t\tlet deleteCount = 0;\n\t\t\t\t\t\t\tconst subArr = this._subscriptions.filter(a => a.cacheId && !a.clients.length);\n\t\t\t\t\t\n\t\t\t\t\t\t\tfor (let zz = 0; zz < subArr.length; zz++) {\n\t\t\t\t\t\t\t\tthis._debugRemoveCacheHits += 1;\n\t\t\t\t\t\t\t\tthis._nodeCache.del(subArr[zz].cacheId);\n\t\t\t\t\t\t\t\tsubArr[zz].cacheId = 0;\n\t\t\t\t\t\t\t\tdeleteCount += 1;\n\t\t\t\t\t\t\t\tif (this._nodeCache.getStats().vsize < this._heapLimit * 0.75) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\t'Sub Cache: ' +\n\t\t\t\t\t\t\t\t\t'Too Big - ' +\n\t\t\t\t\t\t\t\t\tsub.publication +\n\t\t\t\t\t\t\t\t\t' - Deleted: ' +\n\t\t\t\t\t\t\t\t\tdeleteCount +\n\t\t\t\t\t\t\t\t\t' - ' +\n\t\t\t\t\t\t\t\t\tnodeCacheSize\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err) {\n\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\thasError: true,\n\t\t\t\t\t\t\tdata: err\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tawait ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendPubData)\\n\\nData \\n' + JSON.stringify(sub.subscriptionData, null, 2) + '\\n\\nErrors\\n' + JSON.stringify(err, null, 2));\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\tawait this._monitorManagerFunction.finishMonitorFunction(monitor);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendWS(ws: WebSocket, data: ServerResponseModel) {\n\t\tthis._websocketManager.send(ws, data);\n\t}\n\n\tpublic getEnableDebug() {\n\t\treturn this._enableDebug;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/managers/subscription.manager.ts"],"names":["NodeCache","require","os_1","flag_collection_1","logged_in_users_collection_1","app_status_1","cron_jobs_1","files_1","flags_1","flags_update_1","logs_1","notifications_1","report_builder_dashboard_builders_1","report_builder_libraries_1","report_builder_reports_1","super_admin_1","user_groups_1","user_guides_1","resolveio_server_app_1","common_1","numCPUs","cpus","length","v8","SubscriptionManager","this","_publications","_subscriptions","_loggedInUsers","_mongoQueue","_mongoQueueId","_cacheId","_heapSize","getHeapStatistics","_enableDebug","_debugOplogCollections","_debugOplogHits","_debugSubCollections","_debugSubHits","_debugUnSubHits","_debugUnSubAllHits","_debugMongoQueueHits","_debugMongoQueueCollections","_debugSendQueueHits","_debugRemoveCacheHits","_oplogRetryCount","latencyBuffer","Map","LATENCY_UPDATE_INTERVAL","LATENCY_UPDATE_THRESHOLD_MS","_invalidationDebounceTimers","_invalidationPendingTimestamps","DEBOUNCE_DELAY","MAX_WAIT_TIME","create","wss","serverConfig","monitorManagerFunction","_this","subscriptionManager","setImmediate","__awaiter","initialize","_a","sent","prototype","_websocketManager","ResolveIOServer","getMainServer","getWebSocketManager","_monitorManagerFunction","_nodeCache","stdTTL","checkperiod","setInterval","flushThrottledLatencyUpdates","_wss","loadSuperAdminPublications","loadAppStatusPublications","loadLogPublications","loadFilePublications","loadCronJobPublications","loadFlagsUpdatePublications","loadFlagsPublications","loadNotificationPublications","loadReportBuilderReportPublications","loadReportBuilderLibraryPublications","loadUserGroupPublications","loadUserGuidePublications","loadReportBuilderDashboardBuilderPublications","tailOpLog","getEnableDebug","console","log","Date","JSON","stringify","sort","a","b","collection","localeCompare","publication","type","LoggedInUsers","find","_b","userCopy","deepCopy","i","loggedInUser","date","now","getTime","this_1","getWebSocket","id_ws","unsubscribeAll","_c","forEach","sub","j","clients","id_socket","splice","deleteOne","_id","findIndex","client","this_2","some","Flags","findOne","flag","value","setCacheLimit","process","env","IS_WORKERS_ENABLED","_heapLimit","invalidatePubsCache","debounceKey","firstInvalidationTime","get","set","has","clearTimeout","delete","_executeInvalidation","setTimeout","getMongoManager","invalidateQueryCache","collSubs","filter","collections","includes","collSubs_1","__values","collSubs_1_1","next","running","runAgain","user_specific","e_1","ws","readyState","OPEN","sendDataToOneWithRetry","messageId","_f","sendDataToAllWithRetry","delay","ms","Promise","resolve","sendDataToAll","sendDataToOne","publications","method","Object","assign","loggedInLatency","existingEntry","newLatency","lastUpdate","Math","abs","latency","size","updates","Array","from","entries","map","__read","updateOne","update","$set","bulkWrite","clear","error","error_1","subscribe","messageRoute","messageDate","subscriptionData","hits","push","pub","check","_schema","valObj","valKeys","keys","rootKeys","validate","errors","urlData","split","urlModule_1","urlNext","otherRouteSubs","startsWith","otherSub","unsubscribe","id_user","getPublicationCollections","cacheId","processSubscription","createLoggedInUser","user","objectIdHexString","__v","insertOne","Error","indexOf","userSubs","removeWebSocket","getActiveSubscriptions","resumeToken","_oplog$","closed","removeAllListeners","close","exit","pipeline","$match","$and","ns.coll","$nin","$not","lastResumeToken_1","getMainDB","watch","resumeAfter","on","doc","ns","coll","operationType","getMethodManager","callMethod","call","documentKey","NODE_APP_INSTANCE","IS_WORKER_INSTANCE","WORKER_INDEX","cacheData","parse","dateReviver","serverRes","hasError","data","sendWS","del","monitor","startMonitorFunction","function","apply","__spreadArray","res","err_1","sendEmail","finishMonitorFunction","subIndex","_g","res_1","_l","done","getBinarySize","endsWith","_m","_d","nodeCacheSize","getStats","vsize","deleteCount","subArr","zz","_e","err_2","send","exports"],"mappings":"+xEACAA,W,0FAAAC,QAAA,YAAA,GACAC,KAAAD,QAAA,IAAA,EAEAE,kBAAAF,QAAA,gCAAA,EACAG,6BAAAH,QAAA,2CAAA,EAIAI,aAAAJ,QAAA,4BAAA,EACAK,YAAAL,QAAA,2BAAA,EACAM,QAAAN,QAAA,uBAAA,EACAO,QAAAP,QAAA,uBAAA,EACAQ,eAAAR,QAAA,8BAAA,EACAS,OAAAT,QAAA,sBAAA,EACAU,gBAAAV,QAAA,+BAAA,EACAW,oCAAAX,QAAA,mDAAA,EACAY,2BAAAZ,QAAA,0CAAA,EACAa,yBAAAb,QAAA,wCAAA,EACAc,cAAAd,QAAA,6BAAA,EACAe,cAAAf,QAAA,6BAAA,EACAgB,cAAAhB,QAAA,6BAAA,EACAiB,uBAAAjB,QAAA,yBAAA,EACAkB,SAAAlB,QAAA,gBAAA,EAGMmB,SAAU,EAAAlB,KAAAmB,MAAI,EAAGC,OACjBC,GAAKtB,QAAQ,IAAI,EA0BvBuB,oBAAA,WAuDC,SAAAA,sBArDQC,KAAAC,cAAmC,GACnCD,KAAAE,eAA4C,GAE5CF,KAAAG,eAAsC,GAEtCH,KAAAI,YAAiC,GACjCJ,KAAAK,cAAgB,EAKhBL,KAAAM,SAAW,EAEXN,KAAAO,UAAYT,GAAGU,kBAAiB,EAAKb,QAOrCK,KAAAS,aAAe,CAAA,EACfT,KAAAU,uBAAyB,GACzBV,KAAAW,gBAAkB,EAClBX,KAAAY,qBAAuB,GACvBZ,KAAAa,cAAgB,EAChBb,KAAAc,gBAAkB,EAClBd,KAAAe,mBAAqB,EACrBf,KAAAgB,qBAAuB,EACvBhB,KAAAiB,4BAA8B,GAC9BjB,KAAAkB,oBAAsB,EACtBlB,KAAAmB,sBAAwB,EAExBnB,KAAAoB,iBAAmB,EAGnBpB,KAAAqB,cAAgB,IAAIC,IAGXtB,KAAAuB,wBAA0B,IAG1BvB,KAAAwB,4BAA8B,IAMvCxB,KAAAyB,4BAA8B,IAAIH,IAClCtB,KAAA0B,+BAAiC,IAAIJ,IAC5BtB,KAAA2B,eAAiB,IACjB3B,KAAA4B,cAAgB,GAGlB,CAy7BhB,OAv7BQ7B,oBAAA8B,OAAP,SAAcC,EAAuBC,EAAcC,GAAnD,IAAAC,EAAAjC,KACOkC,EAAsB,IAAInC,oBAIhC,OAHAoC,aAAa,WAAA,OAAAC,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,2DACZ,MAAA,CAAA,EAAMC,EAAoBG,WAAWP,EAAKC,EAAcC,CAAsB,G,cAA9EM,EAAAC,KAAA,E,SACA,EACML,CACR,EAEcnC,oBAAAyC,UAAAH,WAAd,SAAyBP,EAAuBC,EAAcC,G,uHA8C7D,OA7CAhC,KAAKyC,kBAAoBhD,uBAAAiD,gBAAgBC,cAAa,EAAGC,oBAAmB,EAC5E5C,KAAK6C,wBAA0Bb,EAE/BhC,KAAK8C,WAAa,IAAIvE,UAAW,CAAEwE,OAAQ,EAAGC,YAAa,CAAC,CAAE,EAE9DC,YAAY,WAAM,OAAAhB,EAAKiB,6BAA4B,CAAjC,EAAqClD,KAAKuB,uBAAuB,EAsBnFvB,KAAK+B,aAAeA,EACpB/B,KAAKmD,KAAOrB,GAGZ,EAAAxC,cAAA8D,4BAA2BpD,IAAI,GAC/B,EAAApB,aAAAyE,2BAA0BrD,IAAI,GAC9B,EAAAf,OAAAqE,qBAAoBtD,IAAI,GACxB,EAAAlB,QAAAyE,sBAAqBvD,IAAI,GACzB,EAAAnB,YAAA2E,yBAAwBxD,IAAI,GAC5B,EAAAhB,eAAAyE,6BAA4BzD,IAAI,GAChC,EAAAjB,QAAA2E,uBAAsB1D,IAAI,GAC1B,EAAAd,gBAAAyE,8BAA6B3D,IAAI,GACjC,EAAAX,yBAAAuE,qCAAoC5D,IAAI,GACxC,EAAAZ,2BAAAyE,sCAAqC7D,IAAI,GACzC,EAAAT,cAAAuE,2BAA0B9D,IAAI,GAC9B,EAAAR,cAAAuE,2BAA0B/D,IAAI,GAC9B,EAAAb,oCAAA6E,+CAA8ChE,IAAI,EAElD,CAAA,EAAMA,KAAKiE,UAAS,G,OAkFT,OAlFX3B,EAAAC,KAAA,EAEAU,YAAY,WACXhB,EAAKb,iBAAmB,CACzB,EAAG,IAAK,EAER6B,YAAY,WACPhB,EAAKiC,eAAc,IACtBC,QAAQC,IAAI,IAAIC,KAAQ,cAAe,OAAQpC,EAAK/B,eAAeL,MAAM,EACzEsE,QAAQC,IAAI,IAAIC,KAAQ,cAAe,kBAAmBpC,EAAK9B,eAAeN,MAAM,EACpFsE,QAAQC,IAAI,IAAIC,KAAQ,cAAe,cAAepC,EAAK7B,YAAYP,MAAM,EAC7EsE,QAAQC,IAAI,IAAIC,KAAQ,cAAe,mBAAoBpC,EAAKjB,oBAAoB,EACpFmD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,0BAA2BC,KAAKC,UAAUtC,EAAKhB,4BAA4BuD,KAAK,SAACC,EAAGC,GAAM,OAAAD,EAAEE,WAAWC,cAAcF,EAAEC,UAAU,GAAKF,EAAEI,YAAYD,cAAcF,EAAEG,WAAW,CAArF,CAAsF,EAAG,KAAM,CAAC,CAAC,EAClOV,QAAQC,IAAI,IAAIC,KAAQ,cAAe,aAAcpC,EAAKtB,eAAe,EACzEwD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,oBAAqBC,KAAKC,UAAUtC,EAAKvB,uBAAuB8D,KAAK,SAACC,EAAGC,GAAM,OAAAD,EAAEE,WAAWC,cAAcF,EAAEC,UAAU,GAAKF,EAAEK,KAAKF,cAAcF,EAAEI,IAAI,CAAvE,CAAwE,EAAG,KAAM,CAAC,CAAC,EACzMX,QAAQC,IAAI,IAAIC,KAAQ,cAAe,kBAAmBpC,EAAKf,mBAAmB,EAClFiD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,WAAYpC,EAAKpB,aAAa,EACrEsD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,kBAAmBC,KAAKC,UAAUtC,EAAKrB,qBAAqB4D,KAAK,SAACC,EAAGC,GAAM,OAAAD,EAAEI,YAAYD,cAAcF,EAAEG,WAAW,CAAzC,CAA0C,EAAG,KAAM,CAAC,CAAC,EACvKV,QAAQC,IAAI,IAAIC,KAAQ,cAAe,aAAcpC,EAAKnB,eAAe,EACzEqD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,iBAAkBpC,EAAKlB,kBAAkB,EAChFoD,QAAQC,IAAI,IAAIC,KAAQ,cAAe,qBAAsBpC,EAAKd,qBAAqB,GAGxFc,EAAKtB,gBAAkB,EACvBsB,EAAKvB,uBAAyB,GAC9BuB,EAAKrB,qBAAuB,GAC5BqB,EAAKjB,qBAAuB,EAC5BiB,EAAKhB,4BAA8B,GACnCgB,EAAKf,oBAAsB,EAC3Be,EAAKpB,cAAgB,EACrBoB,EAAKnB,gBAAkB,EACvBmB,EAAKlB,mBAAqB,EAC1BkB,EAAKd,sBAAwB,CAC9B,EAAG,GAAK,EAER8B,YAAY,WAAA,OAAAb,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,iFACW,OAAtBK,EAAAtC,KAAsB,CAAA,EAAMrB,6BAAAoG,cAAcC,KAAI,G,OAA9C1C,EAAKnC,eAAiB8E,EAAA1C,KAAA,EAElB2C,GAAW,EAAAxF,SAAAyF,UAASnF,KAAKG,cAAc,E,WAClCiF,G,uEAGHC,EAFDA,EAAeH,EAASE,IAEVE,MAAmD,KAA3CjB,KAAKkB,IAAG,EAAKF,EAAaC,KAAKE,QAAO,EAC3DC,EAAKhD,kBAAkBiD,aAAaL,EAAaM,KAAK,GACrDF,EAAKvB,eAAc,GACtBC,QAAQC,IAAI,IAAIC,KAAQ,cAAe,WAAYoB,EAAKhD,kBAAkBiD,aAAaL,EAAaM,KAAK,EAAQ,KAAGF,EAAKhD,kBAAkBiD,aAAaL,EAAaM,KAAK,EAAa,UAAG,CAAC,EAE5L,CAAA,EAAMF,EAAKG,eAAeH,EAAKhD,kBAAkBiD,aAAaL,EAAaM,KAAK,CAAC,IAJ9E,CAAA,EAAA,GADD,CAAA,EAAA,G,cAKFE,EAAAtD,KAAA,E,aAaA,OAVAkD,EAAKvF,eAAe4F,QAAQ,SAAAC,GAC3B,IAAK,IAAIC,EAAID,EAAIE,QAAQpG,OAAS,EAAQ,GAALmG,EAAQA,CAAC,GAChCD,EAAIE,QAAQD,GAEdE,YAAcb,EAAaM,OACrCI,EAAIE,QAAQE,OAAOH,EAAG,CAAC,CAG1B,CAAC,EAED,CAAA,EAAMrH,6BAAAoG,cAAcqB,UAAU,CAACC,IAAKhB,EAAagB,GAAG,CAAC,G,OAArDR,EAAAtD,KAAA,EAEsE,GAAlEkD,EAAKtF,eAAemG,UAAU,SAAA7B,GAAK,OAAAA,EAAE4B,MAAQhB,EAAagB,GAAvB,CAA0B,GAChEZ,EAAKtF,eAAegG,OAAOV,EAAKtF,eAAemG,UAAU,SAAA7B,GAAK,OAAAA,EAAE4B,MAAQhB,EAAagB,GAAvB,CAA0B,EAAG,CAAC,E,+BAxBvFjB,G,QAASjF,eAAeN,OAAS,E,wBAAQ,GAALuF,E,KAApCA,CAAC,GAAyC,CAAA,EAAA,G,wCAAEA,CAAC,G,aA8BtD,IAASA,EAAI,EAAGA,EAAIpF,KAAKE,eAAeL,OAAQuF,CAAC,GAGhD,IAFIW,EAAM/F,KAAKE,eAAekF,G,WAErBY,GACR,IAAIO,EAASR,EAAIE,QAAQD,GAEpBQ,EAAKrG,eAAesG,KAAK,SAAAhC,GAAK,OAAAA,EAAEkB,QAAUY,EAAOL,SAAnB,CAA4B,GAC9DH,EAAIE,QAAQE,OAAOH,EAAG,CAAC,C,SAJhBA,EAAID,EAAIE,QAAQpG,OAAS,EAAQ,GAALmG,EAAQA,CAAC,G,EAArCA,CAAC,E,gBAQT,GAAK,EAEG,CAAA,EAAMtH,kBAAAgI,MAAMC,QAAQ,CAAC7B,KAAM,cAAc,CAAC,G,cAAjD8B,EAAOtE,EAAAC,KAAA,IAECqE,EAAKC,MAChB7G,KAAKS,aAAe,CAAA,EAGpBT,KAAKS,aAAe,CAAA,EAGrBT,KAAK8G,cAAa,E,UAGX/G,oBAAAyC,UAAAsE,cAAR,WACwC,SAAnCC,QAAQC,IAAIC,mBACfjH,KAAKkH,WAA8B,GAAjBlH,KAAKO,UAGvBP,KAAKkH,WAA8B,GAAjBlH,KAAKO,SAEzB,EAEaR,oBAAAyC,UAAA2E,oBAAb,SAAiCxC,EAAoBG,G,kIAC9CsC,EAAczC,EACdY,EAAMlB,KAAKkB,IAAG,EAGd8B,EAAwBrH,KAAK0B,+BAA+B4F,IAAIF,CAAW,GAAK7B,EACtFvF,KAAK0B,+BAA+B6F,IAAIH,EAAaC,CAAqB,EAGtErH,KAAKyB,4BAA4B+F,IAAIJ,CAAW,GACnDK,aAAazH,KAAKyB,4BAA4B6F,IAAIF,CAAW,CAAC,EAIxC7B,EAAM8B,GAA0BrH,KAAK4B,gBAI3D5B,KAAK0B,+BAA+BgG,OAAON,CAAW,EACtD,CAAA,EAAMpH,KAAK2H,qBAAqBhD,EAAYG,CAAI,IAH7C,CAAA,EAAA,G,cAGHxC,EAAAC,KAAA,E,aAGAvC,KAAKyB,4BAA4B8F,IAChCH,EACAQ,WAAW,WAAA,OAAAxF,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,2DAEV,OADAjC,KAAK0B,+BAA+BgG,OAAON,CAAW,EACtD,CAAA,EAAMpH,KAAK2H,qBAAqBhD,EAAYG,CAAI,G,cAAhDxC,EAAAC,KAAA,E,UACEvC,KAAK2B,cAAc,CAAC,E,iCAKZ5B,oBAAAyC,UAAAmF,qBAAd,SAAmChD,EAAoBG,G,wIAElD9E,KAAKyB,4BAA4B+F,IAAI7C,CAAU,IAClD8C,aAAazH,KAAKyB,4BAA4B6F,IAAI3C,CAAU,CAAC,EAC7D3E,KAAKyB,4BAA4BiG,OAAO/C,CAAU,GAInDlF,uBAAAiD,gBAAgBmF,gBAAe,EAAGC,qBAAqBnD,CAAU,EAE3DoD,EAAW/H,KAAKE,eAAe8H,OAAO,SAAAvD,GAAK,OAAAA,EAAEwD,YAAYC,SAASvD,CAAU,CAAjC,CAAkC,E,2CAEjEwD,EAAAC,SAAAL,CAAQ,EAAAM,EAAAF,EAAAG,KAAA,E,wCAKzB,GALUvC,EAAGsC,EAAAxB,MACT7G,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,iBAAkB0B,EAAIlB,YAAakB,EAAIwC,QAASxC,EAAIyC,QAAQ,EAGjFzC,EAAIwC,QAEP,OADAxC,EAAIyC,SAAW,CAAA,EACf,CAAA,EAAA,I,IAGGxI,KAAKC,cAAc8F,EAAIlB,aAAa4D,cAApC,MAAA,CAAA,EAAA,I,2CACgBC,EAAA,KAAA,EAAApG,EAAA8F,SAAArC,EAAIE,OAAO,EAAAhB,EAAA3C,EAAAgG,KAAA,E,0CAArB/B,EAAMtB,EAAA4B,OAEV8B,OADEA,EAAK3I,KAAKyC,kBAAkBiD,aAAaa,EAAOL,SAAS,GACzD,KAAA,EAAFyC,EAAIC,cAAeD,EAAGE,KAAtB,MAAA,CAAA,EAAA,G,iBAEF,O,sBAAA,CAAA,EAAM7I,KAAK8I,uBAAuBH,EAAIpC,EAAOwC,UAAWhD,EAAKpB,EAAYG,CAAI,G,cAA7EkE,EAAAzG,KAAA,E,qPASH,MAAA,CAAA,EAAMvC,KAAKiJ,uBAAuBlD,EAAKpB,EAAYG,CAAI,G,QAAvDkE,EAAAzG,KAAA,E,0NAKWxC,oBAAAyC,UAAA0G,MAAd,SAAoBC,G,mFAEnB,MAAA,CAAA,EAAO,IAAIC,QAAQ,SAAAC,GAAW,OAAAzB,WAAWyB,EAASF,CAAE,CAAtB,CAAuB,E,MAGxCpJ,oBAAAyC,UAAAyG,uBAAd,SAAqClD,EAA8BpB,EAAoBG,G,0GACtFiB,EAAIwC,QAAU,CAAA,E,iBAQb,OALIvI,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,4BAA6B0B,EAAIlB,WAAW,EAGrEkB,EAAIyC,SAAW,CAAA,EACf,CAAA,EAAMxI,KAAKsJ,cAAcvD,EAAKpB,EAAYG,CAAI,G,cAA9CxC,EAAAC,KAAA,EAEIvC,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,yBAA0B0B,EAAIlB,YAAakB,EAAIyC,QAAQ,EAG5EzC,EAAIyC,UACP,CAAA,EAAMxI,KAAKkJ,MAAM,GAAG,GADjB,CAAA,EAAA,G,OACH5G,EAAAC,KAAA,E,oBAEOwD,EAAIyC,SAAQ,MAAA,CAAA,EAAA,G,wBAErBzC,EAAIwC,QAAU,CAAA,E,UAGDxI,oBAAAyC,UAAAsG,uBAAd,SAAqCH,EAAeI,EAAmBhD,EAA8BpB,EAAoBG,G,0GACxHiB,EAAIwC,QAAU,CAAA,E,iBAQb,OALIvI,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,4BAA6B0B,EAAIlB,WAAW,EAGrEkB,EAAIyC,SAAW,CAAA,EACf,CAAA,EAAMxI,KAAKuJ,cAAcZ,EAAII,EAAWhD,EAAKpB,EAAYG,CAAI,G,cAA7DxC,EAAAC,KAAA,EAEIvC,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,yBAA0B0B,EAAIlB,YAAakB,EAAIyC,QAAQ,EAG5EzC,EAAIyC,UACP,CAAA,EAAMxI,KAAKkJ,MAAM,GAAG,GADjB,CAAA,EAAA,G,OACH5G,EAAAC,KAAA,E,oBAEOwD,EAAIyC,SAAQ,MAAA,CAAA,EAAA,G,wBACrBzC,EAAIwC,QAAU,CAAA,E,UAIRxI,oBAAAyC,UAAAgH,aAAP,SAAoBC,GACnBzJ,KAAKC,cAAgByJ,OAAOC,OAAO3J,KAAKC,cAAewJ,CAAM,CAC9D,EAGO1J,oBAAAyC,UAAAoH,gBAAP,SAAuBjB,GACtB,IAGMpD,EACAsE,EACAC,EALFzE,EAAerF,KAAKG,eAAe6E,KAAK,SAAAP,GAAK,OAAAA,EAAEkB,QAAUgD,EAAc,SAA1B,CAA2B,EACvEtD,IAECE,EAAM,IAAIlB,KACVwF,EAAgB7J,KAAKqB,cAAciG,IAAIqB,EAAc,SAAC,EACtDmB,EAAanB,EAAY,QAI9B,CAACkB,GACAtE,EAAIC,QAAO,EAAKqE,EAAcE,WAAWvE,QAAO,GAAMxF,KAAKwB,6BACZ,IAA/CwI,KAAKC,IAAIH,EAAaD,EAAcK,OAAO,KAG5C7E,EAAaC,KAAOC,EACpBvF,KAAKqB,cAAckG,IAAIoB,EAAc,UAAG,CAAEuB,QAASJ,EAAYC,WAAYxE,CAAG,CAAE,EAElF,EAGcxF,oBAAAyC,UAAAU,6BAAd,W,kHACC,GAAgC,IAA5BlD,KAAKqB,cAAc8I,KAAY,MAAA,CAAA,GAE7BC,EAAUC,MAAMC,KAAKtK,KAAKqB,cAAckJ,QAAO,CAAE,EAAEC,IAAI,SAAClI,G,IAAA2C,EAAAwF,OAAAnI,EAAA,CAAA,EAACqD,EAAKV,EAAA,GAAEY,EAAAZ,EAAA,GAA6B,MAAA,CAClGyF,UAAW,CACV1C,OAAQ,CAAErC,MAAKA,CAAA,EACfgF,OAAQ,CAAEC,KAAM,CAAEV,QAH2DrE,EAAAqE,QAGlD5E,KAH8DO,EAAAkE,UAG9C,CAAE,C,CAE9C,CALkG,CAKjG,E,iBAGD,O,sBAAA,CAAA,EAAMpL,6BAAAoG,cAAc8F,UAAUT,CAAO,G,cAArC9H,EAAAC,KAAA,EACAvC,KAAKqB,cAAcyJ,MAAK,EAEpB9K,KAAKkE,eAAc,GACtBC,QAAQC,IAAI,IAAIC,KAAQ,cAAe,4CAA6C+F,EAAQvK,MAAM,E,+BAInGsE,QAAQ4G,MAAM,IAAI1G,KAAQ,cAAe,wCAAyC2G,CAAK,E,6BAM5EjL,oBAAAyC,UAAAyI,UAAb,SAAuBC,EAAsBC,EAAmBxC,EAAeI,EAAmBlE,EAAqBuG,G,0IACtHpL,KAAKa,eAAiB,EAEjBb,KAAKY,qBAAqB6F,KAAK,SAAAhC,GAAK,OAAAA,EAAEI,cAAgBA,CAAlB,CAA6B,EAOrE7E,KAAKY,qBAAqBoE,KAAK,SAAAP,GAAK,OAAAA,EAAEI,cAAgBA,CAAlB,CAA6B,EAAEwG,MAAQ,EAN3ErL,KAAKY,qBAAqB0K,KAAK,CAC9BzG,YAAaA,EACbwG,KAAM,C,CACN,EAMEE,EAAMvL,KAAKC,cAAc4E,IAEzB,CAAA,EAAA,IACHV,QAAQ4G,MAAM,IAAI1G,KAAQ,mBAAqBQ,CAAW,EAC1D,CAAA,I,OAGA,GAA8B,EAA1BuG,EAAiBvL,QAAcuL,EAAiB,GAAI,CACvD,GAAKG,CAAAA,EAAIC,MAER,OADArH,QAAQ4G,MAAM,IAAI1G,KAAQ,6BAA+BQ,CAAW,EACpE,CAAA,GAEI,GAAK0G,CAAAA,EAAIC,MAAMC,QAEnB,OADAtH,QAAQ4G,MAAM,IAAI1G,KAAQ,2BAA6BQ,CAAW,EAClE,CAAA,GAQA,IALI6G,EAAS,GACTC,EAAUjC,OAAOkC,KAAKL,EAAIC,MAAMC,OAAO,EAEvCI,EAAWF,EAAQ3D,OAAO,SAAAvD,GAAK,MAAA,CAACA,EAAEyD,SAAS,GAAG,CAAf,CAAgB,EAE1C9C,EAAI,EAAGA,EAAIgG,EAAiBvL,OAAQuF,CAAC,GAC7CsG,EAAOG,EAASzG,IAAMgG,EAAiBhG,GAGxC,IACCmG,EAAIC,MAAMM,SAASJ,CAAM,C,CAE1B,MAAOK,GACN,GAAIA,EAEH,OADA5H,QAAQ4G,MAAM,IAAI1G,KAAQ,uBAAyBQ,EAAc,IAAKkH,CAAM,EAC5E,CAAA,E,EA2EJ,MArEqB,WAAjBb,IACCc,EAAUd,EAAae,MAAM,GAAG,EAChCC,EAAY,GACZC,EAAUH,EAAQ,GAEH,KAAfA,EAAQ,KACXE,EAAY,IACZC,EAAUH,EAAQ,IAGnBE,GAAaC,EAEQ,EAAjBH,EAAQnM,SACXqM,GAAa,MAGVE,EAAiBpM,KAAKE,eAAe8H,OAAO,SAAAvD,GAAK,OAAAA,EAAEwB,QAAQQ,KAAK,SAAA/B,GAAK,OAAAA,EAAEwB,YAAcyC,EAAc,WAAwB,WAAnBjE,EAAEwG,cAAgD,MAAnBxG,EAAEwG,cAAwBxG,EAAEwG,eAAiBA,GAAgB,CAACxG,EAAEwG,aAAamB,WAAWH,CAAS,CAAnK,CAAoK,CAAxL,CAAyL,GAE3NrM,SAGlBuM,EAAetG,QAAQ,SAAAwG,GACtBA,EAASrG,QAAQ+B,OAAO,SAAAvD,GAAK,OAAAA,EAAEyB,YAAcyC,EAAc,SAA9B,CAA+B,EAAE7C,QAAQ,SAAAS,GACrEtE,EAAKsK,YAAYhG,EAAO2E,aAAc,IAAI7G,KAAQsE,EAAIpC,EAAOwC,UAAWuD,EAASzH,YAAayH,EAASlB,gBAAgB,CACxH,CAAC,CACF,CAAC,GAICrF,EAAM/F,KAAKE,eAAe8E,KAAK,SAAAP,GAAK,OAAAA,EAAEI,cAAgBA,GAAeP,KAAKC,UAAUE,EAAE2G,gBAAgB,IAAM9G,KAAKC,UAAU6G,CAAgB,CAAvG,CAAwG,GAI1IrF,EAAIE,QAAQQ,KAAK,SAAAhC,GAAK,OAAAA,EAAEyB,YAAcyC,EAAc,WAAKlE,EAAEsE,YAAcA,CAAnD,CAA4D,GACtFhD,EAAIE,QAAQqF,KAAK,CAChBkB,QAAS7D,EAAY,QACrBI,UAAWA,EACX7C,UAAWyC,EAAc,UACzBuC,aAAcA,C,CACd,EAKFlL,KAAKE,eAAeoL,KAAK,CACxBzG,YAAaA,EACbuG,iBAAkBA,EAClBnD,YAAajI,KAAKyM,0BAA0B5H,CAAW,EACvDoB,QAAS,CAAC,CACTuG,QAAS7D,EAAY,QACrBI,UAAWA,EACX7C,UAAWyC,EAAc,UACzBuC,aAAcA,C,GAEfwB,QAAS,EACTnE,QAAS,CAAA,EACTC,SAAU,CAAA,C,CACV,EAGGzC,EAAAA,GACE/F,KAAKE,eAAe8E,KAAK,SAAAP,GAAK,OAAAA,EAAEI,cAAgBA,GAAeP,KAAKC,UAAUE,EAAE2G,gBAAgB,IAAM9G,KAAKC,UAAU6G,CAAgB,CAAvG,CAAwG,EAGzIpL,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,UAAW0B,EAAIlB,YAAakB,EAAIwC,QAASxC,EAAIyC,SAAUzC,EAAIE,QAAQpG,MAAM,EAIlG,CAAA,EAAMG,KAAK2M,oBAAoB5G,EAAK4C,EAAII,CAAS,G,OAAjDzG,EAAAC,KAAA,E,iCAIWxC,oBAAAyC,UAAAoK,mBAAb,SAAgCjH,G,yHAC3BgD,EAAK3I,KAAKyC,kBAAkBiD,aAAaC,CAAK,IAG7CkH,EAAO,CACVxG,KAAK,EAAA3G,SAAAoN,mBAAiB,EACtBC,IAAK,EACLzH,KAAM,IAAIjB,KACVmI,QAAS7D,EAAY,QACrBkE,KAAMlE,EAAS,KACfhD,MAAOgD,EAAc,S,EAGtB3I,KAAKG,eAAemL,KAAKuB,CAAI,EAC7B,CAAA,EAAMlO,6BAAAoG,cAAciI,UAAUH,CAAI,IAX/B,CAAA,EAAA,G,OAaH,OAFAvK,EAAAC,KAAA,EAEA,CAAA,EAAOsK,G,OAGP,MAAM,IAAII,MAAM,uCAAuC,C,OAKlDlN,oBAAAyC,UAAA+J,YAAP,SAAmBrB,EAAsBC,EAAmBxC,EAAeI,EAAmBlE,EAAqBuG,GAGlH,GAFApL,KAAKc,iBAAmB,EAEnBd,KAAKC,cAAc4E,GAInB,CACJ,IAAIkB,EAAM/F,KAAKE,eAAe8E,KAAK,SAAAP,GAAK,OAAAA,EAAEI,cAAgBA,GAAeP,KAAKC,UAAUE,EAAE2G,gBAAgB,IAAM9G,KAAKC,UAAU6G,CAAgB,CAAvG,CAAwG,EAEhJ,GAAIrF,EAAK,CACR,IAAK,IAAIX,EAAIW,EAAIE,QAAQpG,OAAS,EAAQ,GAALuF,EAAQA,CAAC,GACzCW,EAAIE,QAAQb,GAAGoH,UAAY7D,EAAY,SAAK5C,EAAIE,QAAQb,GAAG2D,YAAcA,GAAahD,EAAIE,QAAQb,GAAGc,YAAcyC,EAAc,WACpI5C,EAAIE,QAAQE,OAAOf,EAAG,CAAC,EAIrBpF,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,QAAS0B,EAAIlB,YAAakB,EAAIwC,QAASxC,EAAIyC,SAAUzC,EAAIE,QAAQpG,MAAM,C,OAdjGsE,QAAQC,IAAI,mBAAqBS,CAAW,CAkB9C,EAIa9E,oBAAAyC,UAAAoD,eAAb,SAA4B+C,G,6HAC3B3I,KAAKe,oBAAsB,EAEvB4H,GAECA,EAAmB,eACtB,CAAA,IAIDA,EAAmB,eAAI,CAAA,EAE+C,GAAlE3I,KAAKG,eAAeqK,IAAI,SAAA/F,GAAK,OAAAA,EAAEkB,KAAF,CAAO,EAAEuH,QAAQvE,EAAc,SAAC,GAChE3I,KAAKG,eAAegG,OAAOnG,KAAKG,eAAeqK,IAAI,SAAA/F,GAAK,OAAAA,EAAEkB,KAAF,CAAO,EAAEuH,QAAQvE,EAAc,SAAC,EAAG,CAAC,EAG7F,CAAA,EAAMhK,6BAAAoG,cAAcqB,UAAU,CAAET,MAAOgD,EAAc,SAAC,CAAE,IAbrD,CAAA,EAAA,G,OAiBH,IAJArG,EAAAC,KAAA,EAEI4K,EAAWnN,KAAKE,eAAe8H,OAAO,SAAAvD,GAAK,OAAAA,EAAEwB,QAAQQ,KAAK,SAAA/B,GAAK,OAAAA,EAAE8H,UAAY7D,EAAY,SAAKjE,EAAEwB,YAAcyC,EAAc,SAA7D,CAA8D,CAAlF,CAAmF,EAEzHvD,EAAI+H,EAAStN,OAAS,EAAQ,GAALuF,EAAQA,CAAC,GAG1C,IAFIW,EAAMoH,EAAS/H,GAEVY,EAAID,EAAIE,QAAQpG,OAAS,EAAQ,GAALmG,EAAQA,CAAC,GACzCD,EAAIE,QAAQD,GAAGE,YAAcyC,EAAc,WAC9C5C,EAAIE,QAAQE,OAAOH,EAAG,CAAC,EAK1BhG,KAAKyC,kBAAkB2K,gBAAgBzE,CAAE,E,iCAIpC5I,oBAAAyC,UAAA6K,uBAAP,WACC,OAAOrN,KAAKE,cACb,EAGQH,oBAAAyC,UAAAiK,0BAAR,SAAkC5H,GACjC,OAAO7E,KAAKC,cAAc4E,GAAaoD,WACxC,EAGclI,oBAAAyC,UAAAyB,UAAd,SAAwBqJ,G,+HACnBtN,CAAAA,KAAKuN,SAAYvN,KAAKuN,QAAQC,OAA9B,CAAA,EAAA,IACHxN,KAAKuN,QAAQE,mBAAkB,EAC/B,CAAA,EAAMzN,KAAKuN,QAAQG,MAAK,I,OAAxBzI,EAAA1C,KAAA,EACAvC,KAAKuN,QAAU,K,iBAIhB,MAAA,CAAA,EAAM,IAAInE,QAAQ,SAAAC,GAAW,OAAAzB,WAAWyB,EAAS,GAAI,CAAxB,CAAyB,G,UAAtDpE,EAAA1C,KAAA,EAEKvC,KAAKuN,SAAWvN,CAAAA,KAAKuN,QAAQC,OAA9B,MAAA,CAAA,EAAA,I,GACHxN,KAAKoB,kBAAoB,EAEG,EAAxBpB,KAAKoB,mBACR+C,QAAQ4G,MAAM,4GAA4G,EAC1HhE,QAAQ4G,KAAK,CAAC,GAGTC,EAAW,CAChB,CACCC,OAAQ,CACPC,KAAM,CACL,CAACC,UAAW,CAAEC,KAAM,CACnB,uBACA,oBACA,OACA,WACA,qBACA,kBACA,4BACA,4BACA,mBACA,kBACA,CAAE,EACH,CAACD,UAAW,CAAEE,KAAM,eAAe,CAAE,EACrC,CAACF,UAAW,CAAEE,KAAM,WAAW,CAAE,E,KAQjCX,EAAA,MAAA,CAAA,EAAA,IACHY,EAAkBZ,E,8CAEjBtN,KAAKuN,QAAU9N,uBAAAiD,gBAAgByL,UAAS,EAAGC,MAAMR,EAAU,CAAES,YAAaf,CAAW,CAAE,E,6BAGnFtN,KAAKuN,UACRvN,KAAKuN,QAAQE,mBAAkB,EAC/B,CAAA,EAAMzN,KAAKuN,QAAQG,MAAK,IAFrB,CAAA,EAAA,G,OAEHzI,EAAA1C,KAAA,EACAvC,KAAKuN,QAAU,K,iBAGhB,MAAA,CAAA,EAAMvN,KAAKiE,UAAUqJ,CAAW,G,OAChC,OADArI,EAAA1C,KAAA,EACA,CAAA,G,4BAIDvC,KAAKuN,QAAU9N,uBAAAiD,gBAAgByL,UAAS,EAAGC,MAAMR,CAAQ,E,mBAG1DzJ,QAAQC,IAAI,IAAIC,KAAQ,eAAe,EAEvCrE,KAAKuN,QAAQe,GAAG,SAAU,SAAOC,GAAuH,OAAAnM,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,0EACnJsM,EAAIC,IACHxO,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,YAAakK,EAAIC,EAAE,EAGxC7J,EAAa4J,EAAIC,GAAGC,KAEnBzO,KAAKU,uBAAuB+F,KAAK,SAAAhC,GAAK,OAAAA,EAAEE,aAAe4J,EAAIC,GAAGC,MAAQhK,EAAEK,OAASyJ,EAAIG,aAA/C,CAA4D,EAQtG1O,KAAKU,uBAAuBsE,KAAK,SAAAP,GAAK,OAAAA,EAAEE,aAAe4J,EAAIC,GAAGC,MAAQhK,EAAEK,OAASyJ,EAAIG,aAA/C,CAA4D,EAAErD,MAAQ,EAP5GrL,KAAKU,uBAAuB4K,KAAK,CAChC3G,WAAY4J,EAAIC,GAAGC,KACnB3J,KAAMyJ,EAAIG,cACVrD,KAAM,C,CACN,EAME1G,GACH3E,KAAKW,iBAAmB,EAEE,WAAtB4N,EAAIG,cAAJ,CAAA,EAAA,GACgB,oBAAf/J,GACmC,0BAAlC3E,KAAK+B,aAAuB,SAA5B,CAAA,EAAA,IACHtC,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAGC,WAAWC,KAAKpP,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAI,yBAA0BJ,EAAIO,YAAiB,GAAC,EACvK,CAAA,EAAM9O,KAAKmH,oBAAoBxC,EAAY,QAAQ,KAPnD,CAAA,EAAA,KAlBD,CAAA,EAAA,I,OAyBCrC,EAAAC,KAAA,E,uBAIiB,qBAAfoC,EAAA,CAAA,EAAA,GACH,CAAA,EAAM3E,KAAKmH,oBAAoBxC,EAAY,QAAQ,G,OAAnDrC,EAAAC,KAAA,E,2CAG6B,WAAtBgM,EAAIG,eAAoD,YAAtBH,EAAIG,cAAtC,CAAA,EAAA,GACW,qBAAf/J,EAAA,CAAA,EAAA,GACH,CAAA,EAAM3E,KAAKmH,oBAAoBxC,EAAY,QAAQ,G,OAAnDrC,EAAAC,KAAA,E,2CAG6B,WAAtBgM,EAAIG,cAAJ,CAAA,EAAA,IACW,qBAAf/J,EAAA,CAAA,EAAA,IACH,CAAA,EAAM3E,KAAKmH,oBAAoBxC,EAAY,QAAQ,G,OAAnDrC,EAAAC,KAAA,E,yBAKgB,UAAfoC,EAAA,CAAA,EAAA,IACQ,CAAA,EAAMjG,kBAAAgI,MAAMC,QAAQ,CAAE7B,KAAM,cAAc,CAAE,G,SAAnD8B,EAAOtE,EAAAC,KAAA,IAECqE,EAAKC,MAChB7G,KAAKS,aAAe,CAAA,EAGpBT,KAAKS,aAAe,CAAA,E,mBAItByN,EAAkBK,EAAIlI,IAEhBU,QAAQC,IAAI+H,mBAAuD,MAAlChI,QAAQC,IAAI+H,mBAAkE,UAAnChI,QAAQC,IAAIC,oBAAsE,SAAnCF,QAAQC,IAAIgI,oBAAiCjI,QAAQC,IAAIiI,a,kCAI3L,EAEDjP,KAAKuN,QAAQe,GAAG,QAAS,SAAMvD,GAAK,OAAA3I,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,2DAEnC,OADAkC,QAAQC,IAAI,IAAIC,KAAQ,cAAe0G,CAAK,EAC5C,CAAA,EAAM/K,KAAKuN,QAAQG,MAAK,G,cAAxBpL,EAAAC,KAAA,E,SACA,EAEDvC,KAAKuN,QAAQe,GAAG,MAAO,WAAA,OAAAlM,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,2DAEtB,OADAkC,QAAQC,IAAI,IAAIC,KAAQ,WAAW,EACnC,CAAA,EAAMrE,KAAKuN,QAAQG,MAAK,G,cAAxBpL,EAAAC,KAAA,E,SACA,EAEDvC,KAAKuN,QAAQe,GAAG,QAAS,WAAA,OAAAlM,UAAAH,EAAA,KAAA,EAAA,KAAA,EAAA,W,2DAIxB,OAHAkC,QAAQC,IAAI,IAAIC,KAAQ,aAAa,EACrCrE,KAAKuN,QAAQE,mBAAkB,EAC/BzN,KAAKuN,QAAU,KACf,CAAA,EAAMvN,KAAKiE,UAAUiK,CAAe,G,cAApC5L,EAAAC,KAAA,E,SACA,E,mCAIWxC,oBAAAyC,UAAAmK,oBAAd,SAAkC5G,EAA8B4C,EAAeI,G,mHACzE/I,KAAKC,cAAc8F,EAAIlB,aAAa4D,cAArC,MAAA,CAAA,EAAA,G,IACC1C,EAAI2G,QAAJ,MAAA,CAAA,EAAA,G,8CAEEwC,EAAY5K,KAAK6K,MAAMnP,KAAK8C,WAAWwE,IAAIvB,EAAI2G,OAAO,EAAGhN,SAAA0P,WAAW,EAEpEC,EAAiC,CACpCtG,UAAWA,EACXuG,SAAU,CAAA,EACVC,KAAML,C,EAGHlP,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,qBAAsB0B,EAAIlB,WAAW,EAG9D7E,KAAKwP,OAAO7G,EAAI0G,CAAS,E,aAMzB,O,SAHArP,KAAK8C,WAAW2M,IAAI1J,EAAI2G,OAAO,EAC/B3G,EAAI2G,QAAU,EAEd,CAAA,EAAM1M,KAAKiJ,uBAAuBlD,EAAK,GAAI,QAAQ,G,cAAnDd,EAAA1C,KAAA,E,gCAQD,OAJIvC,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,2BAA4B0B,EAAIlB,YAAakB,EAAIwC,OAAO,EAG7ExC,EAAIwC,QACP,CAAA,GAGD,CAAA,EAAMvI,KAAKiJ,uBAAuBlD,EAAK,GAAI,QAAQ,G,OAAnDd,EAAA1C,KAAA,E,qCAQD,OAJIvC,KAAKS,cACR0D,QAAQC,IAAI,IAAIC,KAAQ,oCAAqC0B,EAAIlB,YAAakB,EAAIwC,OAAO,EAGtFxC,EAAIwC,QACP,CAAA,GAGD,CAAA,EAAMvI,KAAK8I,uBAAuBH,EAAII,EAAWhD,EAAK,GAAI,QAAQ,G,OAAlEd,EAAA1C,KAAA,E,mCAIYxC,oBAAAyC,UAAA+G,cAAd,SAA4BZ,EAAeI,EAAmBhD,EAA8BpB,EAAoBG,G,sHAC3G4K,EAAU1P,KAAK6C,wBAAwB8M,qBAAqB,4BAA6B5J,EAAIlB,YAAa,GAAI,GAAIkB,EAAIqF,gBAAgB,E,iBAI/H,O,uBAFV3L,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAGC,WAAWC,KAAKpP,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAI,wBAAyB7J,EAAMiB,EAAIlB,YAAaF,EAAYL,KAAKC,UAAUwB,EAAIqF,gBAAgB,CAAC,EAE7M,CAAA,GAAM9I,EAAAtC,KAAKC,cAAc8F,EAAIlB,aAAa+K,UAASf,KAAIgB,MAAAvN,EAAAwN,cAAA,CAACpG,OAAOC,OAAO,GAAI3J,KAAMD,oBAAoByC,SAAS,EAAGmG,EAAY,SAAC8B,OAAK1E,EAAIqF,gBAAgB,EAAA,CAAA,CAAA,CAAA,G,cAA5J2E,EAAM9K,EAAA1C,KAAA,EAEN8M,EAAiC,CACpCtG,UAAWA,EACXuG,SAAU,CAAA,EACVC,KAAMQ,C,EAGP/P,KAAKwP,OAAO7G,EAAI0G,CAAS,E,aAWzB,O,WARIA,EAAiC,CACpCtG,UAAWA,EACXuG,SAAU,CAAA,EACVC,KAAMS,C,EAGPhQ,KAAKwP,OAAO7G,EAAI0G,CAAS,EAEzB,CAAA,EAAM5P,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAGsB,UAAU,oBAAqB,6BAA+BjQ,KAAK+B,aAA0B,YAAG,sCAAwCgE,EAAIlB,YAAc,qCAAuCP,KAAKC,UAAUwB,EAAIqF,iBAAkB,KAAM,CAAC,EAAI,eAAiB9G,KAAKC,UAAUyL,EAAK,KAAM,CAAC,CAAC,G,cAAvV/K,EAAA1C,KAAA,E,aAGA,MAAA,CAAA,EAAMvC,KAAK6C,wBAAwBqN,sBAAsBR,CAAO,G,cAAhEzK,EAAA1C,KAAA,E,2BAKYxC,oBAAAyC,UAAA8G,cAAd,SAA4BvD,EAA8BpB,EAAoBG,G,4KACxEiB,EAAIE,QAAQpG,OAAb,CAAA,EAAA,IACCkG,EAAI2G,UACP1M,KAAK8C,WAAW2M,IAAI1J,EAAI2G,OAAO,EAC/B3G,EAAI2G,QAAU,GAIC,IADZyD,EAAWnQ,KAAKE,eAAeoG,UAAU,SAAA7B,GAAK,OAAAA,EAAEI,cAAgBkB,EAAIlB,aAAeP,KAAKC,UAAUE,EAAE2G,gBAAgB,IAAM9G,KAAKC,UAAUwB,EAAIqF,gBAAgB,CAA/G,CAAgH,IAEjKpL,KAAKE,eAAeiG,OAAOgK,EAAU,CAAC,EAGvC,CAAA,I,OAGIT,EAAU1P,KAAK6C,wBAAwB8M,qBAAqB,cAAe5J,EAAIlB,YAAa,GAAI,GAAIkB,EAAIqF,gBAAgB,E,iBAOjH,O,uBAJc,kBAApBrF,EAAIlB,aAAuD,kBAApBkB,EAAIlB,aAC9CpF,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAGC,WAAWC,KAAKpP,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAI,wBAAyB7J,EAAMiB,EAAIlB,YAAaF,EAAYL,KAAKC,UAAUwB,EAAIqF,gBAAgB,CAAC,EAG9M,CAAA,GAAMgF,EAAApQ,KAAKC,cAAc8F,EAAIlB,aAAa+K,UAASf,KAAIgB,MAAAO,EAAAN,cAAA,CAACpG,OAAOC,OAAO,GAAI3J,KAAMD,oBAAoByC,SAAS,GAACiI,OAAK1E,EAAIqF,gBAAgB,EAAA,CAAA,CAAA,CAAA,G,OAEjJ,GAFIiF,EAAMC,EAAA/N,KAAA,EAENwD,EAAI2G,QACP,IAGC,GAFIwC,EAAY5K,KAAK6K,MAAMnP,KAAK8C,WAAWwE,IAAIvB,EAAI2G,OAAO,EAAGhN,SAAA0P,WAAW,EAEpE9K,KAAKC,UAAU2K,CAAS,IAAM5K,KAAKC,UAAU8L,CAAG,EAAG,C,IACtD,IAAmB/N,EAAA8F,SAAArC,EAAIE,OAAO,EAAAhB,EAAA3C,EAAAgG,KAAA,EAAA,CAAArD,EAAAsL,KAAAtL,EAAA3C,EAAAgG,KAAA,EAArB/B,EAAMtB,EAAA4B,OACV8B,EAAK3I,KAAKyC,kBAAkBiD,aAAaa,EAAOL,SAAS,IACnDyC,EAAGC,aAAeD,EAAGE,OAC1BwG,EAAiC,CACpCtG,UAAWxC,EAAOwC,UAClBuG,SAAU,CAAA,EACVC,KAAMc,C,EAGPrQ,KAAKwP,OAAO7G,EAAI0G,CAAS,E,kGAI3BrP,KAAK8C,WAAW2M,IAAI1J,EAAI2G,OAAO,GAE3B,EAAAhN,SAAA8Q,eAAclM,KAAKC,UAAU8L,CAAG,CAAC,EAAI,KACxC,CAACtK,EAAIkC,YAAYC,SAAS,MAAM,GAChC,CAACnC,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAEgM,SAAS,WAAW,CAAtB,CAAuB,GAClD,CAAC1K,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAE4H,WAAW,UAAU,CAAvB,CAAwB,EAEnDrM,KAAK8C,WAAWyE,IAAIxB,EAAI2G,QAASpI,KAAKC,UAAU8L,CAAG,CAAC,EAGpDtK,EAAI2G,QAAU,C,EAIjB,MAAAgE,GACC3K,EAAIE,QAAQuE,IAAI,SAAAjE,GACf,IAAIoC,EAAK1G,EAAKQ,kBAAkBiD,aAAaa,EAAOL,SAAS,EACzDyC,GAAMA,EAAGC,aAAeD,EAAGE,OAC1BwG,EAAiC,CACpCtG,UAAWxC,EAAOwC,UAClBuG,SAAU,CAAA,EACVC,KAAMc,C,EAGPpO,EAAKuN,OAAO7G,EAAI0G,CAAS,EAE3B,CAAC,EAEDrP,KAAK8C,WAAW2M,IAAI1J,EAAI2G,OAAO,GAE3B,EAAAhN,SAAA8Q,eAAclM,KAAKC,UAAU8L,CAAG,CAAC,EAAI,KACxC,CAACtK,EAAIkC,YAAYC,SAAS,MAAM,GAChC,CAACnC,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAEgM,SAAS,WAAW,CAAtB,CAAuB,GAClD,CAAC1K,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAE4H,WAAW,UAAU,CAAvB,CAAwB,EAEnDrM,KAAK8C,WAAWyE,IAAIxB,EAAI2G,QAASpI,KAAKC,UAAU8L,CAAG,CAAC,EAGpDtK,EAAI2G,QAAU,C,KAIZ,C,IACJ,IAAmB7G,EAAAuC,SAAArC,EAAIE,OAAO,EAAA0K,EAAA9K,EAAAyC,KAAA,EAAA,CAAAqI,EAAAJ,KAAAI,EAAA9K,EAAAyC,KAAA,EAArB/B,EAAMoK,EAAA9J,OACV8B,EAAK3I,KAAKyC,kBAAkBiD,aAAaa,EAAOL,SAAS,IACnDyC,EAAGC,aAAeD,EAAGE,OAC1BwG,EAAiC,CACpCtG,UAAWxC,EAAOwC,UAClBuG,SAAU,CAAA,EACVC,KAAMc,C,EAGPrQ,KAAKwP,OAAO7G,EAAI0G,CAAS,E,kGAI3B,IAAI,EAAA3P,SAAA8Q,eAAclM,KAAKC,UAAU8L,CAAG,CAAC,EAAI,KACxC,CAACtK,EAAIkC,YAAYC,SAAS,MAAM,GAChC,CAACnC,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAEgM,SAAS,WAAW,CAAtB,CAAuB,GAClD,CAAC1K,EAAIkC,YAAYjD,KAAK,SAAAP,GAAK,OAAAA,EAAE4H,WAAW,UAAU,CAAvB,CAAwB,GAOnD,GALAtG,EAAI2G,QAAU1M,KAAKM,QAAQ,GAC3BN,KAAK8C,WAAWyE,IAAIxB,EAAI2G,QAASpI,KAAKC,UAAU8L,CAAG,CAAC,GAE9CO,EAAgB5Q,KAAK8C,WAAW+N,SAAQ,EAAGC,OAE7B9Q,KAAKkH,WAAY,CAKpC,IAHI6J,EAAc,EACZC,EAAShR,KAAKE,eAAe8H,OAAO,SAAAvD,GAAK,OAAAA,EAAEiI,SAAW,CAACjI,EAAEwB,QAAQpG,MAAxB,CAA8B,EAEpEoR,EAAK,EAAGA,EAAKD,EAAOnR,SAC5BG,KAAKmB,uBAAyB,EAC9BnB,KAAK8C,WAAW2M,IAAIuB,EAAOC,GAAIvE,OAAO,EACtCsE,EAAOC,GAAIvE,QAAU,EACrBqE,GAAe,EACX/Q,EAAAA,KAAK8C,WAAW+N,SAAQ,EAAGC,MAA0B,IAAlB9Q,KAAKkH,aALR+J,CAAE,IAUnCjR,KAAKS,cACR0D,QAAQC,IACP,wBAEA2B,EAAIlB,YACJ,eACAkM,EACA,MACAH,CAAa,C,OAMhB7K,EAAI2G,QAAU,C,mCAKhB,IAAmBwE,EAAA9I,SAAArC,EAAIE,OAAO,EAAA+C,EAAAkI,EAAA5I,KAAA,EAAA,CAAAU,EAAAuH,KAAAvH,EAAAkI,EAAA5I,KAAA,EAArB/B,EAAMyC,EAAAnC,OACV8B,EAAK3I,KAAKyC,kBAAkBiD,aAAaa,EAAOL,SAAS,IACnDyC,EAAGC,aAAeD,EAAGE,OAC1BwG,EAAiC,CACpCtG,UAAWxC,EAAOwC,UAClBuG,SAAU,CAAA,EACVC,KAAM4B,C,EAGPnR,KAAKwP,OAAO7G,EAAI0G,CAAS,E,kGAI3B,MAAA,CAAA,EAAM5P,uBAAAiD,gBAAgBC,cAAa,EAAGgM,iBAAgB,EAAGsB,UAAU,oBAAqB,6BAA+BjQ,KAAK+B,aAA0B,YAAG,sCAAwCgE,EAAIlB,YAAc,8BAAgCP,KAAKC,UAAUwB,EAAIqF,iBAAkB,KAAM,CAAC,EAAI,eAAiB9G,KAAKC,UAAU4M,EAAK,KAAM,CAAC,CAAC,G,cAAhVb,EAAA/N,KAAA,E,aAGA,MAAA,CAAA,EAAMvC,KAAK6C,wBAAwBqN,sBAAsBR,CAAO,G,cAAhEY,EAAA/N,KAAA,E,2BAKKxC,oBAAAyC,UAAAgN,OAAR,SAAe7G,EAAe4G,GAC7BvP,KAAKyC,kBAAkB2O,KAAKzI,EAAI4G,CAAI,CACrC,EAEOxP,oBAAAyC,UAAA0B,eAAP,WACC,OAAOlE,KAAKS,YACb,EACDV,mBAAA,EAAC,EAh/BYsR,QAAAtR,oBAAAA","file":"subscription.manager.js","sourcesContent":["import { ChangeStream, ChangeStreamDeleteDocument, ChangeStreamInsertDocument, ChangeStreamReplaceDocument, ChangeStreamUpdateDocument, ResumeToken } from 'mongodb';\nimport * as NodeCache from 'node-cache';\nimport { cpus } from 'os';\nimport * as WebSocket from 'ws';\nimport { Flags } from '../collections/flag.collection';\nimport { LoggedInUsers } from '../collections/logged-in-users.collection';\nimport { LoggedInUserModel } from '../models/logged-in-users.model';\nimport { ServerResponseModel } from '../models/server-message.model';\nimport { ActiveSubscriptionModel, SubscriptionModel } from '../models/subscription.model';\nimport { loadAppStatusPublications } from '../publications/app-status';\nimport { loadCronJobPublications } from '../publications/cron-jobs';\nimport { loadFilePublications } from '../publications/files';\nimport { loadFlagsPublications } from '../publications/flags';\nimport { loadFlagsUpdatePublications } from '../publications/flags-update';\nimport { loadLogPublications } from '../publications/logs';\nimport { loadNotificationPublications } from '../publications/notifications';\nimport { loadReportBuilderDashboardBuilderPublications } from '../publications/report-builder-dashboard-builders';\nimport { loadReportBuilderLibraryPublications } from '../publications/report-builder-libraries';\nimport { loadReportBuilderReportPublications } from '../publications/report-builder-reports';\nimport { loadSuperAdminPublications } from '../publications/super-admin';\nimport { loadUserGroupPublications } from '../publications/user-groups';\nimport { loadUserGuidePublications } from '../publications/user-guides';\nimport { ResolveIOServer } from '../resolveio-server-app';\nimport { dateReviver, deepCopy, getBinarySize, objectIdHexString } from '../util/common';\nimport { MonitorManagerFunction } from './monitor.manager';\nimport { WebSocketManager } from './websocket.manager';\nconst numCPUs = cpus().length;\nconst v8 = require('v8');\n\n// Performance Dependencies\n// import * as path from 'path';\n// import { Worker } from 'worker_threads';\n\ninterface MongoQueueModel {\n\t_id: number,\n\ttype: string;\n\tcollection: string;\n\tsubscription: ActiveSubscriptionModel;\n\trunning: boolean;\n\trun_again: boolean;\n}\n\n// interface CurrentPerformanceMonitor {\n// \t_id: number;\n// \tfunction: string;\n// \tpublication: string;\n// \tsubscriptionData: any[];\n// \tdate_start: Date;\n// \tdate_end: Date;\n// \tduration: number;\n// \tresult: string;\n// }\n\nexport class SubscriptionManager {\n\tprivate _websocketManager: WebSocketManager;\n\tprivate _publications: SubscriptionModel = {};\n\tprivate _subscriptions: ActiveSubscriptionModel[] = [];\n\tprivate _wss: WebSocket.Server;\n\tprivate _loggedInUsers: LoggedInUserModel[] = [];\n\n\tprivate _mongoQueue: MongoQueueModel[] = [];\n\tprivate _mongoQueueId = 0;\n\t\n\tprivate _oplog$: ChangeStream;\n\n\tprivate _nodeCache;\n\tprivate _cacheId = 1;\n\n\tprivate _heapSize = v8.getHeapStatistics() / numCPUs;\n\tprivate _heapLimit: number;\n\n\tprivate serverConfig;\n\n\tprivate _monitorManagerFunction: MonitorManagerFunction;\n\n\tprivate _enableDebug = false;\n\tprivate _debugOplogCollections = [];\n\tprivate _debugOplogHits = 0;\n\tprivate _debugSubCollections = [];\n\tprivate _debugSubHits = 0;\n\tprivate _debugUnSubHits = 0;\n\tprivate _debugUnSubAllHits = 0;\n\tprivate _debugMongoQueueHits = 0;\n\tprivate _debugMongoQueueCollections = [];\n\tprivate _debugSendQueueHits = 0;\n\tprivate _debugRemoveCacheHits = 0;\n\n\tprivate _oplogRetryCount = 0;\n\n\t// Buffer to store throttled latency updates with timestamps\n\tprivate latencyBuffer = new Map<string, { latency: number, lastUpdate: Date }>();\n\n\t// Interval to flush latency updates in MongoDB\n\tprivate readonly LATENCY_UPDATE_INTERVAL = 60000;\n\n\t// Minimum time difference between two latency updates for the same user\n\tprivate readonly LATENCY_UPDATE_THRESHOLD_MS = 30000;\n\n\t// private currentPerfomanceMonitor: CurrentPerformanceMonitor[] = [];\n\t// private idPerformance: number = 0;\n\t// private performanceThread;\n\n\tprivate _invalidationDebounceTimers = new Map<string, NodeJS.Timeout>();\n\tprivate _invalidationPendingTimestamps = new Map<string, number>();\n\tprivate readonly DEBOUNCE_DELAY = 100; // 100ms debounce window\n\tprivate readonly MAX_WAIT_TIME = 500; // 500ms maximum delay\n\n\n\tconstructor() {}\n\t\n\tstatic create(wss: WebSocket.Server, serverConfig, monitorManagerFunction: MonitorManagerFunction) {\n\t\tconst subscriptionManager = new SubscriptionManager();\n\t\tsetImmediate(async () => {\n\t\t\tawait subscriptionManager.initialize(wss, serverConfig, monitorManagerFunction);\n\t\t});\n\t\treturn subscriptionManager;\n\t}\n\t\n\tprivate async initialize(wss: WebSocket.Server, serverConfig, monitorManagerFunction: MonitorManagerFunction) {\n\t\tthis._websocketManager = ResolveIOServer.getMainServer().getWebSocketManager();\n\t\tthis._monitorManagerFunction = monitorManagerFunction;\n\n\t\tthis._nodeCache = new NodeCache( { stdTTL: 0, checkperiod: 0 } );\n\n\t\tsetInterval(() => this.flushThrottledLatencyUpdates(), this.LATENCY_UPDATE_INTERVAL);\n\n\t\t// setTimeout(() => {\n\t\t// \tconsole.log('Setting up performance thread');\n\n\t\t// \tthis.performanceThread = new Worker(path.join(__dirname, './subscription.performance.js'));\n\n\t\t// \tthis.performanceThread.on('exit', code => {\n\t\t// \t\tconsole.error(new Date(), 'THREAD EXITED!!!!!!!!!!!!!!!!!!', code);\n\t\t// \t});\n\n\t\t// \tthis.performanceThread.on('error', code => {\n\t\t// \t\tconsole.error(new Date(), 'THREAD RECV ERROR !!!!!!!!!!!!!!!!!!', code);\n\t\t// \t});\n\t\t// }, 5000);\n\n\t\t// setInterval(() => {\n\t\t// \tconsole.log('Post thread msg');\n\t\t// \tthis.performanceThread.postMessage(this.currentPerfomanceMonitor);\n\t\t// \tthis.currentPerfomanceMonitor = [];\n\t\t// }, 10000);\n\n\t\tthis.serverConfig = serverConfig;\n\t\tthis._wss = wss;\n\n\t\t// Publications\n\t\tloadSuperAdminPublications(this);\n\t\tloadAppStatusPublications(this);\n\t\tloadLogPublications(this);\n\t\tloadFilePublications(this);\n\t\tloadCronJobPublications(this);\n\t\tloadFlagsUpdatePublications(this);\n\t\tloadFlagsPublications(this);\n\t\tloadNotificationPublications(this);\n\t\tloadReportBuilderReportPublications(this);\n\t\tloadReportBuilderLibraryPublications(this);\n\t\tloadUserGroupPublications(this);\n\t\tloadUserGuidePublications(this);\n\t\tloadReportBuilderDashboardBuilderPublications(this);\n\n\t\tawait this.tailOpLog();\n\n\t\tsetInterval(() => {\n\t\t\tthis._oplogRetryCount = 0;\n\t\t}, 15000);\n\n\t\tsetInterval(() => {\n\t\t\tif (this.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Subs', this._subscriptions.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Logged In Users', this._loggedInUsers.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue', this._mongoQueue.length);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue Hits', this._debugMongoQueueHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Mongo Queue Collections', JSON.stringify(this._debugMongoQueueCollections.sort((a, b) => a.collection.localeCompare(b.collection) || a.publication.localeCompare(b.publication)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Oplog Hits', this._debugOplogHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Oplog Collections', JSON.stringify(this._debugOplogCollections.sort((a, b) => a.collection.localeCompare(b.collection) || a.type.localeCompare(b.type)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Send Queue Hits', this._debugSendQueueHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Sub Hits', this._debugSubHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Sub Collections', JSON.stringify(this._debugSubCollections.sort((a, b) => a.publication.localeCompare(b.publication)), null, 2));\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub Hits', this._debugUnSubHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub All Hits', this._debugUnSubAllHits);\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Cache Cleanup Hits', this._debugRemoveCacheHits);\n\t\t\t}\n\t\t\t\n\t\t\tthis._debugOplogHits = 0;\n\t\t\tthis._debugOplogCollections = [];\n\t\t\tthis._debugSubCollections = [];\n\t\t\tthis._debugMongoQueueHits = 0;\n\t\t\tthis._debugMongoQueueCollections = [];\n\t\t\tthis._debugSendQueueHits = 0;\n\t\t\tthis._debugSubHits = 0;\n\t\t\tthis._debugUnSubHits = 0;\n\t\t\tthis._debugUnSubAllHits = 0;\n\t\t\tthis._debugRemoveCacheHits = 0;\n\t\t}, 60000);\n\n\t\tsetInterval(async () => {\n\t\t\tthis._loggedInUsers = await LoggedInUsers.find();\n\t\n\t\t\tlet userCopy = deepCopy(this._loggedInUsers);\n\t\t\tfor (let i = this._loggedInUsers.length - 1; i >= 0; i--) {\n\t\t\t\tlet loggedInUser = userCopy[i];\n\n\t\t\t\tif (!loggedInUser.date || Date.now() - loggedInUser.date.getTime() > 120000) {\n\t\t\t\t\tif (this._websocketManager.getWebSocket(loggedInUser.id_ws)) {\n\t\t\t\t\t\tif (this.getEnableDebug()) {\n\t\t\t\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Unsub WS', this._websocketManager.getWebSocket(loggedInUser.id_ws)['user'], this._websocketManager.getWebSocket(loggedInUser.id_ws)['id_socket'], 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.unsubscribeAll(this._websocketManager.getWebSocket(loggedInUser.id_ws));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._subscriptions.forEach(sub => {\n\t\t\t\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\t\t\t\tlet client = sub.clients[j];\n\n\t\t\t\t\t\t\t\tif (client.id_socket === loggedInUser.id_ws) {\n\t\t\t\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait LoggedInUsers.deleteOne({_id: loggedInUser._id});\n\n\t\t\t\t\t\tif (this._loggedInUsers.findIndex(a => a._id === loggedInUser._id) >= 0) {\n\t\t\t\t\t\t\tthis._loggedInUsers.splice(this._loggedInUsers.findIndex(a => a._id === loggedInUser._id), 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < this._subscriptions.length; i++) {\n\t\t\t\tlet sub = this._subscriptions[i];\n\n\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\tlet client = sub.clients[j];\n\n\t\t\t\t\tif (!this._loggedInUsers.some(a => a.id_ws === client.id_socket)) {\n\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, 30000);\n\n\t\tlet flag = await Flags.findOne({type: 'Enable Debug'});\n\n\t\tif (flag && flag.value) {\n\t\t\tthis._enableDebug = true;\n\t\t}\n\t\telse {\n\t\t\tthis._enableDebug = false;\n\t\t}\n\n\t\tthis.setCacheLimit();\n\t}\n\n\tprivate setCacheLimit() {\t\n\t\tif (process.env.IS_WORKERS_ENABLED === 'true') {\n\t\t\tthis._heapLimit = this._heapSize * 0.4;\n\t\t}\n\t\telse {\n\t\t\tthis._heapLimit = this._heapSize * 0.3; // Use 50% of total heap size\n\t\t}\n\t}\n\n\tpublic async invalidatePubsCache(collection: string, type: string) {\n\t\tconst debounceKey = collection;\n\t\tconst now = Date.now();\n\t\n\t\t// Initialize or get existing timestamp\n\t\tconst firstInvalidationTime = this._invalidationPendingTimestamps.get(debounceKey) || now;\n\t\tthis._invalidationPendingTimestamps.set(debounceKey, firstInvalidationTime);\n\t\n\t\t// Clear any existing timer\n\t\tif (this._invalidationDebounceTimers.has(debounceKey)) {\n\t\t\tclearTimeout(this._invalidationDebounceTimers.get(debounceKey));\n\t\t}\n\t\n\t\t// Check if we've waited too long\n\t\tconst waitedTooLong = (now - firstInvalidationTime) >= this.MAX_WAIT_TIME;\n\t\t\n\t\tif (waitedTooLong) {\n\t\t\t// Immediate execution path\n\t\t\tthis._invalidationPendingTimestamps.delete(debounceKey);\n\t\t\tawait this._executeInvalidation(collection, type);\n\t\t} else {\n\t\t\t// Normal debounce path\n\t\t\tthis._invalidationDebounceTimers.set(\n\t\t\t\tdebounceKey,\n\t\t\t\tsetTimeout(async () => {\n\t\t\t\t\tthis._invalidationPendingTimestamps.delete(debounceKey);\n\t\t\t\t\tawait this._executeInvalidation(collection, type);\n\t\t\t\t}, this.DEBOUNCE_DELAY)\n\t\t\t);\n\t\t}\n\t}\n\t\n\tprivate async _executeInvalidation(collection: string, type: string) {\n\t\t// Clean up any existing timer (defensive)\n\t\tif (this._invalidationDebounceTimers.has(collection)) {\n\t\t\tclearTimeout(this._invalidationDebounceTimers.get(collection));\n\t\t\tthis._invalidationDebounceTimers.delete(collection);\n\t\t}\n\t\n\t\t// Original invalidation logic\n\t\tResolveIOServer.getMongoManager().invalidateQueryCache(collection);\n\t\n\t\tconst collSubs = this._subscriptions.filter(a => a.collections.includes(collection));\n\t\n\t\tfor (const sub of collSubs) {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Invalidate Sub', sub.publication, sub.running, sub.runAgain);\n\t\t\t}\n\t\n\t\t\tif (sub.running) {\n\t\t\t\tsub.runAgain = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\n\t\t\tif (this._publications[sub.publication].user_specific) {\n\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\tconst ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\tif (ws?.readyState === ws.OPEN) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch {\n\t\t\t\t\t\t\t// Error handling\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tawait this.sendDataToAllWithRetry(sub, collection, type);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async delay(ms: number) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\treturn new Promise(resolve => setTimeout(resolve, ms));\n\t}\n\n\tprivate async sendDataToAllWithRetry(sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tsub.running = true;\n\n\t\tdo {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Running sendDataToAll Sub', sub.publication);\n\t\t\t}\n\n\t\t\tsub.runAgain = false;\n\t\t\tawait this.sendDataToAll(sub, collection, type);\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Done sendDataToAll Sub', sub.publication, sub.runAgain);\n\t\t\t}\n\n\t\t\tif (sub.runAgain) {\n\t\t\t\tawait this.delay(500); // delay, adjust as needed\n\t\t\t}\n\t\t} while (sub.runAgain);\n\n\t\tsub.running = false;\n\t}\n\n\tprivate async sendDataToOneWithRetry(ws: WebSocket, messageId: number, sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tsub.running = true;\n\n\t\tdo {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Running sendDataToOne Sub', sub.publication);\n\t\t\t}\n\n\t\t\tsub.runAgain = false;\n\t\t\tawait this.sendDataToOne(ws, messageId, sub, collection, type);\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Done sendDataToOne Sub', sub.publication, sub.runAgain);\n\t\t\t}\n\n\t\t\tif (sub.runAgain) {\n\t\t\t\tawait this.delay(500); // delay, adjust as needed\n\t\t\t}\n\t\t} while (sub.runAgain);\n\t\tsub.running = false;\n\t}\n\n\t// Add all files to publications private object\n\tpublic publications(method: SubscriptionModel) {\n\t\tthis._publications = Object.assign(this._publications, method);\n\t}\n\n\t// Throttled `loggedInLatency` method\n\tpublic loggedInLatency(ws: WebSocket) {\n\t\tlet loggedInUser = this._loggedInUsers.find(a => a.id_ws === ws['id_socket']);\n\t\tif (!loggedInUser) return;\n\n\t\tconst now = new Date();\n\t\tconst existingEntry = this.latencyBuffer.get(ws['id_socket']);\n\t\tconst newLatency = ws['latency'];\n\n\t\t// Throttle updates: only update if time threshold has passed or latency has significantly changed\n\t\tif (\n\t\t\t!existingEntry || \n\t\t\t(now.getTime() - existingEntry.lastUpdate.getTime() >= this.LATENCY_UPDATE_THRESHOLD_MS) || \n\t\t\t(Math.abs(newLatency - existingEntry.latency) > 100) // Optional: log only significant changes\n\t\t) {\n\t\t\t// Update in-memory and buffer\n\t\t\tloggedInUser.date = now;\n\t\t\tthis.latencyBuffer.set(ws['id_socket'], { latency: newLatency, lastUpdate: now });\n\t\t}\n\t}\n\n\t// Method to flush buffered latency updates in bulk\n\tprivate async flushThrottledLatencyUpdates() {\n\t\tif (this.latencyBuffer.size === 0) return; // No updates to flush\n\n\t\tconst updates = Array.from(this.latencyBuffer.entries()).map(([id_ws, { latency, lastUpdate }]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { id_ws },\n\t\t\t\tupdate: { $set: { latency, date: lastUpdate } }\n\t\t\t}\n\t\t}));\n\n\t\ttry {\n\t\t\tawait LoggedInUsers.bulkWrite(updates);\n\t\t\tthis.latencyBuffer.clear(); // Clear buffer after successful update\n\n\t\t\tif (this.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'Sub Manager', 'Throttled latency batch update successful', updates.length);\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tconsole.error(new Date(), 'Sub Manager', 'Throttled latency batch update failed', error);\n\t\t\t// Optional: implement retry logic or logging for failed updates\n\t\t}\n\t}\n\n\t// Subscribe to publication\n\tpublic async subscribe(messageRoute: string, messageDate: Date, ws: WebSocket, messageId: number, publication: string, subscriptionData: any[]) {\n\t\tthis._debugSubHits += 1;\n\n\t\tif (!this._debugSubCollections.some(a => a.publication === publication)) {\n\t\t\tthis._debugSubCollections.push({\n\t\t\t\tpublication: publication,\n\t\t\t\thits: 1\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tthis._debugSubCollections.find(a => a.publication === publication).hits += 1;\n\t\t}\n\n\t\tlet pub = this._publications[publication];\n\n\t\tif (!pub) {\n\t\t\tconsole.error(new Date(), 'No Publication: ' + publication);\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tif (subscriptionData.length > 1 || subscriptionData[0]) {\n\t\t\t\tif (!pub.check) {\n\t\t\t\t\tconsole.error(new Date(), 'No Check Function For Pub ' + publication);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse if (!pub.check._schema) {\n\t\t\t\t\tconsole.error(new Date(), 'No Check Schema For Pub ' + publication);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlet valObj = {};\n\t\t\t\t\tlet valKeys = Object.keys(pub.check._schema);\n\n\t\t\t\t\tlet rootKeys = valKeys.filter(a => !a.includes('.'));\n\n\t\t\t\t\tfor (let i = 0; i < subscriptionData.length; i++) {\n\t\t\t\t\t\tvalObj[rootKeys[i]] = subscriptionData[i];\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpub.check.validate(valObj);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (errors) {\n\t\t\t\t\t\tif (errors) {\n\t\t\t\t\t\t\tconsole.error(new Date(), 'Error in Pub Check (' + publication + ')', errors);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (messageRoute !== 'Bypass') {\n\t\t\t\tlet urlData = messageRoute.split('/');\n\t\t\t\tlet urlModule = '';\n\t\t\t\tlet urlNext = urlData[0];\n\n\t\t\t\tif (urlData[0] === '') {\n\t\t\t\t\turlModule = '/';\n\t\t\t\t\turlNext = urlData[1];\n\t\t\t\t}\n\n\t\t\t\turlModule += urlNext;\n\n\t\t\t\tif (urlData.length > 1) {\n\t\t\t\t\turlModule += '/';\n\t\t\t\t}\n\n\t\t\t\tlet otherRouteSubs = this._subscriptions.filter(a => a.clients.some(b => b.id_socket === ws['id_socket'] && b.messageRoute !== 'Bypass' && b.messageRoute !== '/' && b.messageRoute !== messageRoute && !b.messageRoute.startsWith(urlModule)));\n\n\t\t\t\tif (otherRouteSubs.length) {\n\t\t\t\t\t// ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Detected Undestroyed Subscription - ' + this.serverConfig['CLIENT_NAME'], 'USER: ' + ws['user'] + ' (Socket: ' + ws['id_socket'] + ') ' + ' is on route: ' + messageRoute + ' but has the following subscriptions on other routes:' + JSON.stringify(otherRouteSubs, null, 2));\n\n\t\t\t\t\totherRouteSubs.forEach(otherSub => {\n\t\t\t\t\t\totherSub.clients.filter(a => a.id_socket === ws['id_socket']).forEach(client => {\n\t\t\t\t\t\t\tthis.unsubscribe(client.messageRoute, new Date(), ws, client.messageId, otherSub.publication, otherSub.subscriptionData);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\n\t\t\t// If sub found (another user watching same data), add client to same sub\n\t\t\tif (sub) {\n\t\t\t\tif (!sub.clients.some(a => a.id_socket === ws['id_socket'] && a.messageId === messageId)) {\n\t\t\t\t\tsub.clients.push({\n\t\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\tid_socket: ws['id_socket'],\n\t\t\t\t\t\tmessageRoute: messageRoute\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If sub not found, create new sub\n\t\t\telse {\n\t\t\t\tthis._subscriptions.push({\n\t\t\t\t\tpublication: publication,\n\t\t\t\t\tsubscriptionData: subscriptionData,\n\t\t\t\t\tcollections: this.getPublicationCollections(publication),\n\t\t\t\t\tclients: [{\n\t\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\tid_socket: ws['id_socket'],\n\t\t\t\t\t\tmessageRoute: messageRoute,\n\t\t\t\t\t}],\n\t\t\t\t\tcacheId: 0,\n\t\t\t\t\trunning: false,\n\t\t\t\t\trunAgain: false\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!sub) {\n\t\t\t\tsub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\t\t\t}\n\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'New Sub', sub.publication, sub.running, sub.runAgain, sub.clients.length);\n\t\t\t}\n\n\t\t\t// Immediately send data to the new client\n\t\t\tawait this.processSubscription(sub, ws, messageId);\n\t\t}\n\t}\n\n\tpublic async createLoggedInUser(id_ws: string): Promise<LoggedInUserModel> {\n\t\tlet ws = this._websocketManager.getWebSocket(id_ws);\n\n\t\tif (ws) {\n\t\t\tlet user = {\n\t\t\t\t_id: objectIdHexString(),\n\t\t\t\t__v: 0,\n\t\t\t\tdate: new Date(),\n\t\t\t\tid_user: ws['id_user'],\n\t\t\t\tuser: ws['user'],\n\t\t\t\tid_ws: ws['id_socket']\n\t\t\t};\n\t\t\t\n\t\t\tthis._loggedInUsers.push(user);\n\t\t\tawait LoggedInUsers.insertOne(user);\n\t\t\t\n\t\t\treturn user;\n\t\t}\n\t\telse {\n\t\t\tthrow new Error('Error in Create Logged In User: No WS');\n\t\t}\n\t}\n\n\t// Unsubscribe from publication \n\tpublic unsubscribe(messageRoute: string, messageDate: Date, ws: WebSocket, messageId: number, publication: string, subscriptionData: any[]) {\t\t\n\t\tthis._debugUnSubHits += 1;\n\n\t\tif (!this._publications[publication]) {\n\t\t\tconsole.log('No Publication: ' + publication);\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tlet sub = this._subscriptions.find(a => a.publication === publication && JSON.stringify(a.subscriptionData) === JSON.stringify(subscriptionData));\n\n\t\t\tif (sub) {\n\t\t\t\tfor (let i = sub.clients.length - 1; i >= 0; i--) {\n\t\t\t\t\tif (sub.clients[i].id_user === ws['id_user'] && sub.clients[i].messageId === messageId && sub.clients[i].id_socket === ws['id_socket']) {\n\t\t\t\t\t\tsub.clients.splice(i, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\tconsole.log(new Date(), 'Unsub', sub.publication, sub.running, sub.runAgain, sub.clients.length);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// Unsubscribe from publication\n\tpublic async unsubscribeAll(ws: WebSocket) {\n\t\tthis._debugUnSubAllHits += 1;\n\n\t\tif (ws) {\n\t\t\t// Check if WebSocket has already been unsubscribed\n\t\t\tif (ws['isUnsubscribed']) {\n\t\t\t\treturn; // Skip if already unsubscribed\n\t\t\t}\n\t\t\t\n\t\t\t// Mark the WebSocket as unsubscribed to prevent further calls\n\t\t\tws['isUnsubscribed'] = true;\n\t\t\t\n\t\t\tif (this._loggedInUsers.map(a => a.id_ws).indexOf(ws['id_socket']) >= 0) {\n\t\t\t\tthis._loggedInUsers.splice(this._loggedInUsers.map(a => a.id_ws).indexOf(ws['id_socket']), 1);\n\t\t\t}\n\t\t\t\n\t\t\tawait LoggedInUsers.deleteOne({ id_ws: ws['id_socket'] });\n\n\t\t\tlet userSubs = this._subscriptions.filter(a => a.clients.some(b => b.id_user === ws['id_user'] && b.id_socket === ws['id_socket']));\n\n\t\t\tfor (let i = userSubs.length - 1; i >= 0; i--) {\n\t\t\t\tlet sub = userSubs[i];\n\n\t\t\t\tfor (let j = sub.clients.length - 1; j >= 0; j--) {\n\t\t\t\t\tif (sub.clients[j].id_socket === ws['id_socket']) {\n\t\t\t\t\t\tsub.clients.splice(j, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._websocketManager.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic getActiveSubscriptions() {\n\t\treturn this._subscriptions;\n\t}\n\n\t// Get publication collection\n\tprivate getPublicationCollections(publication: string) {\n\t\treturn this._publications[publication].collections;\n\t}\n\n\t// Watch (tail) Mongo's operation log on the entire database (all insert/modify/delete will trigger this function)\n\tprivate async tailOpLog(resumeToken?: ResumeToken) {\n\t\tif (this._oplog$ && !this._oplog$.closed) {\n\t\t\tthis._oplog$.removeAllListeners();\n\t\t\tawait this._oplog$.close();\n\t\t\tthis._oplog$ = null;\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tawait new Promise(resolve => setTimeout(resolve, 1000));\n\n\t\tif (!this._oplog$ || this._oplog$.closed) {\n\t\t\tthis._oplogRetryCount += 1;\n\n\t\t\tif (this._oplogRetryCount > 5) {\n\t\t\t\tconsole.error('****************** TAIL OPLOG ERROR, RETRYING A BUNCH OF TIMES, KILLING PROCESS **************************');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst pipeline = [\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t{'ns.coll': { $nin: [\n\t\t\t\t\t\t\t\t'log-method-latencies', \n\t\t\t\t\t\t\t\t'log-subscriptions', \n\t\t\t\t\t\t\t\t'logs', \n\t\t\t\t\t\t\t\t'counters', \n\t\t\t\t\t\t\t\t'cron-job-histories', \n\t\t\t\t\t\t\t\t'email-histories',\n\t\t\t\t\t\t\t\t'qb-soap-request-histories', \n\t\t\t\t\t\t\t\t'qb-soap-request-responses', \n\t\t\t\t\t\t\t\t'qb-soap-requests',\n\t\t\t\t\t\t\t\t'qb-soap-retries'\n\t\t\t\t\t\t\t] }},\n\t\t\t\t\t\t\t{'ns.coll': { $not: /.*\\.versions$/ }},\n\t\t\t\t\t\t\t{'ns.coll': { $not: /^monitor-/ }},\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tlet lastResumeToken: ResumeToken;\n\n\t\t\tif (resumeToken) {\n\t\t\t\tlastResumeToken = resumeToken;\n\t\t\t\ttry {\n\t\t\t\t\tthis._oplog$ = ResolveIOServer.getMainDB().watch(pipeline, { resumeAfter: resumeToken });\n\t\t\t\t}\n\t\t\t\tcatch {\n\t\t\t\t\tif (this._oplog$) {\n\t\t\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\t\t\tawait this._oplog$.close();\n\t\t\t\t\t\tthis._oplog$ = null;\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.tailOpLog(resumeToken);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._oplog$ = ResolveIOServer.getMainDB().watch(pipeline);\n\t\t\t}\n\n\t\t\tconsole.log(new Date(), 'oplog started');\n\n\t\t\tthis._oplog$.on('change', async (doc: ChangeStreamInsertDocument | ChangeStreamUpdateDocument | ChangeStreamReplaceDocument | ChangeStreamDeleteDocument) => {\n\t\t\t\tif (doc.ns) {\n\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\tconsole.log(new Date(), 'Oplog Hit', doc.ns);\n\t\t\t\t\t}\n\n\t\t\t\t\tlet collection = doc.ns.coll;\n\n\t\t\t\t\tif (!this._debugOplogCollections.some(a => a.collection === doc.ns.coll && a.type === doc.operationType)) {\n\t\t\t\t\t\tthis._debugOplogCollections.push({\n\t\t\t\t\t\t\tcollection: doc.ns.coll,\n\t\t\t\t\t\t\ttype: doc.operationType,\n\t\t\t\t\t\t\thits: 1\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._debugOplogCollections.find(a => a.collection === doc.ns.coll && a.type === doc.operationType).hits += 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (collection) {\n\t\t\t\t\t\tthis._debugOplogHits += 1;\n\n\t\t\t\t\t\tif (doc.operationType === 'insert') {\n\t\t\t\t\t\t\tif (collection === 'support-tickets') {\n\t\t\t\t\t\t\t\tif (this.serverConfig['ROOT_URL'] === 'https://resolveio.com') {\n\t\t\t\t\t\t\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'sendSupportTicketEmail', doc.documentKey['_id']);\n\t\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'insert');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'insert');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (doc.operationType === 'update' || doc.operationType === 'replace') {\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'update');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (doc.operationType === 'delete') {\n\t\t\t\t\t\t\tif (collection !== 'method-responses') {\n\t\t\t\t\t\t\t\tawait this.invalidatePubsCache(collection, 'delete');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (collection === 'flags') {\n\t\t\t\t\t\tlet flag = await Flags.findOne({ type: 'Enable Debug' });\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (flag && flag.value) {\n\t\t\t\t\t\t\tthis._enableDebug = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis._enableDebug = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlastResumeToken = doc._id;\n\n\t\t\t\t\tif ((!process.env.NODE_APP_INSTANCE || process.env.NODE_APP_INSTANCE === '0') && (process.env.IS_WORKERS_ENABLED === 'false' || (process.env.IS_WORKER_INSTANCE === 'true' && process.env.WORKER_INDEX === '0'))) {\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis._oplog$.on('error', async error => {\n\t\t\t\tconsole.log(new Date(), 'oplog error', error);\n\t\t\t\tawait this._oplog$.close();\n\t\t\t});\n\n\t\t\tthis._oplog$.on('end', async () => {\n\t\t\t\tconsole.log(new Date(), 'oplog end');\n\t\t\t\tawait this._oplog$.close();\n\t\t\t});\n\n\t\t\tthis._oplog$.on('close', async () => {\n\t\t\t\tconsole.log(new Date(), 'oplog close');\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tawait this.tailOpLog(lastResumeToken);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async processSubscription(sub: ActiveSubscriptionModel, ws: WebSocket, messageId: number) {\n\t\tif (!this._publications[sub.publication].user_specific) {\t\t\t\n\t\t\tif (sub.cacheId) {\n\t\t\t\ttry {\n\t\t\t\t\tlet cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), dateReviver);\n\n\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tdata: cacheData\n\t\t\t\t\t};\n\n\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\tconsole.log(new Date(), 'Process Sub, Cache', sub.publication);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t}\n\t\t\t\tcatch {\n\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\t\tsub.cacheId = 0;\n\n\t\t\t\t\tawait this.sendDataToAllWithRetry(sub, '', 'newSub');\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\tconsole.log(new Date(), 'Process Sub, Non - Cache', sub.publication, sub.running);\n\t\t\t\t}\n\n\t\t\t\tif (sub.running) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait this.sendDataToAllWithRetry(sub, '', 'newSub');\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (this._enableDebug) {\n\t\t\t\tconsole.log(new Date(), 'Process Sub Specific, Non - Cache', sub.publication, sub.running);\n\t\t\t}\n\n\t\t\tif (sub.running) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tawait this.sendDataToOneWithRetry(ws, messageId, sub, '', 'newSub');\n\t\t}\n\t}\n\n\tprivate async sendDataToOne(ws: WebSocket, messageId: number, sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tlet monitor = this._monitorManagerFunction.startMonitorFunction('User Specific Publication', sub.publication, '', '', sub.subscriptionData);\n\t\ttry {\n\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));\n\n\t\t\tlet res = await this._publications[sub.publication].function.call(Object.assign({}, this, SubscriptionManager.prototype), ws['id_user'], ...sub.subscriptionData);\n\n\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: false,\n\t\t\t\tdata: res\n\t\t\t};\n\n\t\t\tthis.sendWS(ws, serverRes);\n\t\t}\n\t\tcatch (err) {\n\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: true,\n\t\t\t\tdata: err\n\t\t\t};\n\t\t\t\n\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\n\t\t\tawait ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendDataToOne - WS)\\n\\nData \\n' + JSON.stringify(sub.subscriptionData, null, 2) + '\\n\\nErrors\\n' + JSON.stringify(err, null, 2));\n\t\t}\n\t\tfinally {\n\t\t\tawait this._monitorManagerFunction.finishMonitorFunction(monitor);\n\t\t}\n\t}\n\n\t// Fetch pub once, send to all clients linked to this pub\n\tprivate async sendDataToAll(sub: ActiveSubscriptionModel, collection: string, type: string) {\n\t\tif (!sub.clients.length) {\n\t\t\tif (sub.cacheId) {\n\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\tsub.cacheId = 0;\n\t\t\t}\n\n\t\t\tlet subIndex = this._subscriptions.findIndex(a => a.publication === sub.publication && JSON.stringify(a.subscriptionData) === JSON.stringify(sub.subscriptionData));\n\t\t\tif (subIndex >= 0) {\n\t\t\t\tthis._subscriptions.splice(subIndex, 1);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tlet monitor = this._monitorManagerFunction.startMonitorFunction('Publication', sub.publication, '', '', sub.subscriptionData);\n\n\t\t\ttry {\n\t\t\t\tif (sub.publication !== 'superadminAPM' && sub.publication !== 'loggedInUsers') {\n\t\t\t\t\tResolveIOServer.getMainServer().getMethodManager().callMethod.call(ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));\n\t\t\t\t}\n\n\t\t\t\tlet res = await this._publications[sub.publication].function.call(Object.assign({}, this, SubscriptionManager.prototype), ...sub.subscriptionData);\n\n\t\t\t\tif (sub.cacheId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), dateReviver);\n\t\n\t\t\t\t\t\tif (JSON.stringify(cacheData) !== JSON.stringify(res)) {\n\t\t\t\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t\t};\n\t\t\n\t\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\n\t\t\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch {\n\t\t\t\t\t\tsub.clients.map(client => {\n\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t};\n\t\n\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\n\t\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (getBinarySize(JSON.stringify(res)) < 1000000 && \n\t\t\t\t\t\t!sub.collections.includes('logs') &&\n\t\t\t\t\t\t!sub.collections.find(a => a.endsWith('.versions')) &&\n\t\t\t\t\t\t!sub.collections.find(a => a.startsWith('monitor-'))\n\t\t\t\t\t) {\n\t\t\t\t\t\tsub.cacheId = this._cacheId++;\n\t\t\t\t\t\tthis._nodeCache.set(sub.cacheId, JSON.stringify(res));\n\n\t\t\t\t\t\tconst nodeCacheSize = this._nodeCache.getStats().vsize;\n\n\t\t\t\t\t\tif (nodeCacheSize > this._heapLimit) {\n\t\t\t\t\t\t\t// Evict cache entries as needed\n\t\t\t\t\t\t\tlet deleteCount = 0;\n\t\t\t\t\t\t\tconst subArr = this._subscriptions.filter(a => a.cacheId && !a.clients.length);\n\t\t\t\t\t\n\t\t\t\t\t\t\tfor (let zz = 0; zz < subArr.length; zz++) {\n\t\t\t\t\t\t\t\tthis._debugRemoveCacheHits += 1;\n\t\t\t\t\t\t\t\tthis._nodeCache.del(subArr[zz].cacheId);\n\t\t\t\t\t\t\t\tsubArr[zz].cacheId = 0;\n\t\t\t\t\t\t\t\tdeleteCount += 1;\n\t\t\t\t\t\t\t\tif (this._nodeCache.getStats().vsize < this._heapLimit * 0.75) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (this._enableDebug) {\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\t'Sub Cache: ' +\n\t\t\t\t\t\t\t\t\t'Too Big - ' +\n\t\t\t\t\t\t\t\t\tsub.publication +\n\t\t\t\t\t\t\t\t\t' - Deleted: ' +\n\t\t\t\t\t\t\t\t\tdeleteCount +\n\t\t\t\t\t\t\t\t\t' - ' +\n\t\t\t\t\t\t\t\t\tnodeCacheSize\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsub.cacheId = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err) {\n\t\t\t\tfor (let client of sub.clients) {\n\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\thasError: true,\n\t\t\t\t\t\t\tdata: err\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tawait ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendPubData)\\n\\nData \\n' + JSON.stringify(sub.subscriptionData, null, 2) + '\\n\\nErrors\\n' + JSON.stringify(err, null, 2));\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\tawait this._monitorManagerFunction.finishMonitorFunction(monitor);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendWS(ws: WebSocket, data: ServerResponseModel) {\n\t\tthis._websocketManager.send(ws, data);\n\t}\n\n\tpublic getEnableDebug() {\n\t\treturn this._enableDebug;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as WebSocket from 'ws';
|
|
2
|
+
import { TaskPayload } from '../models/server-message.model';
|
|
3
|
+
import { MethodManager } from './method.manager';
|
|
4
|
+
import { WebSocketManager } from './websocket.manager';
|
|
5
|
+
export interface WorkerConnection {
|
|
6
|
+
id: string;
|
|
7
|
+
ws: WebSocket.WebSocket;
|
|
8
|
+
activeTasks: {
|
|
9
|
+
taskId: string;
|
|
10
|
+
weight: number;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
export declare class WorkerDispatcherManager {
|
|
14
|
+
private _websocketManager;
|
|
15
|
+
private _methodManager;
|
|
16
|
+
private _workers;
|
|
17
|
+
private _taskQueue;
|
|
18
|
+
private _clientRequests;
|
|
19
|
+
private _runningTasks;
|
|
20
|
+
private MAX_CONCURRENCY;
|
|
21
|
+
constructor();
|
|
22
|
+
static create(websocketManager: WebSocketManager, methodManager: MethodManager): WorkerDispatcherManager;
|
|
23
|
+
initialize(websocketManager: WebSocketManager, methodManager: MethodManager): void;
|
|
24
|
+
isSafeShutdown(): boolean;
|
|
25
|
+
addWorker(ws: WebSocket.WebSocket): void;
|
|
26
|
+
disconnectWorker(workerId: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Add a new task to our in-memory queue and try to dispatch.
|
|
29
|
+
*/
|
|
30
|
+
addClientTask(messageId: number, method: string, params: any[], userContext?: {
|
|
31
|
+
id_user?: string;
|
|
32
|
+
user?: string;
|
|
33
|
+
id_ws?: string;
|
|
34
|
+
}): void;
|
|
35
|
+
addInternalTask(method: string, params: any[]): void;
|
|
36
|
+
/**
|
|
37
|
+
* The main loop that assigns tasks from _taskQueue to any worker that has capacity.
|
|
38
|
+
*/
|
|
39
|
+
private dispatchQueue;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the worker with the fewest activeTasks that is under maxConcurrency. Or null if none.
|
|
42
|
+
*/
|
|
43
|
+
private findAvailableWorker;
|
|
44
|
+
private assignTaskToWorker;
|
|
45
|
+
/**
|
|
46
|
+
* Handle messages coming back from a worker (like 'taskComplete').
|
|
47
|
+
*/
|
|
48
|
+
handleWorkerMessage(workerId: string, messageStr: string): void;
|
|
49
|
+
sendWorkerPayload(ws: WebSocket.WebSocket, payload: TaskPayload | string): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.WorkerDispatcherManager=void 0;var common_1=require("../util/common"),WorkerDispatcherManager=function(){function WorkerDispatcherManager(){this._workers=[],this._taskQueue=[],this._clientRequests={},this._runningTasks=[],this.MAX_CONCURRENCY=3}return WorkerDispatcherManager.create=function(e,t){var r=new WorkerDispatcherManager;return r.initialize(e,t),r},WorkerDispatcherManager.prototype.initialize=function(e,t){this._websocketManager=e,this._methodManager=t},WorkerDispatcherManager.prototype.isSafeShutdown=function(){return!this._taskQueue.length&&!this._runningTasks},WorkerDispatcherManager.prototype.addWorker=function(e){this._workers.push({id:e.id_worker,ws:e,activeTasks:[]})},WorkerDispatcherManager.prototype.disconnectWorker=function(t){this._workers=this._workers.filter(function(e){return e.id!==t})},WorkerDispatcherManager.prototype.addClientTask=function(e,t,r,s){var a="task-"+(0,common_1.objectIdHexString)();this._taskQueue.push({taskId:a,messageId:e,method:t,params:r,userContext:s}),s&&s.id_ws&&(this._clientRequests[a]=s.id_ws),this.dispatchQueue()},WorkerDispatcherManager.prototype.addInternalTask=function(e,t){var r="task-"+(0,common_1.objectIdHexString)();this._taskQueue.push({taskId:r,method:e,params:t,messageId:0,userContext:{user:"Internal System"}}),this.dispatchQueue()},WorkerDispatcherManager.prototype.dispatchQueue=function(){var e,t,r=this;!this._taskQueue.length||!(e=this._taskQueue[0])||(t=this.findAvailableWorker())&&(this._taskQueue.shift(),this.assignTaskToWorker(t,e),!this._taskQueue.length)||setTimeout(function(){r.dispatchQueue()},25)},WorkerDispatcherManager.prototype.findAvailableWorker=function(){var t=this,e=this._workers.filter(function(e){return e.activeTasks.map(function(e){return e.weight}).reduce(function(e,t){return t},0)<t.MAX_CONCURRENCY});return e.length?(e.sort(function(e,t){return e.activeTasks.map(function(e){return e.weight}).reduce(function(e,t){return t},0)-t.activeTasks.map(function(e){return e.weight}).reduce(function(e,t){return t},0)}),e[0]):null},WorkerDispatcherManager.prototype.assignTaskToWorker=function(t,r){var e=this._methodManager.getMethod(r.method);if(e){t.activeTasks.push({taskId:r.taskId,weight:e&&e.workerTaskWeight?e.workerTaskWeight:1});e={type:"task",taskId:r.taskId,messageId:r.messageId,method:r.method,params:r.params,userContext:r.userContext||{}};try{this.sendWorkerPayload(t.ws,e)}catch(e){console.error("Failed to send task to worker:",e),t.activeTasks=t.activeTasks.filter(function(e){return e.taskId!==r.taskId}),this._taskQueue.unshift(r)}}else console.error("Failed to send task to worker - Could not find method:")},WorkerDispatcherManager.prototype.handleWorkerMessage=function(t,r){var s,e,a,o;try{e=JSON.parse(r,common_1.dateReviver)}catch(e){return void console.error("Failed to parse worker message:",r)}"taskComplete"===e.type&&((r=this._workers.find(function(e){return e.id===t}))?(s=e.taskId,a=e.messageId,o=e.error,e=e.result,r.activeTasks=r.activeTasks.filter(function(e){return e.taskId!==s}),(r=this._clientRequests[s])&&(a={messageId:a,hasError:!1,data:e},o&&(a.hasError=!0,a.data=e),o=this._websocketManager.getWebSocket(r),this._websocketManager.send(o,a),delete this._clientRequests[s]),this.dispatchQueue()):console.error("Unknown worker for taskComplete:",t))},WorkerDispatcherManager.prototype.sendWorkerPayload=function(e,t){if("string"!=typeof t&&(t=JSON.stringify(t)),e&&e.readyState===e.OPEN)try{e.send(t)}catch(e){console.error("Failed to send worker response:",e)}else e&&e.close()},WorkerDispatcherManager}();exports.WorkerDispatcherManager=WorkerDispatcherManager;
|
|
2
|
+
//# sourceMappingURL=worker-dispatcher.manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/managers/worker-dispatcher.manager.ts"],"names":["common_1","require","WorkerDispatcherManager","this","_workers","_taskQueue","_clientRequests","_runningTasks","MAX_CONCURRENCY","create","websocketManager","methodManager","workerDispatcherManager","initialize","prototype","_websocketManager","_methodManager","isSafeShutdown","length","addWorker","ws","push","id","activeTasks","disconnectWorker","workerId","filter","w","addClientTask","messageId","method","params","userContext","taskId","objectIdHexString","id_ws","dispatchQueue","addInternalTask","user","task","_this","findAvailableWorker","shift","assignTaskToWorker","setTimeout","candidates","x","map","a","weight","reduce","b","sort","y","worker","getMethod","workerTaskWeight","payload","type","sendWorkerPayload","err","console","error","unshift","handleWorkerMessage","messageStr","taskId_1","result","res","clientReqWS","data","JSON","parse","dateReviver","_a","find","clientReqId","hasError","getWebSocket","send","stringify","readyState","OPEN","close","exports"],"mappings":"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","file":"worker-dispatcher.manager.js","sourcesContent":["import * as WebSocket from 'ws';\nimport { ServerResponseModel, TaskPayload, TaskQueueItem, TaskResponse } from '../models/server-message.model';\nimport { dateReviver, objectIdHexString } from '../util/common';\nimport { MethodManager } from './method.manager';\nimport { WebSocketManager } from './websocket.manager';\n\nexport interface WorkerConnection {\n id: string;\n ws: WebSocket.WebSocket;\n activeTasks: { taskId: string, weight: number }[];\n}\n\nexport class WorkerDispatcherManager {\n\tprivate _websocketManager: WebSocketManager;\n\tprivate _methodManager: MethodManager;\n private _workers: WorkerConnection[] = [];\n\tprivate _taskQueue: TaskQueueItem[] = [];\n private _clientRequests: { [taskId: string]: string } = {};\n\tprivate _runningTasks = [];\n\n private MAX_CONCURRENCY = 3;\n\n constructor() {}\n \n static create(websocketManager: WebSocketManager, methodManager: MethodManager) {\n const workerDispatcherManager = new WorkerDispatcherManager();\n workerDispatcherManager.initialize(websocketManager, methodManager);\n return workerDispatcherManager;\n }\n\n public initialize(websocketManager: WebSocketManager, methodManager: MethodManager) {\n\t\tthis._websocketManager = websocketManager;\n\t\tthis._methodManager = methodManager;\n }\n\n\tpublic isSafeShutdown() {\n\t\treturn !this._taskQueue.length && !this._runningTasks;\n\t}\n\n public addWorker(ws: WebSocket.WebSocket) {\n this._workers.push({\n\t\t\tid: ws['id_worker'],\n\t\t\tws: ws,\n\t\t\tactiveTasks: []\n\t\t});\n }\n\n\tpublic disconnectWorker(workerId: string) {\n\t\tthis._workers = this._workers.filter(w => w.id !== workerId);\n\t}\n\n /**\n\t * Add a new task to our in-memory queue and try to dispatch.\n\t */\n\tpublic addClientTask(messageId: number, method: string, params: any[], userContext?: { id_user?: string; user?: string; id_ws?: string }) {\n\t\tlet taskId = 'task-' + objectIdHexString();\n\n\t\tthis._taskQueue.push({\n\t\t\ttaskId,\n\t\t\tmessageId,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t\tuserContext\n\t\t});\n\n\t\tif (userContext && userContext.id_ws) {\n\t\t\tthis._clientRequests[taskId] = userContext.id_ws;\n\t\t}\n\n\t\tthis.dispatchQueue();\n\t}\n\n\tpublic addInternalTask(method: string, params: any[]) {\n\t\tlet taskId = 'task-' + objectIdHexString();\n\n\t\tthis._taskQueue.push({\n\t\t\ttaskId,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t\tmessageId: 0,\n\t\t\tuserContext: {\n\t\t\t\tuser: 'Internal System'\n\t\t\t}\n\t\t});\n\n\t\tthis.dispatchQueue();\n\t}\n\n\t/**\n\t * The main loop that assigns tasks from _taskQueue to any worker that has capacity.\n\t */\n\tprivate dispatchQueue() {\n\t\tif (!this._taskQueue.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Try to assign tasks while we have them\n\t\tlet task = this._taskQueue[0];\n\t\tif (!task) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet w = this.findAvailableWorker();\n\n\t\tif (!w) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.dispatchQueue();\n\t\t\t}, 25);\n\t\t\t\n\t\t\treturn; // no worker can take more tasks\n\t\t}\n\n\t\t// Remove from queue\n\t\tthis._taskQueue.shift();\n\t\tthis.assignTaskToWorker(w, task);\n\n\t\tif (this._taskQueue.length) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.dispatchQueue();\n\t\t\t}, 25);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the worker with the fewest activeTasks that is under maxConcurrency. Or null if none.\n\t */\n\tprivate findAvailableWorker(): WorkerConnection | null {\n\t\tlet candidates = this._workers.filter(x => x.activeTasks.map(a => a.weight).reduce((a, b) => a = b, 0) < this.MAX_CONCURRENCY);\n\t\tif (!candidates.length) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Sort by how busy they are\n\t\tcandidates.sort((x, y) => x.activeTasks.map(a => a.weight).reduce((a, b) => a = b, 0) - y.activeTasks.map(a => a.weight).reduce((a, b) => a = b, 0));\n\t\treturn candidates[0];\n\t}\n\n\tprivate assignTaskToWorker(worker: WorkerConnection, task: TaskQueueItem) {\n\t\tlet method = this._methodManager.getMethod(task.method);\n\n\t\tif (!method) {\n\t\t\tconsole.error('Failed to send task to worker - Could not find method:');\n\t\t\treturn;\n\t\t}\n\n\t\tworker.activeTasks.push({\n\t\t\ttaskId: task.taskId,\n\t\t\tweight: method && method.workerTaskWeight ? method.workerTaskWeight : 1\n\t\t});\n\n\t\tlet payload: TaskPayload = {\n\t\t\ttype: 'task',\n\t\t\ttaskId: task.taskId,\n\t\t\tmessageId: task.messageId,\n\t\t\tmethod: task.method,\n\t\t\tparams: task.params,\n\t\t\tuserContext: task.userContext || {}\n\t\t};\n\n\t\ttry {\n\t\t\tthis.sendWorkerPayload(worker.ws, payload);\n\t\t}\n\t\tcatch (err) {\n\t\t\tconsole.error('Failed to send task to worker:', err);\n\n\t\t\tworker.activeTasks = worker.activeTasks.filter(a => a.taskId !== task.taskId);\n\t\t\t// Put task back at front\n\t\t\tthis._taskQueue.unshift(task);\n\t\t}\n\t}\n\n\t/**\n\t * Handle messages coming back from a worker (like 'taskComplete').\n\t */\n\tpublic handleWorkerMessage(workerId: string, messageStr: string) {\n\t\tlet data: TaskResponse;\n\t\t\n\t\ttry {\n\t\t\tdata = JSON.parse(messageStr, dateReviver);\n\t\t}\n\t\tcatch {\n\t\t\tconsole.error('Failed to parse worker message:', messageStr);\n\t\t\treturn;\n\t\t}\n\n\t\tif (data.type === 'taskComplete') {\n\t\t\tlet w = this._workers.find(x => x.id === workerId);\n\t\t\tif (!w) {\n\t\t\t\tconsole.error('Unknown worker for taskComplete:', workerId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tlet { taskId, messageId, error, result } = data;\n\t\t\t\n\t\t\tw.activeTasks = w.activeTasks.filter(a => a.taskId !== taskId);\n\n\t\t\t// Look up original request\n\t\t\tlet clientReqId = this._clientRequests[taskId];\n\t\t\t\n\t\t\tif (clientReqId) {\n\t\t\t\t// Send the final response to the client\n\t\t\t\tlet res: ServerResponseModel = {\n\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tdata: result\n\t\t\t\t};\n\n\t\t\t\tif (error) {\n\t\t\t\t\tres.hasError = true;\n\t\t\t\t\tres.data = result;\n\t\t\t\t}\n\n\t\t\t\tlet clientReqWS = this._websocketManager.getWebSocket(clientReqId);\n\t\t\t\tthis._websocketManager.send(clientReqWS, res);\n\n\t\t\t\tdelete this._clientRequests[taskId];\n\t\t\t}\n\n\t\t\t// Try to dispatch more from the queue\n\t\t\tthis.dispatchQueue();\n\t\t}\n\t}\n\n\tpublic sendWorkerPayload(ws: WebSocket.WebSocket, payload: TaskPayload | string) {\n if (typeof payload !== 'string') {\n payload = JSON.stringify(payload);\n }\n\n if (ws && ws.readyState === ws.OPEN) {\n try {\n ws.send(payload);\n }\n catch (err) {\n console.error('Failed to send worker response:', err);\n }\n }\n else if (ws) {\n ws.close();\n }\n }\n}"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TaskResponse } from '../models/server-message.model';
|
|
2
|
+
import { MethodManager } from './method.manager';
|
|
3
|
+
export declare class WorkerServerManager {
|
|
4
|
+
private _methodManager;
|
|
5
|
+
private _serverConfig;
|
|
6
|
+
private _runningTasks;
|
|
7
|
+
constructor();
|
|
8
|
+
static create(methodManager: MethodManager, serverConfig: any): WorkerServerManager;
|
|
9
|
+
initialize(methodManager: MethodManager, serverConfig: any): void;
|
|
10
|
+
private startWorkerInstance;
|
|
11
|
+
private handleIncomingTask;
|
|
12
|
+
sendWorkerResponse(ws: any, payload: TaskResponse | string): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var __awaiter=this&&this.__awaiter||function(e,n,o,s){return new(o=o||Promise)(function(t,r){function fulfilled(e){try{step(s.next(e))}catch(e){r(e)}}function rejected(e){try{step(s.throw(e))}catch(e){r(e)}}function step(e){var r;e.done?t(e.value):((r=e.value)instanceof o?r:new o(function(e){e(r)})).then(fulfilled,rejected)}step((s=s.apply(e,n||[])).next())})},__generator=this&&this.__generator||function(n,o){var s,a,i,c={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},l={next:verb(0),throw:verb(1),return:verb(2)};return"function"==typeof Symbol&&(l[Symbol.iterator]=function(){return this}),l;function verb(t){return function(e){var r=[t,e];if(s)throw new TypeError("Generator is already executing.");for(;c=l&&r[l=0]?0:c;)try{if(s=1,a&&(i=2&r[0]?a.return:r[0]?a.throw||((i=a.return)&&i.call(a),0):a.next)&&!(i=i.call(a,r[1])).done)return i;switch(a=0,(r=i?[2&r[0],i.value]:r)[0]){case 0:case 1:i=r;break;case 4:return c.label++,{value:r[1],done:!1};case 5:c.label++,a=r[1],r=[0];continue;case 7:r=c.ops.pop(),c.trys.pop();continue;default:if(!(i=0<(i=c.trys).length&&i[i.length-1])&&(6===r[0]||2===r[0])){c=0;continue}if(3===r[0]&&(!i||r[1]>i[0]&&r[1]<i[3]))c.label=r[1];else if(6===r[0]&&c.label<i[1])c.label=i[1],i=r;else{if(!(i&&c.label<i[2])){i[2]&&c.ops.pop(),c.trys.pop();continue}c.label=i[2],c.ops.push(r)}}r=o.call(n,c)}catch(e){r=[6,e],a=0}finally{s=i=0}if(5&r[0])throw r[1];return{value:r[0]?r[1]:void 0,done:!0}}}},__read=this&&this.__read||function(e,r){var t="function"==typeof Symbol&&e[Symbol.iterator];if(!t)return e;var n,o,s=t.call(e),a=[];try{for(;(void 0===r||0<r--)&&!(n=s.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(t=s.return)&&t.call(s)}finally{if(o)throw o.error}}return a},__spreadArray=this&&this.__spreadArray||function(e,r,t){if(t||2===arguments.length)for(var n,o=0,s=r.length;o<s;o++)!n&&o in r||((n=n||Array.prototype.slice.call(r,0,o))[o]=r[o]);return e.concat(n||Array.prototype.slice.call(r))},WebSocket=(Object.defineProperty(exports,"__esModule",{value:!0}),exports.WorkerServerManager=void 0,require("ws")),common_1=require("../util/common"),method_manager_1=require("./method.manager"),WorkerServerManager=function(){function WorkerServerManager(){this._runningTasks=[]}return WorkerServerManager.create=function(e,r){var t=new WorkerServerManager;return t.initialize(e,r),t},WorkerServerManager.prototype.initialize=function(e,r){this._methodManager=e,this._serverConfig=r,this.startWorkerInstance()},WorkerServerManager.prototype.startWorkerInstance=function(){var e=this,r=(console.log(new Date,"Worker instance started, connecting to main server via WebSocket..."),this._serverConfig.SERVER_URL+"/websocket?workerToken="+this._serverConfig.WORKER_TOKEN),n=new WebSocket(r),o=null,t=null;n.on("open",function(){console.log(new Date,"Connected to main server as worker",process.env.WORKER_INDEX,process.env.NODE_APP_INSTANCE),e.sendWorkerResponse(n,"ping"),t=setInterval(function(){o?(o=null,e.sendWorkerResponse(n,"ping")):n.close()},15e3)}),n.on("message",function(t){return __awaiter(e,void 0,void 0,function(){var r;return __generator(this,function(e){switch(e.label){case 0:return"ping"!==(t="string"!=typeof t?t.toString():t)?[3,1]:(this.sendWorkerResponse(n,"pong"),[3,4]);case 1:return"pong"!==t?[3,2]:(o=new Date,[3,4]);case 2:r=void 0;try{r=JSON.parse(t,common_1.dateReviver)}catch(e){return console.error("Worker parse error",e),[2]}return"task"!==r.type?[3,4]:[4,this.handleIncomingTask(n,r)];case 3:e.sent(),e.label=4;case 4:return[2]}})})}),n.on("close",function(){console.log(new Date,"Disconnected from main server. Reconnecting in 5s..."),setTimeout(function(){return e.startWorkerInstance},5e3),t&&clearInterval(t)}),n.on("error",function(e){console.error(new Date,"Worker WS error:",e),n.close()})},WorkerServerManager.prototype.handleIncomingTask=function(d,h){return __awaiter(this,void 0,void 0,function(){var r,t,n,o,s,a,i,c,l,u=this;return __generator(this,function(e){switch(e.label){case 0:if(r=h.taskId,t=h.messageId,n=h.method,o=h.params,s=h.userContext,this._runningTasks.push(r),!r||!n)return console.log("Invalid task message received",h),this.sendWorkerResponse(d,{type:"taskComplete",taskId:r,messageId:t,error:!0,result:"Invalid task"}),[2];a=!1,i=setTimeout(function(){return __awaiter(u,void 0,void 0,function(){return __generator(this,function(e){switch(e.label){case 0:return a=!0,console.error(new Date,"Worker timed out on task:",r,"Method:",n),console.error(new Date,"Error in Method: ".concat(n," - ").concat(JSON.stringify(h,null,2))),this.sendWorkerResponse(d,{type:"taskComplete",taskId:r,messageId:t,error:!0,result:"Task timed out"}),[4,this._methodManager.callMethod("insertErrorLog","Timeout in Method: ".concat(n," - ").concat(JSON.stringify(h,null,2)))];case 1:return e.sent(),[2]}})})},12e4),e.label=1;case 1:return e.trys.push([1,3,,5]),c=Object.assign({},this._methodManager,method_manager_1.MethodManager.prototype,{id_user:(null==s?void 0:s.id_user)||"",user:(null==s?void 0:s.user)||"",id_ws:(null==s?void 0:s.id_ws)||""}),[4,(l=this._methodManager.callMethod).call.apply(l,__spreadArray([c,n],__read(o),!1))];case 2:return l=e.sent(),a||(clearTimeout(i),this.sendWorkerResponse(d,{type:"taskComplete",taskId:r,messageId:t,error:!1,result:l})),this._runningTasks=this._runningTasks.filter(function(e){return e!==r}),[3,5];case 3:return c=e.sent(),a||(clearTimeout(i),console.error("Worker failed task:",r,"Method:",n,c),c.message="Worker failed task:"+r+" Method:"+n+" - "+c.message,this.sendWorkerResponse(d,{type:"taskComplete",taskId:r,messageId:t,error:!0,result:c||"Unknown error"})),console.error(new Date,"Error in Method: ".concat(n," - ").concat(JSON.stringify(h,null,2))),[4,this._methodManager.callMethod("insertErrorLog","Error in Method: ".concat(n," - ").concat(JSON.stringify(h,null,2)))];case 4:return e.sent(),this._runningTasks=this._runningTasks.filter(function(e){return e!==r}),[3,5];case 5:return[2]}})})},WorkerServerManager.prototype.sendWorkerResponse=function(e,r){if("string"!=typeof r&&(r=JSON.stringify(r)),e&&e.readyState===e.OPEN)try{e.send(r)}catch(e){console.error("Failed to send worker response:",e)}else e&&e.close()},WorkerServerManager}();exports.WorkerServerManager=WorkerServerManager;
|
|
2
|
+
//# sourceMappingURL=worker-server.manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/managers/worker-server.manager.ts"],"names":["WebSocket","require","common_1","method_manager_1","WorkerServerManager","this","_runningTasks","create","methodManager","serverConfig","workerServerManager","initialize","prototype","_methodManager","_serverConfig","startWorkerInstance","_this","wsUrl","console","log","Date","ws","lastComm","interval","on","process","env","WORKER_INDEX","NODE_APP_INSTANCE","sendWorkerResponse","setInterval","close","rawData","__awaiter","toString","msg","JSON","parse","dateReviver","e","error","type","handleIncomingTask","_a","sent","setTimeout","clearInterval","err","data","taskId","messageId","method","params","userContext","push","result","timedOut","timeoutHandle","concat","stringify","callMethod","managerThis","Object","assign","MethodManager","id_user","user","id_ws","call","apply","__spreadArray","__read","_b","clearTimeout","filter","a","err_1","message","payload","readyState","OPEN","send","exports"],"mappings":"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","file":"worker-server.manager.js","sourcesContent":["import * as WebSocket from 'ws';\nimport { TaskPayload, TaskResponse } from '../models/server-message.model';\nimport { dateReviver } from '../util/common';\nimport { MethodManager } from './method.manager';\n\nexport class WorkerServerManager {\n private _methodManager;\n private _serverConfig;\n private _runningTasks = [];\n\n constructor() {}\n \n static create(methodManager: MethodManager, serverConfig) {\n const workerServerManager = new WorkerServerManager();\n workerServerManager.initialize(methodManager, serverConfig);\n return workerServerManager;\n }\n\n public initialize(methodManager: MethodManager, serverConfig) {\n this._methodManager = methodManager;\n this._serverConfig = serverConfig;\n this.startWorkerInstance();\n }\n\n private startWorkerInstance() {\n console.log(new Date(), 'Worker instance started, connecting to main server via WebSocket...');\n\n let wsUrl = this._serverConfig['SERVER_URL'] + '/websocket?workerToken=' + this._serverConfig['WORKER_TOKEN'];\n\n const ws = new WebSocket(wsUrl);\n\n let lastComm = null;\n let interval = null;\n\n ws.on('open', () => {\n console.log(new Date(), 'Connected to main server as worker', process.env.WORKER_INDEX, process.env.NODE_APP_INSTANCE);\n this.sendWorkerResponse(ws, 'ping');\n\n interval = setInterval(() => {\n if (!lastComm) {\n ws.close();\n }\n else {\n lastComm = null;\n this.sendWorkerResponse(ws, 'ping');\n }\n }, 15000);\n });\n\n ws.on('message', async (rawData: any) => {\n // console.log(new Date(), 'Message Recv', rawData);\n\n if (typeof rawData !== 'string') {\n rawData = rawData.toString();\n }\n\n // console.log(new Date(), 'String Message Recv', rawData);\n\n if (rawData === 'ping') {\n // console.log(new Date(), 'Recv Ping, Sending Pong');\n this.sendWorkerResponse(ws, 'pong');\n }\n else if (rawData === 'pong') {\n // console.log(new Date(), 'Recv Ping, Sending Pong');\n lastComm = new Date();\n }\n else {\n let msg: any;\n try {\n msg = JSON.parse(rawData, dateReviver);\n }\n catch (e) {\n console.error('Worker parse error', e);\n return;\n }\n\n // We expect: { type: 'task', taskId, method, params, userContext? }\n if (msg.type === 'task') {\n await this.handleIncomingTask(ws, msg);\n }\n }\n });\n\n ws.on('close', () => {\n console.log(new Date(), 'Disconnected from main server. Reconnecting in 5s...');\n setTimeout(() => this.startWorkerInstance, 5000);\n\n if (interval) {\n clearInterval(interval);\n }\n });\n\n ws.on('error', (err) => {\n console.error(new Date(), 'Worker WS error:', err);\n ws.close();\n });\n }\n\n private async handleIncomingTask(ws: WebSocket.WebSocket, data: TaskPayload) {\n let { taskId, messageId, method, params, userContext } = data;\n this._runningTasks.push(taskId);\n if (!taskId || !method) {\n console.log('Invalid task message received', data);\n this.sendWorkerResponse(ws, {\n type: 'taskComplete',\n taskId,\n messageId,\n error: true,\n result: 'Invalid task'\n });\n\n return;\n }\n\n let timedOut = false;\n let timeoutHandle = setTimeout(async () => {\n timedOut = true;\n console.error(new Date(), 'Worker timed out on task:', taskId, 'Method:', method);\n\n console.error(new Date(), `Error in Method: ${method} - ${JSON.stringify(data, null, 2)}`);\n\n this.sendWorkerResponse(ws, {\n type: 'taskComplete',\n taskId,\n messageId,\n error: true,\n result: 'Task timed out'\n });\n\n await this._methodManager.callMethod('insertErrorLog', `Timeout in Method: ${method} - ${JSON.stringify(data, null, 2)}`);\n }, 120000);\n\n try {\n let managerThis = Object.assign({}, this._methodManager, MethodManager.prototype, {\n id_user: userContext?.id_user || '',\n user: userContext?.user || '',\n id_ws: userContext?.id_ws || ''\n });\n\n let result = await this._methodManager.callMethod.call(managerThis, method, ...params);\n\n if (!timedOut) {\n clearTimeout(timeoutHandle);\n this.sendWorkerResponse(ws, {\n type: 'taskComplete',\n taskId,\n messageId,\n error: false,\n result\n });\n }\n\n this._runningTasks = this._runningTasks.filter(a => a !== taskId);\n }\n catch (err) {\n if (!timedOut) {\n clearTimeout(timeoutHandle);\n console.error('Worker failed task:', taskId, 'Method:', method, err);\n err.message = 'Worker failed task:' + taskId + ' Method:' + method + ' - ' + err.message;\n this.sendWorkerResponse(ws, {\n type: 'taskComplete',\n taskId,\n messageId,\n error: true,\n result: err || 'Unknown error'\n });\n }\n\n console.error(new Date(), `Error in Method: ${method} - ${JSON.stringify(data, null, 2)}`);\n \n await this._methodManager.callMethod('insertErrorLog', `Error in Method: ${method} - ${JSON.stringify(data, null, 2)}`);\n \n this._runningTasks = this._runningTasks.filter(a => a !== taskId);\n }\n }\n\n public sendWorkerResponse(ws, payload: TaskResponse | string) {\n if (typeof payload !== 'string') {\n payload = JSON.stringify(payload);\n }\n\n if (ws && ws.readyState === ws.OPEN) {\n try {\n ws.send(payload);\n }\n catch (err) {\n console.error('Failed to send worker response:', err);\n }\n }\n else if (ws) {\n ws.close();\n }\n }\n}"]}
|
package/models/method.model.d.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ServerResponseModel {
|
|
2
|
+
messageId: number;
|
|
3
|
+
hasError: boolean;
|
|
4
|
+
data: any;
|
|
5
|
+
}
|
|
6
|
+
interface Task {
|
|
7
|
+
taskId: string;
|
|
8
|
+
messageId: number;
|
|
9
|
+
}
|
|
10
|
+
export interface TaskQueueItem extends Task {
|
|
11
|
+
method: string;
|
|
12
|
+
params: any[];
|
|
13
|
+
userContext: {
|
|
14
|
+
id_user?: string;
|
|
15
|
+
user?: string;
|
|
16
|
+
id_ws?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface TaskPayload extends TaskQueueItem {
|
|
20
|
+
type: 'task';
|
|
21
|
+
}
|
|
22
|
+
export interface TaskResponse extends Task {
|
|
23
|
+
type: 'taskComplete';
|
|
24
|
+
error: boolean;
|
|
25
|
+
result: any;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
|
2
|
-
//# sourceMappingURL=server-
|
|
2
|
+
//# sourceMappingURL=server-message.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-message.model.js","sources":["models/server-message.model.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n"],"names":["Object","defineProperty","exports","value"],"mappings":"AAAA,aACAA,OAAOC,eAAeC,QAAS,aAAc,CAAEC,MAAO,CAAA,CAAK,CAAC"}
|
package/package.json
CHANGED
package/public_api.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export * from './models/report-builder-library.model';
|
|
|
50
50
|
export * from './models/report-builder-report.model';
|
|
51
51
|
export * from './models/report-builder.model';
|
|
52
52
|
export * from './models/select-data-label.model';
|
|
53
|
-
export * from './models/server-
|
|
53
|
+
export * from './models/server-message.model';
|
|
54
54
|
export * from './models/subscription.model';
|
|
55
55
|
export * from './models/support-ticket.model';
|
|
56
56
|
export * from './models/user-group.model';
|
package/public_api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,r,o,t){void 0===t&&(t=o);var l=Object.getOwnPropertyDescriptor(r,o);l&&("get"in l?r.__esModule:!l.writable&&!l.configurable)||(l={enumerable:!0,get:function(){return r[o]}}),Object.defineProperty(e,t,l)}:function(e,r,o,t){e[t=void 0===t?o:t]=r[o]}),__exportStar=this&&this.__exportStar||function(e,r){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(r,o)||__createBinding(r,e,o)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./collections/app-status.collection"),exports),__exportStar(require("./collections/counter.collection"),exports),__exportStar(require("./collections/cron-job-history.collection"),exports),__exportStar(require("./collections/cron-job.collection"),exports),__exportStar(require("./collections/email-history.collection"),exports),__exportStar(require("./collections/email-verified.collection"),exports),__exportStar(require("./collections/file.collection"),exports),__exportStar(require("./collections/flag-update.collection"),exports),__exportStar(require("./collections/flag.collection"),exports),__exportStar(require("./collections/log-method-latency.collection"),exports),__exportStar(require("./collections/log-subscription.collection"),exports),__exportStar(require("./collections/log.collection"),exports),__exportStar(require("./collections/logged-in-users.collection"),exports),__exportStar(require("./collections/monitor-cpu.collection"),exports),__exportStar(require("./collections/monitor-function.collection"),exports),__exportStar(require("./collections/monitor-memory.collection"),exports),__exportStar(require("./collections/monitor-mongo.collection"),exports),__exportStar(require("./collections/notification.collection"),exports),__exportStar(require("./collections/report-builder-library.collection"),exports),__exportStar(require("./collections/report-builder-report.collection"),exports),__exportStar(require("./collections/user-group.collection"),exports),__exportStar(require("./collections/user-guide.collection"),exports),__exportStar(require("./collections/user.collection"),exports),__exportStar(require("./managers/mongo.manager"),exports),__exportStar(require("./models/app-status.model"),exports),__exportStar(require("./models/billing-logged-in-users.model"),exports),__exportStar(require("./models/collection-document.model"),exports),__exportStar(require("./models/counter.model"),exports),__exportStar(require("./models/cron-job-history.model"),exports),__exportStar(require("./models/cron-job.model"),exports),__exportStar(require("./models/dialog.model"),exports),__exportStar(require("./models/email-history.model"),exports),__exportStar(require("./models/email-verified.model"),exports),__exportStar(require("./models/file.model"),exports),__exportStar(require("./models/flag-update.model"),exports),__exportStar(require("./models/flag.model"),exports),__exportStar(require("./models/log-method-latency.model"),exports),__exportStar(require("./models/log-subscription.model"),exports),__exportStar(require("./models/log.model"),exports),__exportStar(require("./models/logged-in-users.model"),exports),__exportStar(require("./models/method-response.model"),exports),__exportStar(require("./models/method.model"),exports),__exportStar(require("./models/monitor-cpu.model"),exports),__exportStar(require("./models/monitor-memory.model"),exports),__exportStar(require("./models/monitor-mongo.model"),exports),__exportStar(require("./models/notification.model"),exports),__exportStar(require("./models/pagination.model"),exports),__exportStar(require("./models/permission.model"),exports),__exportStar(require("./models/report-builder-library.model"),exports),__exportStar(require("./models/report-builder-report.model"),exports),__exportStar(require("./models/report-builder.model"),exports),__exportStar(require("./models/select-data-label.model"),exports),__exportStar(require("./models/server-
|
|
1
|
+
"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,r,o,t){void 0===t&&(t=o);var l=Object.getOwnPropertyDescriptor(r,o);l&&("get"in l?r.__esModule:!l.writable&&!l.configurable)||(l={enumerable:!0,get:function(){return r[o]}}),Object.defineProperty(e,t,l)}:function(e,r,o,t){e[t=void 0===t?o:t]=r[o]}),__exportStar=this&&this.__exportStar||function(e,r){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(r,o)||__createBinding(r,e,o)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./collections/app-status.collection"),exports),__exportStar(require("./collections/counter.collection"),exports),__exportStar(require("./collections/cron-job-history.collection"),exports),__exportStar(require("./collections/cron-job.collection"),exports),__exportStar(require("./collections/email-history.collection"),exports),__exportStar(require("./collections/email-verified.collection"),exports),__exportStar(require("./collections/file.collection"),exports),__exportStar(require("./collections/flag-update.collection"),exports),__exportStar(require("./collections/flag.collection"),exports),__exportStar(require("./collections/log-method-latency.collection"),exports),__exportStar(require("./collections/log-subscription.collection"),exports),__exportStar(require("./collections/log.collection"),exports),__exportStar(require("./collections/logged-in-users.collection"),exports),__exportStar(require("./collections/monitor-cpu.collection"),exports),__exportStar(require("./collections/monitor-function.collection"),exports),__exportStar(require("./collections/monitor-memory.collection"),exports),__exportStar(require("./collections/monitor-mongo.collection"),exports),__exportStar(require("./collections/notification.collection"),exports),__exportStar(require("./collections/report-builder-library.collection"),exports),__exportStar(require("./collections/report-builder-report.collection"),exports),__exportStar(require("./collections/user-group.collection"),exports),__exportStar(require("./collections/user-guide.collection"),exports),__exportStar(require("./collections/user.collection"),exports),__exportStar(require("./managers/mongo.manager"),exports),__exportStar(require("./models/app-status.model"),exports),__exportStar(require("./models/billing-logged-in-users.model"),exports),__exportStar(require("./models/collection-document.model"),exports),__exportStar(require("./models/counter.model"),exports),__exportStar(require("./models/cron-job-history.model"),exports),__exportStar(require("./models/cron-job.model"),exports),__exportStar(require("./models/dialog.model"),exports),__exportStar(require("./models/email-history.model"),exports),__exportStar(require("./models/email-verified.model"),exports),__exportStar(require("./models/file.model"),exports),__exportStar(require("./models/flag-update.model"),exports),__exportStar(require("./models/flag.model"),exports),__exportStar(require("./models/log-method-latency.model"),exports),__exportStar(require("./models/log-subscription.model"),exports),__exportStar(require("./models/log.model"),exports),__exportStar(require("./models/logged-in-users.model"),exports),__exportStar(require("./models/method-response.model"),exports),__exportStar(require("./models/method.model"),exports),__exportStar(require("./models/monitor-cpu.model"),exports),__exportStar(require("./models/monitor-memory.model"),exports),__exportStar(require("./models/monitor-mongo.model"),exports),__exportStar(require("./models/notification.model"),exports),__exportStar(require("./models/pagination.model"),exports),__exportStar(require("./models/permission.model"),exports),__exportStar(require("./models/report-builder-library.model"),exports),__exportStar(require("./models/report-builder-report.model"),exports),__exportStar(require("./models/report-builder.model"),exports),__exportStar(require("./models/select-data-label.model"),exports),__exportStar(require("./models/server-message.model"),exports),__exportStar(require("./models/subscription.model"),exports),__exportStar(require("./models/support-ticket.model"),exports),__exportStar(require("./models/user-group.model"),exports),__exportStar(require("./models/user-guide.model"),exports),__exportStar(require("./models/user.model"),exports),__exportStar(require("./resolveio-server-app"),exports),__exportStar(require("./util/common"),exports);
|
|
2
2
|
//# sourceMappingURL=public_api.js.map
|