@resolveio/server-lib 20.6.22 → 20.6.23

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.
@@ -33,7 +33,7 @@ export declare class SubscriptionManager {
33
33
  private readonly LATENCY_UPDATE_INTERVAL;
34
34
  private readonly LATENCY_UPDATE_THRESHOLD_MS;
35
35
  private _invalidationDebounceTimers;
36
- private _invalidationPendingFlags;
36
+ private _invalidationPendingTimestamps;
37
37
  private readonly DEBOUNCE_DELAY;
38
38
  private readonly MAX_WAIT_TIME;
39
39
  constructor(wss: WebSocket.Server, serverConfig: any, monitorManagerFunction: MonitorManagerFunction);
@@ -1,2 +1,2 @@
1
- "use strict";var __awaiter=this&&this.__awaiter||function(e,i,o,s){return new(o=o||Promise)(function(n,t){function fulfilled(e){try{step(s.next(e))}catch(e){t(e)}}function rejected(e){try{step(s.throw(e))}catch(e){t(e)}}function step(e){var t;e.done?n(e.value):((t=e.value)instanceof o?t:new o(function(e){e(t)})).then(fulfilled,rejected)}step((s=s.apply(e,i||[])).next())})},__generator=this&&this.__generator||function(i,o){var s,r,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},c={next:verb(0),throw:verb(1),return:verb(2)};return"function"==typeof Symbol&&(c[Symbol.iterator]=function(){return this}),c;function verb(n){return function(e){var t=[n,e];if(s)throw new TypeError("Generator is already executing.");for(;l=c&&t[c=0]?0:l;)try{if(s=1,r&&(a=2&t[0]?r.return:t[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,t[1])).done)return a;switch(r=0,(t=a?[2&t[0],a.value]:t)[0]){case 0:case 1:a=t;break;case 4:return l.label++,{value:t[1],done:!1};case 5:l.label++,r=t[1],t=[0];continue;case 7:t=l.ops.pop(),l.trys.pop();continue;default:if(!(a=0<(a=l.trys).length&&a[a.length-1])&&(6===t[0]||2===t[0])){l=0;continue}if(3===t[0]&&(!a||t[1]>a[0]&&t[1]<a[3]))l.label=t[1];else if(6===t[0]&&l.label<a[1])l.label=a[1],a=t;else{if(!(a&&l.label<a[2])){a[2]&&l.ops.pop(),l.trys.pop();continue}l.label=a[2],l.ops.push(t)}}t=o.call(i,l)}catch(e){t=[6,e],r=0}finally{s=a=0}if(5&t[0])throw t[1];return{value:t[0]?t[1]:void 0,done:!0}}}},__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return{value:(e=e&&i>=e.length?void 0:e)&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},__read=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,o,s=n.call(e),r=[];try{for(;(void 0===t||0<t--)&&!(i=s.next()).done;)r.push(i.value)}catch(e){o={error:e}}finally{try{i&&!i.done&&(n=s.return)&&n.call(s)}finally{if(o)throw o.error}}return r},__spreadArray=this&&this.__spreadArray||function(e,t,n){if(n||2===arguments.length)for(var i,o=0,s=t.length;o<s;o++)!i&&o in t||((i=i||Array.prototype.slice.call(t,0,o))[o]=t[o]);return e.concat(i||Array.prototype.slice.call(t))},logs_1=(Object.defineProperty(exports,"__esModule",{value:!0}),exports.SubscriptionManager=void 0,require("../publications/logs")),app_status_1=require("../publications/app-status"),files_1=require("../publications/files"),super_admin_1=require("../publications/super-admin"),logged_in_users_collection_1=require("../collections/logged-in-users.collection"),cron_jobs_1=require("../publications/cron-jobs"),flags_1=require("../publications/flags"),method_responses_1=require("../publications/method-responses"),resolveio_server_app_1=require("../resolveio-server-app"),notifications_1=require("../publications/notifications"),report_builder_reports_1=require("../publications/report-builder-reports"),report_builder_libraries_1=require("../publications/report-builder-libraries"),user_groups_1=require("../publications/user-groups"),user_guides_1=require("../publications/user-guides"),report_builder_dashboard_builders_1=require("../publications/report-builder-dashboard-builders"),common_1=require("../util/common"),NodeCache=require("node-cache"),flag_collection_1=require("../collections/flag.collection"),os_1=require("os"),flags_update_1=require("../publications/flags-update"),numCPUs=(0,os_1.cpus)().length,v8=require("v8"),SubscriptionManager=function(){function SubscriptionManager(e,t,n){var i=this;this._publications={},this._subscriptions=[],this._loggedInUsers=[],this._mongoQueue=[],this._mongoQueueId=0,this._cacheId=1,this._heapSize=v8.getHeapStatistics()/numCPUs,this._enableDebug=!1,this._debugOplogCollections=[],this._debugOplogHits=0,this._debugSubCollections=[],this._debugSubHits=0,this._debugUnSubHits=0,this._debugUnSubAllHits=0,this._debugMongoQueueHits=0,this._debugMongoQueueCollections=[],this._debugSendQueueHits=0,this._debugRemoveCacheHits=0,this._oplogRetryCount=0,this.latencyBuffer=new Map,this.LATENCY_UPDATE_INTERVAL=6e4,this.LATENCY_UPDATE_THRESHOLD_MS=3e4,this._invalidationDebounceTimers=new Map,this._invalidationPendingFlags=new Map,this.DEBOUNCE_DELAY=100,this.MAX_WAIT_TIME=500,this._websocketManager=resolveio_server_app_1.ResolveIOServer.getMainServer().getWebSocketManager(),this._monitorManagerFunction=n,this._nodeCache=new NodeCache({stdTTL:0,checkperiod:0}),setInterval(function(){return i.flushThrottledLatencyUpdates()},this.LATENCY_UPDATE_INTERVAL),this.serverConfig=t,this._wss=e,(0,super_admin_1.loadSuperAdminPublications)(this),(0,app_status_1.loadAppStatusPublications)(this),(0,logs_1.loadLogPublications)(this),(0,files_1.loadFilePublications)(this),(0,cron_jobs_1.loadCronJobPublications)(this),(0,flags_update_1.loadFlagsUpdatePublications)(this),(0,flags_1.loadFlagsPublications)(this),(0,method_responses_1.loadMethodResponsePublications)(this),(0,notifications_1.loadNotificationPublications)(this),(0,report_builder_reports_1.loadReportBuilderReportPublications)(this),(0,report_builder_libraries_1.loadReportBuilderLibraryPublications)(this),(0,user_groups_1.loadUserGroupPublications)(this),(0,user_guides_1.loadUserGuidePublications)(this),(0,report_builder_dashboard_builders_1.loadReportBuilderDashboardBuilderPublications)(this),this.tailOpLog(),setInterval(function(){i._oplogRetryCount=0},15e3),setInterval(function(){i.getEnableDebug()&&(console.log(new Date,"Sub Manager","Subs",i._subscriptions.length),console.log(new Date,"Sub Manager","Logged In Users",i._loggedInUsers.length),console.log(new Date,"Sub Manager","Mongo Queue",i._mongoQueue.length),console.log(new Date,"Sub Manager","Mongo Queue Hits",i._debugMongoQueueHits),console.log(new Date,"Sub Manager","Mongo Queue Collections",JSON.stringify(i._debugMongoQueueCollections.sort(function(e,t){return e.collection.localeCompare(t.collection)||e.publication.localeCompare(t.publication)}),null,2)),console.log(new Date,"Sub Manager","Oplog Hits",i._debugOplogHits),console.log(new Date,"Sub Manager","Oplog Collections",JSON.stringify(i._debugOplogCollections.sort(function(e,t){return e.collection.localeCompare(t.collection)||e.type.localeCompare(t.type)}),null,2)),console.log(new Date,"Sub Manager","Send Queue Hits",i._debugSendQueueHits),console.log(new Date,"Sub Manager","Sub Hits",i._debugSubHits),console.log(new Date,"Sub Manager","Sub Collections",JSON.stringify(i._debugSubCollections.sort(function(e,t){return e.publication.localeCompare(t.publication)}),null,2)),console.log(new Date,"Sub Manager","Unsub Hits",i._debugUnSubHits),console.log(new Date,"Sub Manager","Unsub All Hits",i._debugUnSubAllHits),console.log(new Date,"Sub Manager","Cache Cleanup Hits",i._debugRemoveCacheHits)),i._debugOplogHits=0,i._debugOplogCollections=[],i._debugSubCollections=[],i._debugMongoQueueHits=0,i._debugMongoQueueCollections=[],i._debugSendQueueHits=0,i._debugSubHits=0,i._debugUnSubHits=0,i._debugUnSubAllHits=0,i._debugRemoveCacheHits=0},6e4),setInterval(function(){return __awaiter(i,void 0,void 0,function(){var t,i,n,o,s,r,a,l,c;return __generator(this,function(e){switch(e.label){case 0:return t=this,[4,logged_in_users_collection_1.LoggedInUsers.find()];case 1:for(t._loggedInUsers=e.sent(),i=(0,common_1.deepCopy)(this._loggedInUsers),n=function(e){var n=i[e];(!n.date||12e4<Date.now()-n.date.getTime())&&(o._websocketManager.getWebSocket(n.id_ws)?(o.getEnableDebug()&&console.log(new Date,"Sub Manager","Unsub WS",o._websocketManager.getWebSocket(n.id_ws).user,o._websocketManager.getWebSocket(n.id_ws).id_socket,2),o.unsubscribeAll(o._websocketManager.getWebSocket(n.id_ws))):(o._subscriptions.forEach(function(e){for(var t=e.clients.length-1;0<=t;t--)e.clients[t].id_socket===n.id_ws&&e.clients.splice(t,1)}),logged_in_users_collection_1.LoggedInUsers.deleteOne({_id:n._id}),0<=o._loggedInUsers.findIndex(function(e){return e._id===n._id})&&o._loggedInUsers.splice(o._loggedInUsers.findIndex(function(e){return e._id===n._id}),1)))},s=(o=this)._loggedInUsers.length-1;0<=s;s--)n(s);for(s=0;s<this._subscriptions.length;s++)for(r=this._subscriptions[s],a=function(e){var t=r.clients[e];l._loggedInUsers.some(function(e){return e.id_ws===t.id_socket})||r.clients.splice(e,1)},l=this,c=r.clients.length-1;0<=c;c--)a(c);return[2]}})})},3e4),flag_collection_1.Flags.findOne({type:"Enable Debug"}).then(function(e){e&&e.value?i._enableDebug=!0:i._enableDebug=!1}),this.setCacheLimit()}return SubscriptionManager.prototype.setCacheLimit=function(){"true"===process.env.IS_WORKERS_ENABLED?this._heapLimit=.4*this._heapSize:this._heapLimit=.3*this._heapSize},SubscriptionManager.prototype.invalidatePubsCache=function(o,s){return __awaiter(this,void 0,void 0,function(){var t,n,i=this;return __generator(this,function(e){return t=o,n=Date.now(),this._invalidationPendingFlags.has(t)&&n-this._invalidationPendingFlags.get(t)>this.MAX_WAIT_TIME?(this._invalidationDebounceTimers.has(t)&&clearTimeout(this._invalidationDebounceTimers.get(t)),this._executeInvalidation(o,s)):(this._invalidationPendingFlags.has(t)||this._invalidationPendingFlags.set(t,n),this._invalidationDebounceTimers.has(t)&&clearTimeout(this._invalidationDebounceTimers.get(t)),this._invalidationDebounceTimers.set(t,setTimeout(function(){i._executeInvalidation(o,s),i._invalidationPendingFlags.delete(t)},this.DEBOUNCE_DELAY))),[2]})})},SubscriptionManager.prototype._executeInvalidation=function(u,g){return __awaiter(this,void 0,void 0,function(){var t,n,i,o,s,r,a,l,c=this;return __generator(this,function(e){switch(e.label){case 0:this._invalidationDebounceTimers.delete(u),resolveio_server_app_1.ResolveIOServer.getMongoManager().invalidateQueryCache(u),t=this._subscriptions.filter(function(e){return e.collections.includes(u)}),n=function(o){return __generator(this,function(e){switch(e.label){case 0:return(i._enableDebug&&console.log(new Date,"Invalidate Sub",o.publication,o.running,o.runAgain),o.running)?(o.runAgain=!0,[2,"continue"]):i._publications[o.publication].user_specific?(Promise.all(o.clients.map(function(i){return __awaiter(c,void 0,void 0,function(){var t,n;return __generator(this,function(e){switch(e.label){case 0:if(!(t=this._websocketManager.getWebSocket(i.id_socket))||t.readyState!==t.OPEN)return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,this.sendDataToOneWithRetry(t,i.messageId,o,u,g)];case 2:return e.sent(),[3,4];case 3:return n=e.sent(),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail("dev@resolveio.com","SERVER - Error Detected - "+this.serverConfig.CLIENT_NAME,"Error Detected During sendDataToOne - User Specific - Socket: "+i.id_socket+", User: "+i.id_user+", MessageId: "+i.messageId+", Pub: "+o.publication+", Err: "+JSON.stringify(n,null,2)),[3,4];case 4:return[2]}})})})),[3,3]):[3,1];case 1:return[4,i.sendDataToAllWithRetry(o,u,g)];case 2:e.sent(),e.label=3;case 3:return[2]}})},i=this,e.label=1;case 1:e.trys.push([1,6,7,8]),o=__values(t),s=o.next(),e.label=2;case 2:return s.done?[3,5]:(r=s.value,[5,n(r)]);case 3:e.sent(),e.label=4;case 4:return s=o.next(),[3,2];case 5:return[3,8];case 6:return r=e.sent(),a={error:r},[3,8];case 7:try{s&&!s.done&&(l=o.return)&&l.call(o)}finally{if(a)throw a.error}return[7];case 8:return[2]}})})},SubscriptionManager.prototype.delay=function(t){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){return[2,new Promise(function(e){return setTimeout(e,t)})]})})},SubscriptionManager.prototype.sendDataToAllWithRetry=function(t,n,i){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){switch(e.label){case 0:t.running=!0,e.label=1;case 1:return this._enableDebug&&console.log(new Date,"Running sendDataToAll Sub",t.publication),t.runAgain=!1,[4,this.sendDataToAll(t,n,i)];case 2:return(e.sent(),this._enableDebug&&console.log(new Date,"Done sendDataToAll Sub",t.publication,t.runAgain),t.runAgain)?[4,this.delay(500)]:[3,4];case 3:e.sent(),e.label=4;case 4:if(t.runAgain)return[3,1];e.label=5;case 5:return t.running=!1,[2]}})})},SubscriptionManager.prototype.sendDataToOneWithRetry=function(t,n,i,o,s){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){switch(e.label){case 0:i.running=!0,e.label=1;case 1:return this._enableDebug&&console.log(new Date,"Running sendDataToOne Sub",i.publication),i.runAgain=!1,[4,this.sendDataToOne(t,n,i,o,s)];case 2:return(e.sent(),this._enableDebug&&console.log(new Date,"Done sendDataToOne Sub",i.publication,i.runAgain),i.runAgain)?[4,this.delay(500)]:[3,4];case 3:e.sent(),e.label=4;case 4:if(i.runAgain)return[3,1];e.label=5;case 5:return i.running=!1,[2]}})})},SubscriptionManager.prototype.publications=function(e){this._publications=Object.assign(this._publications,e)},SubscriptionManager.prototype.loggedInLatency=function(t){var e,n,i,o=this._loggedInUsers.find(function(e){return e.id_ws===t.id_socket});o&&(e=new Date,n=this.latencyBuffer.get(t.id_socket),i=t.latency,!n||e.getTime()-n.lastUpdate.getTime()>=this.LATENCY_UPDATE_THRESHOLD_MS||100<Math.abs(i-n.latency))&&(o.date=e,this.latencyBuffer.set(t.id_socket,{latency:i,lastUpdate:e}))},SubscriptionManager.prototype.flushThrottledLatencyUpdates=function(){return __awaiter(this,void 0,void 0,function(){var t,n;return __generator(this,function(e){switch(e.label){case 0:if(0===this.latencyBuffer.size)return[2];t=Array.from(this.latencyBuffer.entries()).map(function(e){var e=__read(e,2),t=e[0],e=e[1];return{updateOne:{filter:{id_ws:t},update:{$set:{latency:e.latency,date:e.lastUpdate}}}}}),e.label=1;case 1:return e.trys.push([1,3,,4]),[4,logged_in_users_collection_1.LoggedInUsers.bulkWrite(t)];case 2:return e.sent(),this.latencyBuffer.clear(),this.getEnableDebug()&&console.log(new Date,"Sub Manager","Throttled latency batch update successful",t.length),[3,4];case 3:return n=e.sent(),console.error(new Date,"Sub Manager","Throttled latency batch update failed",n),[3,4];case 4:return[2]}})})},SubscriptionManager.prototype.subscribe=function(t,e,n,i,o,s){var r=this,a=(this._debugSubHits+=1,this._debugSubCollections.some(function(e){return e.publication===o})?this._debugSubCollections.find(function(e){return e.publication===o}).hits+=1:this._debugSubCollections.push({publication:o,hits:1}),this._publications[o]);if(a){if(1<s.length||s[0]){if(!a.check)return void console.error(new Date,"No Check Function For Pub "+o);if(!a.check._schema)return void console.error(new Date,"No Check Schema For Pub "+o);for(var l={},c=Object.keys(a.check._schema).filter(function(e){return!e.includes(".")}),u=0;u<s.length;u++)l[c[u]]=s[u];try{a.check.validate(l)}catch(e){if(e)return void console.error(new Date,"Error in Pub Check ("+o+")",e)}}"Bypass"!==t&&(a=t.split("/"),g="",_=a[0],""===a[0]&&(g="/",_=a[1]),g+=_,1<a.length&&(g+="/"),(_=this._subscriptions.filter(function(e){return e.clients.some(function(e){return e.id_socket===n.id_socket&&"Bypass"!==e.messageRoute&&"/"!==e.messageRoute&&e.messageRoute!==t&&!e.messageRoute.startsWith(g)})})).length)&&_.forEach(function(t){t.clients.filter(function(e){return e.id_socket===n.id_socket}).forEach(function(e){r.unsubscribe(e.messageRoute,new Date,n,e.messageId,t.publication,t.subscriptionData)})});var g,_,a=this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)});a?a.clients.some(function(e){return e.id_socket===n.id_socket&&e.messageId===i})||a.clients.push({id_user:n.id_user,messageId:i,id_socket:n.id_socket,messageRoute:t}):this._subscriptions.push({publication:o,subscriptionData:s,collections:this.getPublicationCollections(o),clients:[{id_user:n.id_user,messageId:i,id_socket:n.id_socket,messageRoute:t}],cacheId:0,running:!1,runAgain:!1}),a=a||this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)}),this._enableDebug&&console.log(new Date,"New Sub",a.publication,a.running,a.runAgain,a.clients.length),this.processSubscription(a,n,i)}else console.error(new Date,"No Publication: "+o)},SubscriptionManager.prototype.createLoggedInUser=function(i){return __awaiter(this,void 0,void 0,function(){var t=this;return __generator(this,function(e){return[2,new Promise(function(n,e){return __awaiter(t,void 0,void 0,function(){var t;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i))?(t={_id:(0,common_1.objectIdHexString)(),__v:0,date:new Date,id_user:t.id_user,user:t.user,id_ws:t.id_socket},this._loggedInUsers.push(t),logged_in_users_collection_1.LoggedInUsers.insertOne(t),n(t)):n(null),[2]})})})]})})},SubscriptionManager.prototype.unsubscribe=function(e,t,n,i,o,s){if(this._debugUnSubHits+=1,this._publications[o]){var r=this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)});if(r){for(var a=r.clients.length-1;0<=a;a--)r.clients[a].id_user===n.id_user&&r.clients[a].messageId===i&&r.clients[a].id_socket===n.id_socket&&r.clients.splice(a,1);this._enableDebug&&console.log(new Date,"Unsub",r.publication,r.running,r.runAgain,r.clients.length)}}else console.log("No Publication: "+o)},SubscriptionManager.prototype.unsubscribeAll=function(s){return __awaiter(this,void 0,void 0,function(){var t,n,i,o;return __generator(this,function(e){if(this._debugUnSubAllHits+=1,s){if(s.isUnsubscribed)return[2];for(s.isUnsubscribed=!0,0<=this._loggedInUsers.map(function(e){return e.id_ws}).indexOf(s.id_socket)&&this._loggedInUsers.splice(this._loggedInUsers.map(function(e){return e.id_ws}).indexOf(s.id_socket),1),logged_in_users_collection_1.LoggedInUsers.deleteOne({id_ws:s.id_socket}),t=this._subscriptions.filter(function(e){return e.clients.some(function(e){return e.id_user===s.id_user&&e.id_socket===s.id_socket})}),n=t.length-1;0<=n;n--)for(i=t[n],o=i.clients.length-1;0<=o;o--)i.clients[o].id_socket===s.id_socket&&i.clients.splice(o,1);this._websocketManager.removeWebSocket(s)}return[2]})})},SubscriptionManager.prototype.getActiveSubscriptions=function(){return this._subscriptions},SubscriptionManager.prototype.getPublicationCollections=function(e){return this._publications[e].collections},SubscriptionManager.prototype.tailOpLog=function(o){return __awaiter(this,void 0,void 0,function(){var t,n,i=this;return __generator(this,function(e){switch(e.label){case 0:return this._oplog$&&!this._oplog$.closed&&(this._oplog$.removeAllListeners(),this._oplog$.close(),this._oplog$=null),[4,new Promise(function(e){return setTimeout(e,1e3)})];case 1:if(e.sent(),!this._oplog$||this._oplog$.closed){if(this._oplogRetryCount+=1,5<this._oplogRetryCount&&(console.error("****************** TAIL OPLOG ERROR, RETRYING A BUNCH OF TIMES, KILLING PROCESS **************************"),process.exit(1)),t=[{$match:{$and:[{"ns.coll":{$nin:["log-method-latencies","log-subscriptions","logs","counters","cron-job-histories","email-histories","qb-soap-request-histories","qb-soap-request-responses","qb-soap-requests","qb-soap-retries"]}},{"ns.coll":{$not:/.*\.versions$/}},{"ns.coll":{$not:/^monitor-/}}]}}],o){n=o;try{this._oplog$=resolveio_server_app_1.ResolveIOServer.getMainDB().watch(t,{resumeAfter:o})}catch(e){return this._oplog$&&(this._oplog$.removeAllListeners(),this._oplog$.close(),this._oplog$=null),this.tailOpLog(o),[2]}}else this._oplog$=resolveio_server_app_1.ResolveIOServer.getMainDB().watch(t);console.log(new Date,"oplog started"),this._oplog$.on("change",function(t){var e;t.ns&&(i._enableDebug&&console.log(new Date,"Oplog Hit",t.ns),e=t.ns.coll,i._debugOplogCollections.some(function(e){return e.collection===t.ns.coll&&e.type===t.operationType})?i._debugOplogCollections.find(function(e){return e.collection===t.ns.coll&&e.type===t.operationType}).hits+=1:i._debugOplogCollections.push({collection:t.ns.coll,type:t.operationType,hits:1}),e&&(i._debugOplogHits+=1,"insert"===t.operationType?("support-tickets"===e&&"https://resolveio.com"===i.serverConfig.ROOT_URL&&(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"sendSupportTicketEmail",t.documentKey._id),i.invalidatePubsCache(e,"insert")),"method-responses"!==e&&i.invalidatePubsCache(e,"insert")):"update"===t.operationType||"replace"===t.operationType?"method-responses"!==e&&i.invalidatePubsCache(e,"update"):"delete"===t.operationType&&"method-responses"!==e&&i.invalidatePubsCache(e,"delete")),"flags"===e&&flag_collection_1.Flags.findOne({type:"Enable Debug"}).then(function(e){e&&e.value?i._enableDebug=!0:i._enableDebug=!1}),n=t._id,process.env.NODE_APP_INSTANCE&&"0"!==process.env.NODE_APP_INSTANCE||"false"!==process.env.IS_WORKERS_ENABLED&&"true"===process.env.IS_WORKER_INSTANCE&&process.env.WORKER_INDEX)}),this._oplog$.on("error",function(e){console.log(new Date,"oplog error",e),i._oplog$.removeAllListeners(),i._oplog$.close(),i._oplog$=null,i.tailOpLog(n)}),this._oplog$.on("end",function(){console.log(new Date,"oplog end"),i._oplog$.removeAllListeners(),i._oplog$.close(),i._oplog$=null,i.tailOpLog(n)}),this._oplog$.on("close",function(){console.log(new Date,"oplog close"),i._oplog$.removeAllListeners(),i._oplog$=null,i.tailOpLog(n)})}return[2]}})})},SubscriptionManager.prototype.processSubscription=function(i,o,s){return __awaiter(this,void 0,void 0,function(){var t,n;return __generator(this,function(e){if(this._publications[i.publication].user_specific){if(this._enableDebug&&console.log(new Date,"Process Sub Specific, Non - Cache",i.publication,i.running),i.running)return[2];this.sendDataToOneWithRetry(o,s,i,"","newSub")}else if(i.cacheId)try{t=JSON.parse(this._nodeCache.get(i.cacheId),common_1.dateReviver),n={messageId:s,hasError:!1,data:t},this._enableDebug&&console.log(new Date,"Process Sub, Cache",i.publication),this.sendWS(o,n)}catch(e){this._nodeCache.del(i.cacheId),i.cacheId=0,this.sendDataToAllWithRetry(i,"","newSub")}else{if(this._enableDebug&&console.log(new Date,"Process Sub, Non - Cache",i.publication,i.running),i.running)return[2];this.sendDataToAllWithRetry(i,"","newSub")}return[2]})})},SubscriptionManager.prototype.sendDataToOne=function(s,r,a,l,c){return __awaiter(this,void 0,void 0,function(){var t,n,i,o;return __generator(this,function(e){switch(e.label){case 0:t=this._monitorManagerFunction.startMonitorFunction("User Specific Publication",a.publication,"","",a.subscriptionData),e.label=1;case 1:return e.trys.push([1,3,,4]),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"insertSubscriptionLog",c,a.publication,l,JSON.stringify(a.subscriptionData)),[4,(o=this._publications[a.publication].function).call.apply(o,__spreadArray([Object.assign({},this,SubscriptionManager.prototype),s.id_user],__read(a.subscriptionData),!1))];case 2:return o=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),i={messageId:r,hasError:!1,data:o},this.sendWS(s,i),[3,4];case 3:return n=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),i={messageId:r,hasError:!0,data:n},this.sendWS(s,i),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail("dev@resolveio.com","SERVER - Error Detected - "+this.serverConfig.CLIENT_NAME,"Error Detected During Subscription "+a.publication+" - (sendDataToOne - WS)\n\nData \n"+JSON.stringify(a.subscriptionData,null,2)+"\n\nErrors\n"+JSON.stringify(n,null,2)),[3,4];case 4:return[2]}})})},SubscriptionManager.prototype.sendDataToAll=function(g,_,d){return __awaiter(this,void 0,void 0,function(){var t,o,n,i,s,r,a,l,c,u=this;return __generator(this,function(e){switch(e.label){case 0:return g.clients.length?[3,1]:(g.cacheId&&(this._nodeCache.del(g.cacheId),g.cacheId=0),0<=(c=this._subscriptions.findIndex(function(e){return e.publication===g.publication&&JSON.stringify(e.subscriptionData)===JSON.stringify(g.subscriptionData)}))&&this._subscriptions.splice(c,1),[2]);case 1:t=this._monitorManagerFunction.startMonitorFunction("Publication",g.publication,"","",g.subscriptionData),e.label=2;case 2:return e.trys.push([2,4,,5]),"superadminAPM"!==g.publication&&"loggedInUsers"!==g.publication&&resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"insertSubscriptionLog",d,g.publication,_,JSON.stringify(g.subscriptionData)),[4,(c=this._publications[g.publication].function).call.apply(c,__spreadArray([Object.assign({},this,SubscriptionManager.prototype)],__read(g.subscriptionData),!1))];case 3:if(o=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),g.cacheId)try{n=JSON.parse(this._nodeCache.get(g.cacheId),common_1.dateReviver),JSON.stringify(n)!==JSON.stringify(o)&&(Promise.all(g.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),this._nodeCache.del(g.cacheId),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!g.collections.includes("logs")&&!g.collections.find(function(e){return e.endsWith(".versions")})&&!g.collections.find(function(e){return e.startsWith("monitor-")})?this._nodeCache.set(g.cacheId,JSON.stringify(o)):g.cacheId=0)}catch(e){Promise.all(g.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),this._nodeCache.del(g.cacheId),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!g.collections.includes("logs")&&!g.collections.find(function(e){return e.endsWith(".versions")})&&!g.collections.find(function(e){return e.startsWith("monitor-")})?this._nodeCache.set(g.cacheId,JSON.stringify(o)):g.cacheId=0}else if(Promise.all(g.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!g.collections.includes("logs")&&!g.collections.find(function(e){return e.endsWith(".versions")})&&!g.collections.find(function(e){return e.startsWith("monitor-")})){if(g.cacheId=this._cacheId++,this._nodeCache.set(g.cacheId,JSON.stringify(o)),(i=this._nodeCache.getStats().vsize)>this._heapLimit){for(s=0,r=this._subscriptions.filter(function(e){return e.cacheId&&!e.clients.length}),a=0;a<r.length&&(this._debugRemoveCacheHits+=1,this._nodeCache.del(r[a].cacheId),r[a].cacheId=0,s+=1,!(this._nodeCache.getStats().vsize<.75*this._heapLimit));a++);this._enableDebug&&console.log("Sub Cache: Too Big - "+g.publication+" - Deleted: "+s+" - "+i)}}else g.cacheId=0;return[3,5];case 4:return l=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),Promise.all(g.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!0,data:l},this.sendWS(t,n)),[2]})})})),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail("dev@resolveio.com","SERVER - Error Detected - "+this.serverConfig.CLIENT_NAME,"Error Detected During Subscription "+g.publication+" - (sendPubData)\n\nData \n"+JSON.stringify(g.subscriptionData,null,2)+"\n\nErrors\n"+JSON.stringify(l,null,2)),[3,5];case 5:return[2]}})})},SubscriptionManager.prototype.sendWS=function(e,t){this._websocketManager.send(e,t)},SubscriptionManager.prototype.getEnableDebug=function(){return this._enableDebug},SubscriptionManager}();exports.SubscriptionManager=SubscriptionManager;
1
+ "use strict";var __awaiter=this&&this.__awaiter||function(e,i,o,s){return new(o=o||Promise)(function(n,t){function fulfilled(e){try{step(s.next(e))}catch(e){t(e)}}function rejected(e){try{step(s.throw(e))}catch(e){t(e)}}function step(e){var t;e.done?n(e.value):((t=e.value)instanceof o?t:new o(function(e){e(t)})).then(fulfilled,rejected)}step((s=s.apply(e,i||[])).next())})},__generator=this&&this.__generator||function(i,o){var s,r,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},c={next:verb(0),throw:verb(1),return:verb(2)};return"function"==typeof Symbol&&(c[Symbol.iterator]=function(){return this}),c;function verb(n){return function(e){var t=[n,e];if(s)throw new TypeError("Generator is already executing.");for(;l=c&&t[c=0]?0:l;)try{if(s=1,r&&(a=2&t[0]?r.return:t[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,t[1])).done)return a;switch(r=0,(t=a?[2&t[0],a.value]:t)[0]){case 0:case 1:a=t;break;case 4:return l.label++,{value:t[1],done:!1};case 5:l.label++,r=t[1],t=[0];continue;case 7:t=l.ops.pop(),l.trys.pop();continue;default:if(!(a=0<(a=l.trys).length&&a[a.length-1])&&(6===t[0]||2===t[0])){l=0;continue}if(3===t[0]&&(!a||t[1]>a[0]&&t[1]<a[3]))l.label=t[1];else if(6===t[0]&&l.label<a[1])l.label=a[1],a=t;else{if(!(a&&l.label<a[2])){a[2]&&l.ops.pop(),l.trys.pop();continue}l.label=a[2],l.ops.push(t)}}t=o.call(i,l)}catch(e){t=[6,e],r=0}finally{s=a=0}if(5&t[0])throw t[1];return{value:t[0]?t[1]:void 0,done:!0}}}},__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return{value:(e=e&&i>=e.length?void 0:e)&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},__read=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,o,s=n.call(e),r=[];try{for(;(void 0===t||0<t--)&&!(i=s.next()).done;)r.push(i.value)}catch(e){o={error:e}}finally{try{i&&!i.done&&(n=s.return)&&n.call(s)}finally{if(o)throw o.error}}return r},__spreadArray=this&&this.__spreadArray||function(e,t,n){if(n||2===arguments.length)for(var i,o=0,s=t.length;o<s;o++)!i&&o in t||((i=i||Array.prototype.slice.call(t,0,o))[o]=t[o]);return e.concat(i||Array.prototype.slice.call(t))},logs_1=(Object.defineProperty(exports,"__esModule",{value:!0}),exports.SubscriptionManager=void 0,require("../publications/logs")),app_status_1=require("../publications/app-status"),files_1=require("../publications/files"),super_admin_1=require("../publications/super-admin"),logged_in_users_collection_1=require("../collections/logged-in-users.collection"),cron_jobs_1=require("../publications/cron-jobs"),flags_1=require("../publications/flags"),method_responses_1=require("../publications/method-responses"),resolveio_server_app_1=require("../resolveio-server-app"),notifications_1=require("../publications/notifications"),report_builder_reports_1=require("../publications/report-builder-reports"),report_builder_libraries_1=require("../publications/report-builder-libraries"),user_groups_1=require("../publications/user-groups"),user_guides_1=require("../publications/user-guides"),report_builder_dashboard_builders_1=require("../publications/report-builder-dashboard-builders"),common_1=require("../util/common"),NodeCache=require("node-cache"),flag_collection_1=require("../collections/flag.collection"),os_1=require("os"),flags_update_1=require("../publications/flags-update"),numCPUs=(0,os_1.cpus)().length,v8=require("v8"),SubscriptionManager=function(){function SubscriptionManager(e,t,n){var i=this;this._publications={},this._subscriptions=[],this._loggedInUsers=[],this._mongoQueue=[],this._mongoQueueId=0,this._cacheId=1,this._heapSize=v8.getHeapStatistics()/numCPUs,this._enableDebug=!1,this._debugOplogCollections=[],this._debugOplogHits=0,this._debugSubCollections=[],this._debugSubHits=0,this._debugUnSubHits=0,this._debugUnSubAllHits=0,this._debugMongoQueueHits=0,this._debugMongoQueueCollections=[],this._debugSendQueueHits=0,this._debugRemoveCacheHits=0,this._oplogRetryCount=0,this.latencyBuffer=new Map,this.LATENCY_UPDATE_INTERVAL=6e4,this.LATENCY_UPDATE_THRESHOLD_MS=3e4,this._invalidationDebounceTimers=new Map,this._invalidationPendingTimestamps=new Map,this.DEBOUNCE_DELAY=100,this.MAX_WAIT_TIME=500,this._websocketManager=resolveio_server_app_1.ResolveIOServer.getMainServer().getWebSocketManager(),this._monitorManagerFunction=n,this._nodeCache=new NodeCache({stdTTL:0,checkperiod:0}),setInterval(function(){return i.flushThrottledLatencyUpdates()},this.LATENCY_UPDATE_INTERVAL),this.serverConfig=t,this._wss=e,(0,super_admin_1.loadSuperAdminPublications)(this),(0,app_status_1.loadAppStatusPublications)(this),(0,logs_1.loadLogPublications)(this),(0,files_1.loadFilePublications)(this),(0,cron_jobs_1.loadCronJobPublications)(this),(0,flags_update_1.loadFlagsUpdatePublications)(this),(0,flags_1.loadFlagsPublications)(this),(0,method_responses_1.loadMethodResponsePublications)(this),(0,notifications_1.loadNotificationPublications)(this),(0,report_builder_reports_1.loadReportBuilderReportPublications)(this),(0,report_builder_libraries_1.loadReportBuilderLibraryPublications)(this),(0,user_groups_1.loadUserGroupPublications)(this),(0,user_guides_1.loadUserGuidePublications)(this),(0,report_builder_dashboard_builders_1.loadReportBuilderDashboardBuilderPublications)(this),this.tailOpLog(),setInterval(function(){i._oplogRetryCount=0},15e3),setInterval(function(){i.getEnableDebug()&&(console.log(new Date,"Sub Manager","Subs",i._subscriptions.length),console.log(new Date,"Sub Manager","Logged In Users",i._loggedInUsers.length),console.log(new Date,"Sub Manager","Mongo Queue",i._mongoQueue.length),console.log(new Date,"Sub Manager","Mongo Queue Hits",i._debugMongoQueueHits),console.log(new Date,"Sub Manager","Mongo Queue Collections",JSON.stringify(i._debugMongoQueueCollections.sort(function(e,t){return e.collection.localeCompare(t.collection)||e.publication.localeCompare(t.publication)}),null,2)),console.log(new Date,"Sub Manager","Oplog Hits",i._debugOplogHits),console.log(new Date,"Sub Manager","Oplog Collections",JSON.stringify(i._debugOplogCollections.sort(function(e,t){return e.collection.localeCompare(t.collection)||e.type.localeCompare(t.type)}),null,2)),console.log(new Date,"Sub Manager","Send Queue Hits",i._debugSendQueueHits),console.log(new Date,"Sub Manager","Sub Hits",i._debugSubHits),console.log(new Date,"Sub Manager","Sub Collections",JSON.stringify(i._debugSubCollections.sort(function(e,t){return e.publication.localeCompare(t.publication)}),null,2)),console.log(new Date,"Sub Manager","Unsub Hits",i._debugUnSubHits),console.log(new Date,"Sub Manager","Unsub All Hits",i._debugUnSubAllHits),console.log(new Date,"Sub Manager","Cache Cleanup Hits",i._debugRemoveCacheHits)),i._debugOplogHits=0,i._debugOplogCollections=[],i._debugSubCollections=[],i._debugMongoQueueHits=0,i._debugMongoQueueCollections=[],i._debugSendQueueHits=0,i._debugSubHits=0,i._debugUnSubHits=0,i._debugUnSubAllHits=0,i._debugRemoveCacheHits=0},6e4),setInterval(function(){return __awaiter(i,void 0,void 0,function(){var t,i,n,o,s,r,a,l,c;return __generator(this,function(e){switch(e.label){case 0:return t=this,[4,logged_in_users_collection_1.LoggedInUsers.find()];case 1:for(t._loggedInUsers=e.sent(),i=(0,common_1.deepCopy)(this._loggedInUsers),n=function(e){var n=i[e];(!n.date||12e4<Date.now()-n.date.getTime())&&(o._websocketManager.getWebSocket(n.id_ws)?(o.getEnableDebug()&&console.log(new Date,"Sub Manager","Unsub WS",o._websocketManager.getWebSocket(n.id_ws).user,o._websocketManager.getWebSocket(n.id_ws).id_socket,2),o.unsubscribeAll(o._websocketManager.getWebSocket(n.id_ws))):(o._subscriptions.forEach(function(e){for(var t=e.clients.length-1;0<=t;t--)e.clients[t].id_socket===n.id_ws&&e.clients.splice(t,1)}),logged_in_users_collection_1.LoggedInUsers.deleteOne({_id:n._id}),0<=o._loggedInUsers.findIndex(function(e){return e._id===n._id})&&o._loggedInUsers.splice(o._loggedInUsers.findIndex(function(e){return e._id===n._id}),1)))},s=(o=this)._loggedInUsers.length-1;0<=s;s--)n(s);for(s=0;s<this._subscriptions.length;s++)for(r=this._subscriptions[s],a=function(e){var t=r.clients[e];l._loggedInUsers.some(function(e){return e.id_ws===t.id_socket})||r.clients.splice(e,1)},l=this,c=r.clients.length-1;0<=c;c--)a(c);return[2]}})})},3e4),flag_collection_1.Flags.findOne({type:"Enable Debug"}).then(function(e){e&&e.value?i._enableDebug=!0:i._enableDebug=!1}),this.setCacheLimit()}return SubscriptionManager.prototype.setCacheLimit=function(){"true"===process.env.IS_WORKERS_ENABLED?this._heapLimit=.4*this._heapSize:this._heapLimit=.3*this._heapSize},SubscriptionManager.prototype.invalidatePubsCache=function(s,r){return __awaiter(this,void 0,void 0,function(){var t,n,i,o=this;return __generator(this,function(e){switch(e.label){case 0:return(t=s,n=Date.now(),i=this._invalidationPendingTimestamps.get(t)||n,this._invalidationPendingTimestamps.set(t,i),this._invalidationDebounceTimers.has(t)&&clearTimeout(this._invalidationDebounceTimers.get(t)),n-i>=this.MAX_WAIT_TIME)?(this._invalidationPendingTimestamps.delete(t),[4,this._executeInvalidation(s,r)]):[3,2];case 1:return e.sent(),[3,3];case 2:this._invalidationDebounceTimers.set(t,setTimeout(function(){o._invalidationPendingTimestamps.delete(t),o._executeInvalidation(s,r)},this.DEBOUNCE_DELAY)),e.label=3;case 3:return[2]}})})},SubscriptionManager.prototype._executeInvalidation=function(u,_){return __awaiter(this,void 0,void 0,function(){var t,n,o,i,s,r,a,l,c=this;return __generator(this,function(e){this._invalidationDebounceTimers.has(u)&&(clearTimeout(this._invalidationDebounceTimers.get(u)),this._invalidationDebounceTimers.delete(u)),resolveio_server_app_1.ResolveIOServer.getMongoManager().invalidateQueryCache(u),t=this._subscriptions.filter(function(e){return e.collections.includes(u)}),n=function(i){if(o._enableDebug&&console.log(new Date,"Invalidate Sub",i.publication,i.running,i.runAgain),i.running)return i.runAgain=!0,"continue";o._publications[i.publication].user_specific?i.clients.map(function(n){return __awaiter(c,void 0,void 0,function(){var t;return __generator(this,function(e){if((null==(t=this._websocketManager.getWebSocket(n.id_socket))?void 0:t.readyState)===t.OPEN)try{this.sendDataToOneWithRetry(t,n.messageId,i,u,_)}catch(e){}return[2]})})}):o.sendDataToAllWithRetry(i,u,_)},o=this;try{for(i=__values(t),s=i.next();!s.done;s=i.next())r=s.value,n(r)}catch(e){a={error:e}}finally{try{s&&!s.done&&(l=i.return)&&l.call(i)}finally{if(a)throw a.error}}return[2]})})},SubscriptionManager.prototype.delay=function(t){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){return[2,new Promise(function(e){return setTimeout(e,t)})]})})},SubscriptionManager.prototype.sendDataToAllWithRetry=function(t,n,i){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){switch(e.label){case 0:t.running=!0,e.label=1;case 1:return this._enableDebug&&console.log(new Date,"Running sendDataToAll Sub",t.publication),t.runAgain=!1,[4,this.sendDataToAll(t,n,i)];case 2:return(e.sent(),this._enableDebug&&console.log(new Date,"Done sendDataToAll Sub",t.publication,t.runAgain),t.runAgain)?[4,this.delay(500)]:[3,4];case 3:e.sent(),e.label=4;case 4:if(t.runAgain)return[3,1];e.label=5;case 5:return t.running=!1,[2]}})})},SubscriptionManager.prototype.sendDataToOneWithRetry=function(t,n,i,o,s){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(e){switch(e.label){case 0:i.running=!0,e.label=1;case 1:return this._enableDebug&&console.log(new Date,"Running sendDataToOne Sub",i.publication),i.runAgain=!1,[4,this.sendDataToOne(t,n,i,o,s)];case 2:return(e.sent(),this._enableDebug&&console.log(new Date,"Done sendDataToOne Sub",i.publication,i.runAgain),i.runAgain)?[4,this.delay(500)]:[3,4];case 3:e.sent(),e.label=4;case 4:if(i.runAgain)return[3,1];e.label=5;case 5:return i.running=!1,[2]}})})},SubscriptionManager.prototype.publications=function(e){this._publications=Object.assign(this._publications,e)},SubscriptionManager.prototype.loggedInLatency=function(t){var e,n,i,o=this._loggedInUsers.find(function(e){return e.id_ws===t.id_socket});o&&(e=new Date,n=this.latencyBuffer.get(t.id_socket),i=t.latency,!n||e.getTime()-n.lastUpdate.getTime()>=this.LATENCY_UPDATE_THRESHOLD_MS||100<Math.abs(i-n.latency))&&(o.date=e,this.latencyBuffer.set(t.id_socket,{latency:i,lastUpdate:e}))},SubscriptionManager.prototype.flushThrottledLatencyUpdates=function(){return __awaiter(this,void 0,void 0,function(){var t,n;return __generator(this,function(e){switch(e.label){case 0:if(0===this.latencyBuffer.size)return[2];t=Array.from(this.latencyBuffer.entries()).map(function(e){var e=__read(e,2),t=e[0],e=e[1];return{updateOne:{filter:{id_ws:t},update:{$set:{latency:e.latency,date:e.lastUpdate}}}}}),e.label=1;case 1:return e.trys.push([1,3,,4]),[4,logged_in_users_collection_1.LoggedInUsers.bulkWrite(t)];case 2:return e.sent(),this.latencyBuffer.clear(),this.getEnableDebug()&&console.log(new Date,"Sub Manager","Throttled latency batch update successful",t.length),[3,4];case 3:return n=e.sent(),console.error(new Date,"Sub Manager","Throttled latency batch update failed",n),[3,4];case 4:return[2]}})})},SubscriptionManager.prototype.subscribe=function(t,e,n,i,o,s){var r=this,a=(this._debugSubHits+=1,this._debugSubCollections.some(function(e){return e.publication===o})?this._debugSubCollections.find(function(e){return e.publication===o}).hits+=1:this._debugSubCollections.push({publication:o,hits:1}),this._publications[o]);if(a){if(1<s.length||s[0]){if(!a.check)return void console.error(new Date,"No Check Function For Pub "+o);if(!a.check._schema)return void console.error(new Date,"No Check Schema For Pub "+o);for(var l={},c=Object.keys(a.check._schema).filter(function(e){return!e.includes(".")}),u=0;u<s.length;u++)l[c[u]]=s[u];try{a.check.validate(l)}catch(e){if(e)return void console.error(new Date,"Error in Pub Check ("+o+")",e)}}"Bypass"!==t&&(a=t.split("/"),_="",g=a[0],""===a[0]&&(_="/",g=a[1]),_+=g,1<a.length&&(_+="/"),(g=this._subscriptions.filter(function(e){return e.clients.some(function(e){return e.id_socket===n.id_socket&&"Bypass"!==e.messageRoute&&"/"!==e.messageRoute&&e.messageRoute!==t&&!e.messageRoute.startsWith(_)})})).length)&&g.forEach(function(t){t.clients.filter(function(e){return e.id_socket===n.id_socket}).forEach(function(e){r.unsubscribe(e.messageRoute,new Date,n,e.messageId,t.publication,t.subscriptionData)})});var _,g,a=this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)});a?a.clients.some(function(e){return e.id_socket===n.id_socket&&e.messageId===i})||a.clients.push({id_user:n.id_user,messageId:i,id_socket:n.id_socket,messageRoute:t}):this._subscriptions.push({publication:o,subscriptionData:s,collections:this.getPublicationCollections(o),clients:[{id_user:n.id_user,messageId:i,id_socket:n.id_socket,messageRoute:t}],cacheId:0,running:!1,runAgain:!1}),a=a||this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)}),this._enableDebug&&console.log(new Date,"New Sub",a.publication,a.running,a.runAgain,a.clients.length),this.processSubscription(a,n,i)}else console.error(new Date,"No Publication: "+o)},SubscriptionManager.prototype.createLoggedInUser=function(i){return __awaiter(this,void 0,void 0,function(){var t=this;return __generator(this,function(e){return[2,new Promise(function(n,e){return __awaiter(t,void 0,void 0,function(){var t;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i))?(t={_id:(0,common_1.objectIdHexString)(),__v:0,date:new Date,id_user:t.id_user,user:t.user,id_ws:t.id_socket},this._loggedInUsers.push(t),logged_in_users_collection_1.LoggedInUsers.insertOne(t),n(t)):n(null),[2]})})})]})})},SubscriptionManager.prototype.unsubscribe=function(e,t,n,i,o,s){if(this._debugUnSubHits+=1,this._publications[o]){var r=this._subscriptions.find(function(e){return e.publication===o&&JSON.stringify(e.subscriptionData)===JSON.stringify(s)});if(r){for(var a=r.clients.length-1;0<=a;a--)r.clients[a].id_user===n.id_user&&r.clients[a].messageId===i&&r.clients[a].id_socket===n.id_socket&&r.clients.splice(a,1);this._enableDebug&&console.log(new Date,"Unsub",r.publication,r.running,r.runAgain,r.clients.length)}}else console.log("No Publication: "+o)},SubscriptionManager.prototype.unsubscribeAll=function(s){return __awaiter(this,void 0,void 0,function(){var t,n,i,o;return __generator(this,function(e){if(this._debugUnSubAllHits+=1,s){if(s.isUnsubscribed)return[2];for(s.isUnsubscribed=!0,0<=this._loggedInUsers.map(function(e){return e.id_ws}).indexOf(s.id_socket)&&this._loggedInUsers.splice(this._loggedInUsers.map(function(e){return e.id_ws}).indexOf(s.id_socket),1),logged_in_users_collection_1.LoggedInUsers.deleteOne({id_ws:s.id_socket}),t=this._subscriptions.filter(function(e){return e.clients.some(function(e){return e.id_user===s.id_user&&e.id_socket===s.id_socket})}),n=t.length-1;0<=n;n--)for(i=t[n],o=i.clients.length-1;0<=o;o--)i.clients[o].id_socket===s.id_socket&&i.clients.splice(o,1);this._websocketManager.removeWebSocket(s)}return[2]})})},SubscriptionManager.prototype.getActiveSubscriptions=function(){return this._subscriptions},SubscriptionManager.prototype.getPublicationCollections=function(e){return this._publications[e].collections},SubscriptionManager.prototype.tailOpLog=function(o){return __awaiter(this,void 0,void 0,function(){var t,n,i=this;return __generator(this,function(e){switch(e.label){case 0:return this._oplog$&&!this._oplog$.closed&&(this._oplog$.removeAllListeners(),this._oplog$.close(),this._oplog$=null),[4,new Promise(function(e){return setTimeout(e,1e3)})];case 1:if(e.sent(),!this._oplog$||this._oplog$.closed){if(this._oplogRetryCount+=1,5<this._oplogRetryCount&&(console.error("****************** TAIL OPLOG ERROR, RETRYING A BUNCH OF TIMES, KILLING PROCESS **************************"),process.exit(1)),t=[{$match:{$and:[{"ns.coll":{$nin:["log-method-latencies","log-subscriptions","logs","counters","cron-job-histories","email-histories","qb-soap-request-histories","qb-soap-request-responses","qb-soap-requests","qb-soap-retries"]}},{"ns.coll":{$not:/.*\.versions$/}},{"ns.coll":{$not:/^monitor-/}}]}}],o){n=o;try{this._oplog$=resolveio_server_app_1.ResolveIOServer.getMainDB().watch(t,{resumeAfter:o})}catch(e){return this._oplog$&&(this._oplog$.removeAllListeners(),this._oplog$.close(),this._oplog$=null),this.tailOpLog(o),[2]}}else this._oplog$=resolveio_server_app_1.ResolveIOServer.getMainDB().watch(t);console.log(new Date,"oplog started"),this._oplog$.on("change",function(t){var e;t.ns&&(i._enableDebug&&console.log(new Date,"Oplog Hit",t.ns),e=t.ns.coll,i._debugOplogCollections.some(function(e){return e.collection===t.ns.coll&&e.type===t.operationType})?i._debugOplogCollections.find(function(e){return e.collection===t.ns.coll&&e.type===t.operationType}).hits+=1:i._debugOplogCollections.push({collection:t.ns.coll,type:t.operationType,hits:1}),e&&(i._debugOplogHits+=1,"insert"===t.operationType?("support-tickets"===e&&"https://resolveio.com"===i.serverConfig.ROOT_URL&&(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"sendSupportTicketEmail",t.documentKey._id),i.invalidatePubsCache(e,"insert")),"method-responses"!==e&&i.invalidatePubsCache(e,"insert")):"update"===t.operationType||"replace"===t.operationType?"method-responses"!==e&&i.invalidatePubsCache(e,"update"):"delete"===t.operationType&&"method-responses"!==e&&i.invalidatePubsCache(e,"delete")),"flags"===e&&flag_collection_1.Flags.findOne({type:"Enable Debug"}).then(function(e){e&&e.value?i._enableDebug=!0:i._enableDebug=!1}),n=t._id,process.env.NODE_APP_INSTANCE&&"0"!==process.env.NODE_APP_INSTANCE||"false"!==process.env.IS_WORKERS_ENABLED&&"true"===process.env.IS_WORKER_INSTANCE&&process.env.WORKER_INDEX)}),this._oplog$.on("error",function(e){console.log(new Date,"oplog error",e),i._oplog$.removeAllListeners(),i._oplog$.close(),i._oplog$=null,i.tailOpLog(n)}),this._oplog$.on("end",function(){console.log(new Date,"oplog end"),i._oplog$.removeAllListeners(),i._oplog$.close(),i._oplog$=null,i.tailOpLog(n)}),this._oplog$.on("close",function(){console.log(new Date,"oplog close"),i._oplog$.removeAllListeners(),i._oplog$=null,i.tailOpLog(n)})}return[2]}})})},SubscriptionManager.prototype.processSubscription=function(i,o,s){return __awaiter(this,void 0,void 0,function(){var t,n;return __generator(this,function(e){if(this._publications[i.publication].user_specific){if(this._enableDebug&&console.log(new Date,"Process Sub Specific, Non - Cache",i.publication,i.running),i.running)return[2];this.sendDataToOneWithRetry(o,s,i,"","newSub")}else if(i.cacheId)try{t=JSON.parse(this._nodeCache.get(i.cacheId),common_1.dateReviver),n={messageId:s,hasError:!1,data:t},this._enableDebug&&console.log(new Date,"Process Sub, Cache",i.publication),this.sendWS(o,n)}catch(e){this._nodeCache.del(i.cacheId),i.cacheId=0,this.sendDataToAllWithRetry(i,"","newSub")}else{if(this._enableDebug&&console.log(new Date,"Process Sub, Non - Cache",i.publication,i.running),i.running)return[2];this.sendDataToAllWithRetry(i,"","newSub")}return[2]})})},SubscriptionManager.prototype.sendDataToOne=function(s,r,a,l,c){return __awaiter(this,void 0,void 0,function(){var t,n,i,o;return __generator(this,function(e){switch(e.label){case 0:t=this._monitorManagerFunction.startMonitorFunction("User Specific Publication",a.publication,"","",a.subscriptionData),e.label=1;case 1:return e.trys.push([1,3,,4]),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"insertSubscriptionLog",c,a.publication,l,JSON.stringify(a.subscriptionData)),[4,(o=this._publications[a.publication].function).call.apply(o,__spreadArray([Object.assign({},this,SubscriptionManager.prototype),s.id_user],__read(a.subscriptionData),!1))];case 2:return o=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),i={messageId:r,hasError:!1,data:o},this.sendWS(s,i),[3,4];case 3:return n=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),i={messageId:r,hasError:!0,data:n},this.sendWS(s,i),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail("dev@resolveio.com","SERVER - Error Detected - "+this.serverConfig.CLIENT_NAME,"Error Detected During Subscription "+a.publication+" - (sendDataToOne - WS)\n\nData \n"+JSON.stringify(a.subscriptionData,null,2)+"\n\nErrors\n"+JSON.stringify(n,null,2)),[3,4];case 4:return[2]}})})},SubscriptionManager.prototype.sendDataToAll=function(_,g,d){return __awaiter(this,void 0,void 0,function(){var t,o,n,i,s,r,a,l,c,u=this;return __generator(this,function(e){switch(e.label){case 0:return _.clients.length?[3,1]:(_.cacheId&&(this._nodeCache.del(_.cacheId),_.cacheId=0),0<=(c=this._subscriptions.findIndex(function(e){return e.publication===_.publication&&JSON.stringify(e.subscriptionData)===JSON.stringify(_.subscriptionData)}))&&this._subscriptions.splice(c,1),[2]);case 1:t=this._monitorManagerFunction.startMonitorFunction("Publication",_.publication,"","",_.subscriptionData),e.label=2;case 2:return e.trys.push([2,4,,5]),"superadminAPM"!==_.publication&&"loggedInUsers"!==_.publication&&resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(),"insertSubscriptionLog",d,_.publication,g,JSON.stringify(_.subscriptionData)),[4,(c=this._publications[_.publication].function).call.apply(c,__spreadArray([Object.assign({},this,SubscriptionManager.prototype)],__read(_.subscriptionData),!1))];case 3:if(o=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),_.cacheId)try{n=JSON.parse(this._nodeCache.get(_.cacheId),common_1.dateReviver),JSON.stringify(n)!==JSON.stringify(o)&&(Promise.all(_.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),this._nodeCache.del(_.cacheId),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!_.collections.includes("logs")&&!_.collections.find(function(e){return e.endsWith(".versions")})&&!_.collections.find(function(e){return e.startsWith("monitor-")})?this._nodeCache.set(_.cacheId,JSON.stringify(o)):_.cacheId=0)}catch(e){Promise.all(_.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),this._nodeCache.del(_.cacheId),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!_.collections.includes("logs")&&!_.collections.find(function(e){return e.endsWith(".versions")})&&!_.collections.find(function(e){return e.startsWith("monitor-")})?this._nodeCache.set(_.cacheId,JSON.stringify(o)):_.cacheId=0}else if(Promise.all(_.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!1,data:o},this.sendWS(t,n)),[2]})})})),(0,common_1.getBinarySize)(JSON.stringify(o))<1e6&&!_.collections.includes("logs")&&!_.collections.find(function(e){return e.endsWith(".versions")})&&!_.collections.find(function(e){return e.startsWith("monitor-")})){if(_.cacheId=this._cacheId++,this._nodeCache.set(_.cacheId,JSON.stringify(o)),(i=this._nodeCache.getStats().vsize)>this._heapLimit){for(s=0,r=this._subscriptions.filter(function(e){return e.cacheId&&!e.clients.length}),a=0;a<r.length&&(this._debugRemoveCacheHits+=1,this._nodeCache.del(r[a].cacheId),r[a].cacheId=0,s+=1,!(this._nodeCache.getStats().vsize<.75*this._heapLimit));a++);this._enableDebug&&console.log("Sub Cache: Too Big - "+_.publication+" - Deleted: "+s+" - "+i)}}else _.cacheId=0;return[3,5];case 4:return l=e.sent(),this._monitorManagerFunction.finishMonitorFunction(t),Promise.all(_.clients.map(function(i){return __awaiter(u,void 0,void 0,function(){var t,n;return __generator(this,function(e){return(t=this._websocketManager.getWebSocket(i.id_socket))&&t.readyState===t.OPEN&&(n={messageId:i.messageId,hasError:!0,data:l},this.sendWS(t,n)),[2]})})})),resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail("dev@resolveio.com","SERVER - Error Detected - "+this.serverConfig.CLIENT_NAME,"Error Detected During Subscription "+_.publication+" - (sendPubData)\n\nData \n"+JSON.stringify(_.subscriptionData,null,2)+"\n\nErrors\n"+JSON.stringify(l,null,2)),[3,5];case 5:return[2]}})})},SubscriptionManager.prototype.sendWS=function(e,t){this._websocketManager.send(e,t)},SubscriptionManager.prototype.getEnableDebug=function(){return this._enableDebug},SubscriptionManager}();exports.SubscriptionManager=SubscriptionManager;
2
2
  //# sourceMappingURL=subscription.manager.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/managers/subscription.manager.ts"],"names":["logs_1","require","app_status_1","files_1","super_admin_1","logged_in_users_collection_1","cron_jobs_1","flags_1","method_responses_1","resolveio_server_app_1","notifications_1","report_builder_reports_1","report_builder_libraries_1","user_groups_1","user_guides_1","report_builder_dashboard_builders_1","common_1","NodeCache","flag_collection_1","os_1","flags_update_1","numCPUs","cpus","length","v8","SubscriptionManager","wss","serverConfig","monitorManagerFunction","_this","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","_invalidationPendingFlags","DEBOUNCE_DELAY","MAX_WAIT_TIME","_websocketManager","ResolveIOServer","getMainServer","getWebSocketManager","_monitorManagerFunction","_nodeCache","stdTTL","checkperiod","setInterval","flushThrottledLatencyUpdates","_wss","loadSuperAdminPublications","loadAppStatusPublications","loadLogPublications","loadFilePublications","loadCronJobPublications","loadFlagsUpdatePublications","loadFlagsPublications","loadMethodResponsePublications","loadNotificationPublications","loadReportBuilderReportPublications","loadReportBuilderLibraryPublications","loadUserGroupPublications","loadUserGuidePublications","loadReportBuilderDashboardBuilderPublications","tailOpLog","getEnableDebug","console","log","Date","JSON","stringify","sort","a","b","collection","localeCompare","publication","type","__awaiter","_a","LoggedInUsers","find","_b","sent","userCopy","deepCopy","i","loggedInUser","date","now","getTime","this_1","getWebSocket","id_ws","unsubscribeAll","forEach","sub","j","clients","id_socket","splice","deleteOne","_id","findIndex","client","this_2","some","Flags","findOne","then","flag","value","setCacheLimit","prototype","process","env","IS_WORKERS_ENABLED","_heapLimit","invalidatePubsCache","debounceKey","has","get","clearTimeout","_executeInvalidation","set","setTimeout","delete","getMongoManager","invalidateQueryCache","collSubs","filter","collections","includes","this_3","running","runAgain","user_specific","Promise","all","map","ws","readyState","OPEN","sendDataToOneWithRetry","messageId","getMethodManager","sendEmail","id_user","err_1","sendDataToAllWithRetry","_c","collSubs_1","__values","collSubs_1_1","next","delay","ms","resolve","sendDataToAll","sendDataToOne","publications","method","Object","assign","loggedInLatency","existingEntry","newLatency","lastUpdate","Math","abs","latency","size","updates","Array","from","entries","__read","updateOne","update","$set","bulkWrite","clear","error","error_1","subscribe","messageRoute","messageDate","subscriptionData","pub","hits","push","check","_schema","valObj","rootKeys","keys","validate","errors","urlData","split","urlModule_1","urlNext","otherRouteSubs","startsWith","otherSub","unsubscribe","getPublicationCollections","cacheId","processSubscription","createLoggedInUser","reject","user","objectIdHexString","__v","insertOne","indexOf","userSubs","removeWebSocket","getActiveSubscriptions","resumeToken","_oplog$","closed","removeAllListeners","close","exit","pipeline","$match","$and","ns.coll","$nin","$not","lastResumeToken_1","getMainDB","watch","resumeAfter","errOp","on","doc","ns","coll","operationType","callMethod","call","documentKey","NODE_APP_INSTANCE","IS_WORKER_INSTANCE","WORKER_INDEX","cacheData","parse","dateReviver","serverRes","hasError","data","sendWS","err","del","monitor","startMonitorFunction","function","apply","__spreadArray","res","finishMonitorFunction","err_2","subIndex","res_1","getBinarySize","endsWith","nodeCacheSize","getStats","vsize","deleteCount","subArr","zz","err_3","send","exports"],"mappings":"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","file":"subscription.manager.js","sourcesContent":["import { ServerResponseModel } from '../models/server-response.model';\nimport { ActiveSubscriptionModel, SubscriptionModel } from '../models/subscription.model';\nimport * as WebSocket from 'ws';\nimport { loadLogPublications } from '../publications/logs';\nimport { loadAppStatusPublications } from '../publications/app-status';\nimport { loadFilePublications } from '../publications/files';\nimport { loadSuperAdminPublications } from '../publications/super-admin';\nimport { LoggedInUsers } from '../collections/logged-in-users.collection';\nimport { loadCronJobPublications } from '../publications/cron-jobs';\nimport { loadFlagsPublications } from '../publications/flags';\nimport { loadMethodResponsePublications } from '../publications/method-responses';\nimport { ResolveIOServer } from '../resolveio-server-app';\nimport { loadNotificationPublications } from '../publications/notifications';\nimport { loadReportBuilderReportPublications } from '../publications/report-builder-reports';\nimport { LoggedInUserModel } from '../models/logged-in-users.model';\n\nimport { ChangeStream, ChangeStreamDeleteDocument, ChangeStreamInsertDocument, ChangeStreamReplaceDocument, ChangeStreamUpdateDocument, ResumeToken } from 'mongodb';\nimport { loadReportBuilderLibraryPublications } from '../publications/report-builder-libraries';\nimport { loadUserGroupPublications } from '../publications/user-groups';\nimport { loadUserGuidePublications } from '../publications/user-guides';\nimport { loadReportBuilderDashboardBuilderPublications } from '../publications/report-builder-dashboard-builders';\nimport { dateReviver, deepCopy, getBinarySize, objectIdHexString } from '../util/common';\nimport * as NodeCache from 'node-cache';\nimport { MonitorManagerFunction } from './monitor.manager';\nimport { Flags } from '../collections/flag.collection';\nimport { cpus } from 'os';\nimport { WebSocketManager } from './websocket.manager';\nimport { loadFlagsUpdatePublications } from '../publications/flags-update';\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 _invalidationPendingFlags = new Map<string, number>(); // Tracks first invalidation time\n\tprivate readonly DEBOUNCE_DELAY = 100; // 100ms debounce delay\n\tprivate readonly MAX_WAIT_TIME = 500; // 500ms maximum wait time\n\n\n\tconstructor(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\tloadMethodResponsePublications(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\tthis.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\tthis.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\tLoggedInUsers.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\tFlags.findOne({type: 'Enable Debug'}).then(flag => {\n\t\t\tif (flag && flag.value) {\n\t\t\t\tthis._enableDebug = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._enableDebug = false;\n\t\t\t}\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\t// Now we only use collection as the debounce key\n\t\tconst debounceKey = collection;\n\t\tconst now = Date.now();\n\t\t\n\t\t// If we have a pending invalidation that's been waiting too long\n\t\tif (this._invalidationPendingFlags.has(debounceKey) && \n\t\t\tnow - this._invalidationPendingFlags.get(debounceKey) > this.MAX_WAIT_TIME) {\n\t\t\t// Force immediate execution\n\t\t\tif (this._invalidationDebounceTimers.has(debounceKey)) {\n\t\t\t\tclearTimeout(this._invalidationDebounceTimers.get(debounceKey));\n\t\t\t}\n\t\t\tthis._executeInvalidation(collection, type);\n\t\t\treturn;\n\t\t}\n\n\t\t// Mark first invalidation time (only if not already set)\n\t\tif (!this._invalidationPendingFlags.has(debounceKey)) {\n\t\t\tthis._invalidationPendingFlags.set(debounceKey, now);\n\t\t}\n\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\n\t\t// Set new timer\n\t\tthis._invalidationDebounceTimers.set(debounceKey, setTimeout(() => {\n\t\t\tthis._executeInvalidation(collection, type);\n\t\t\tthis._invalidationPendingFlags.delete(debounceKey); // Clean up\n\t\t}, this.DEBOUNCE_DELAY));\n\t}\n\n\tprivate async _executeInvalidation(collection: string, type: string) {\n\t\t// Clean up timer (already cleared by setTimeout, but just to be safe)\n\t\tthis._invalidationDebounceTimers.delete(collection);\n\t\t\n\t\t// Original invalidation logic\n\t\tResolveIOServer.getMongoManager().invalidateQueryCache(collection);\n\n\t\tlet collSubs = this._subscriptions.filter(a => a.collections.includes(collection));\n\n\t\tfor (let 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\n\t\t\tif (sub.running) {\n\t\t\t\tsub.runAgain = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (this._publications[sub.publication].user_specific) {\n\t\t\t\tPromise.all(\n\t\t\t\t\tsub.clients.map(async client => {\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\ttry {\n\t\t\t\t\t\t\t\tawait this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (err) {\n\t\t\t\t\t\t\t\tResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During sendDataToOne - User Specific - Socket: ' + client.id_socket + ', User: ' + client.id_user + ', MessageId: ' + client.messageId + ', Pub: ' + sub.publication + ', Err: ' + JSON.stringify(err, null, 2));\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);\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\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 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\tthis.processSubscription(sub, ws, messageId);\n\t\t}\n\t}\n\n\tpublic async createLoggedInUser(id_ws: string): Promise<LoggedInUserModel> {\n\t\treturn new Promise(async (resolve, reject) => {\n\t\t\tlet ws = this._websocketManager.getWebSocket(id_ws);\n\n\t\t\tif (ws) {\n\t\t\t\tlet user = {\n\t\t\t\t\t_id: objectIdHexString(),\n\t\t\t\t\t__v: 0,\n\t\t\t\t\tdate: new Date(),\n\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\tuser: ws['user'],\n\t\t\t\t\tid_ws: ws['id_socket']\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tthis._loggedInUsers.push(user);\n\t\t\t\tLoggedInUsers.insertOne(user);\n\t\t\t\t\n\t\t\t\tresolve(user);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresolve(null);\n\t\t\t}\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\tLoggedInUsers.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\tthis._oplog$.close();\n\t\t\tthis._oplog$ = null;\n\t\t}\n\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 (errOp) {\n\t\t\t\t\tif (this._oplog$) {\n\t\t\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\t\t\tthis._oplog$.close();\n\t\t\t\t\t\tthis._oplog$ = null;\n\t\t\t\t\t}\n\t\t\t\t\tthis.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', (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\tthis.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\tthis.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\tthis.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\tthis.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\tFlags.findOne({ type: 'Enable Debug' }).then(flag => {\n\t\t\t\t\t\t\tif (flag && flag.value) {\n\t\t\t\t\t\t\t\tthis._enableDebug = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis._enableDebug = false;\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\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', error => {\n\t\t\t\tconsole.log(new Date(), 'oplog error', error);\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$.close();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tthis.tailOpLog(lastResumeToken);\n\t\t\t});\n\n\t\t\tthis._oplog$.on('end', () => {\n\t\t\t\tconsole.log(new Date(), 'oplog end');\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$.close();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tthis.tailOpLog(lastResumeToken);\n\t\t\t});\n\n\t\t\tthis._oplog$.on('close', () => {\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\tthis.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 (err) {\n\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\t\tsub.cacheId = 0;\n\n\t\t\t\t\tthis.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\tthis.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\tthis.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\t\t\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\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\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\n\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\n\t\t\tthis.sendWS(ws, serverRes);\n\n\t\t\tResolveIOServer.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}\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\t\t\t\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\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\tPromise.all(\n\t\t\t\t\t\t\t\tsub.clients.map(async client => {\n\t\t\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\n\t\t\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t\t\t}\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 (err) {\n\t\t\t\t\t\tPromise.all(\n\t\t\t\t\t\t\tsub.clients.map(async client => {\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\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\tPromise.all(\n\t\t\t\t\t\tsub.clients.map(async 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\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\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\n\n\t\t\t\tPromise.all(\n\t\t\t\t\tsub.clients.map(async client => {\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: true,\n\t\t\t\t\t\t\t\tdata: err\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);\n\n\t\t\t\tResolveIOServer.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}\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":["logs_1","require","app_status_1","files_1","super_admin_1","logged_in_users_collection_1","cron_jobs_1","flags_1","method_responses_1","resolveio_server_app_1","notifications_1","report_builder_reports_1","report_builder_libraries_1","user_groups_1","user_guides_1","report_builder_dashboard_builders_1","common_1","NodeCache","flag_collection_1","os_1","flags_update_1","numCPUs","cpus","length","v8","SubscriptionManager","wss","serverConfig","monitorManagerFunction","_this","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","_websocketManager","ResolveIOServer","getMainServer","getWebSocketManager","_monitorManagerFunction","_nodeCache","stdTTL","checkperiod","setInterval","flushThrottledLatencyUpdates","_wss","loadSuperAdminPublications","loadAppStatusPublications","loadLogPublications","loadFilePublications","loadCronJobPublications","loadFlagsUpdatePublications","loadFlagsPublications","loadMethodResponsePublications","loadNotificationPublications","loadReportBuilderReportPublications","loadReportBuilderLibraryPublications","loadUserGroupPublications","loadUserGuidePublications","loadReportBuilderDashboardBuilderPublications","tailOpLog","getEnableDebug","console","log","Date","JSON","stringify","sort","a","b","collection","localeCompare","publication","type","__awaiter","_a","LoggedInUsers","find","_b","sent","userCopy","deepCopy","i","loggedInUser","date","now","getTime","this_1","getWebSocket","id_ws","unsubscribeAll","forEach","sub","j","clients","id_socket","splice","deleteOne","_id","findIndex","client","this_2","some","Flags","findOne","then","flag","value","setCacheLimit","prototype","process","env","IS_WORKERS_ENABLED","_heapLimit","invalidatePubsCache","debounceKey","firstInvalidationTime","get","set","has","clearTimeout","delete","_executeInvalidation","setTimeout","getMongoManager","invalidateQueryCache","collSubs","filter","collections","includes","this_3","running","runAgain","user_specific","map","ws","readyState","OPEN","sendDataToOneWithRetry","messageId","err","sendDataToAllWithRetry","collSubs_1","__values","collSubs_1_1","next","done","delay","ms","Promise","resolve","sendDataToAll","sendDataToOne","publications","method","Object","assign","loggedInLatency","existingEntry","newLatency","lastUpdate","Math","abs","latency","size","updates","Array","from","entries","__read","_c","updateOne","update","$set","bulkWrite","clear","error","error_1","subscribe","messageRoute","messageDate","subscriptionData","pub","hits","push","check","_schema","valObj","rootKeys","keys","validate","errors","urlData","split","urlModule_1","urlNext","otherRouteSubs","startsWith","otherSub","unsubscribe","id_user","getPublicationCollections","cacheId","processSubscription","createLoggedInUser","reject","user","objectIdHexString","__v","insertOne","indexOf","userSubs","removeWebSocket","getActiveSubscriptions","resumeToken","_oplog$","closed","removeAllListeners","close","exit","pipeline","$match","$and","ns.coll","$nin","$not","lastResumeToken_1","getMainDB","watch","resumeAfter","errOp","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","finishMonitorFunction","err_1","sendEmail","subIndex","res_1","all","getBinarySize","endsWith","nodeCacheSize","getStats","vsize","deleteCount","subArr","zz","err_2","send","exports"],"mappings":"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","file":"subscription.manager.js","sourcesContent":["import { ServerResponseModel } from '../models/server-response.model';\nimport { ActiveSubscriptionModel, SubscriptionModel } from '../models/subscription.model';\nimport * as WebSocket from 'ws';\nimport { loadLogPublications } from '../publications/logs';\nimport { loadAppStatusPublications } from '../publications/app-status';\nimport { loadFilePublications } from '../publications/files';\nimport { loadSuperAdminPublications } from '../publications/super-admin';\nimport { LoggedInUsers } from '../collections/logged-in-users.collection';\nimport { loadCronJobPublications } from '../publications/cron-jobs';\nimport { loadFlagsPublications } from '../publications/flags';\nimport { loadMethodResponsePublications } from '../publications/method-responses';\nimport { ResolveIOServer } from '../resolveio-server-app';\nimport { loadNotificationPublications } from '../publications/notifications';\nimport { loadReportBuilderReportPublications } from '../publications/report-builder-reports';\nimport { LoggedInUserModel } from '../models/logged-in-users.model';\n\nimport { ChangeStream, ChangeStreamDeleteDocument, ChangeStreamInsertDocument, ChangeStreamReplaceDocument, ChangeStreamUpdateDocument, ResumeToken } from 'mongodb';\nimport { loadReportBuilderLibraryPublications } from '../publications/report-builder-libraries';\nimport { loadUserGroupPublications } from '../publications/user-groups';\nimport { loadUserGuidePublications } from '../publications/user-guides';\nimport { loadReportBuilderDashboardBuilderPublications } from '../publications/report-builder-dashboard-builders';\nimport { dateReviver, deepCopy, getBinarySize, objectIdHexString } from '../util/common';\nimport * as NodeCache from 'node-cache';\nimport { MonitorManagerFunction } from './monitor.manager';\nimport { Flags } from '../collections/flag.collection';\nimport { cpus } from 'os';\nimport { WebSocketManager } from './websocket.manager';\nimport { loadFlagsUpdatePublications } from '../publications/flags-update';\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(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\tloadMethodResponsePublications(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\tthis.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\tthis.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\tLoggedInUsers.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\tFlags.findOne({type: 'Enable Debug'}).then(flag => {\n\t\t\tif (flag && flag.value) {\n\t\t\t\tthis._enableDebug = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._enableDebug = false;\n\t\t\t}\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(() => {\n\t\t\t\t\tthis._invalidationPendingTimestamps.delete(debounceKey);\n\t\t\t\t\tthis._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\tsub.clients.map(async client => {\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\tthis.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (err) {\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\tthis.sendDataToAllWithRetry(sub, collection, type);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async delay(ms: number) {\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 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\tthis.processSubscription(sub, ws, messageId);\n\t\t}\n\t}\n\n\tpublic async createLoggedInUser(id_ws: string): Promise<LoggedInUserModel> {\n\t\treturn new Promise(async (resolve, reject) => {\n\t\t\tlet ws = this._websocketManager.getWebSocket(id_ws);\n\n\t\t\tif (ws) {\n\t\t\t\tlet user = {\n\t\t\t\t\t_id: objectIdHexString(),\n\t\t\t\t\t__v: 0,\n\t\t\t\t\tdate: new Date(),\n\t\t\t\t\tid_user: ws['id_user'],\n\t\t\t\t\tuser: ws['user'],\n\t\t\t\t\tid_ws: ws['id_socket']\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tthis._loggedInUsers.push(user);\n\t\t\t\tLoggedInUsers.insertOne(user);\n\t\t\t\t\n\t\t\t\tresolve(user);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresolve(null);\n\t\t\t}\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\tLoggedInUsers.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\tthis._oplog$.close();\n\t\t\tthis._oplog$ = null;\n\t\t}\n\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 (errOp) {\n\t\t\t\t\tif (this._oplog$) {\n\t\t\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\t\t\tthis._oplog$.close();\n\t\t\t\t\t\tthis._oplog$ = null;\n\t\t\t\t\t}\n\t\t\t\t\tthis.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', (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\tthis.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\tthis.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\tthis.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\tthis.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\tFlags.findOne({ type: 'Enable Debug' }).then(flag => {\n\t\t\t\t\t\t\tif (flag && flag.value) {\n\t\t\t\t\t\t\t\tthis._enableDebug = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis._enableDebug = false;\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\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', error => {\n\t\t\t\tconsole.log(new Date(), 'oplog error', error);\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$.close();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tthis.tailOpLog(lastResumeToken);\n\t\t\t});\n\n\t\t\tthis._oplog$.on('end', () => {\n\t\t\t\tconsole.log(new Date(), 'oplog end');\n\t\t\t\tthis._oplog$.removeAllListeners();\n\t\t\t\tthis._oplog$.close();\n\t\t\t\tthis._oplog$ = null;\n\t\t\t\tthis.tailOpLog(lastResumeToken);\n\t\t\t});\n\n\t\t\tthis._oplog$.on('close', () => {\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\tthis.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 (err) {\n\t\t\t\t\tthis._nodeCache.del(sub.cacheId);\n\t\t\t\t\tsub.cacheId = 0;\n\n\t\t\t\t\tthis.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\tthis.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\tthis.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\t\t\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\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\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\n\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\n\t\t\tthis.sendWS(ws, serverRes);\n\n\t\t\tResolveIOServer.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}\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\t\t\t\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\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\tPromise.all(\n\t\t\t\t\t\t\t\tsub.clients.map(async client => {\n\t\t\t\t\t\t\t\t\tlet ws = this._websocketManager.getWebSocket(client.id_socket);\n\t\t\t\t\t\t\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\t\t\t\t\t\t\tlet serverRes: ServerResponseModel = {\n\t\t\t\t\t\t\t\t\t\t\tmessageId: client.messageId,\n\t\t\t\t\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\t\t\t\t\tdata: res\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\n\t\t\t\t\t\t\t\t\t\tthis.sendWS(ws, serverRes);\n\t\t\t\t\t\t\t\t\t}\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 (err) {\n\t\t\t\t\t\tPromise.all(\n\t\t\t\t\t\t\tsub.clients.map(async client => {\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\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\tPromise.all(\n\t\t\t\t\t\tsub.clients.map(async 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\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\tthis._monitorManagerFunction.finishMonitorFunction(monitor);\n\n\t\t\t\tPromise.all(\n\t\t\t\t\tsub.clients.map(async client => {\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: true,\n\t\t\t\t\t\t\t\tdata: err\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);\n\n\t\t\t\tResolveIOServer.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}\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resolveio/server-lib",
3
- "version": "20.6.22",
3
+ "version": "20.6.23",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "package": "./build_package.sh",