diff --git a/packages/rocketchat-authorization/server/publications/permissions.js b/packages/rocketchat-authorization/server/publications/permissions.js index fa8b41c7183682c0b15ace8f158e06ba11887be1..02499e961bfa8598b46b98cfbe496bdd156c3340 100644 --- a/packages/rocketchat-authorization/server/publications/permissions.js +++ b/packages/rocketchat-authorization/server/publications/permissions.js @@ -8,7 +8,8 @@ Meteor.methods({ return { update: records.filter((record) => { return record._updatedAt > updatedAt; - }) + }), + remove: RocketChat.models.Permissions.trashFindDeletedAfter(updatedAt, {}, {fields: {_id: 1, _deletedAt: 1}}).fetch() }; } diff --git a/packages/rocketchat-lib/client/lib/cachedCollection.js b/packages/rocketchat-lib/client/lib/cachedCollection.js index 347728d69b5fdbcb8f2b84d9be118bcf64663eb4..1973ddb6f37476a6d4e9b56012ec4e65b4e00f64 100644 --- a/packages/rocketchat-lib/client/lib/cachedCollection.js +++ b/packages/rocketchat-lib/client/lib/cachedCollection.js @@ -4,12 +4,26 @@ class CachedCollectionManager { constructor() { this.items = []; this._syncEnabled = false; + this.reconnectCb = []; const _unstoreLoginToken = Accounts._unstoreLoginToken; Accounts._unstoreLoginToken = (...args) => { _unstoreLoginToken.apply(Accounts, args); this.clearAllCache(); }; + + let connectionWasOnline = true; + Tracker.autorun(() => { + const connected = Meteor.connection.status().connected; + + if (connected === true && connectionWasOnline === false) { + for (const cb of this.reconnectCb) { + cb(); + } + } + + connectionWasOnline = connected; + }); } register(cachedCollection) { @@ -36,6 +50,10 @@ class CachedCollectionManager { get syncEnabled() { return this._syncEnabled; } + + onReconnect(cb) { + this.reconnectCb.push(cb); + } } RocketChat.CachedCollectionManager = new CachedCollectionManager; @@ -49,7 +67,7 @@ class CachedCollection { syncMethodName, eventName, eventType = 'onUser', - useSync = false, + useSync = true, useCache = false, debug = true, version = 1, @@ -70,6 +88,10 @@ class CachedCollection { this.updatedAt = new Date(0); this.maxCacheTime = maxCacheTime; + if (this.useCache === false) { + return this.clearCache(); + } + RocketChat.CachedCollectionManager.register(this); } @@ -166,28 +188,48 @@ class CachedCollection { this.log(`syncing from ${this.updatedAt}`); Meteor.call(this.syncMethodName, this.updatedAt, (error, data) => { + let changes = []; + if (data.update && data.update.length > 0) { this.log(`${data.update.length} records updated in sync`); - - for (const record of data.update) { - delete record.$loki; - this.collection.upsert({ _id: record._id }, _.omit(record, '_id')); - - if (record._updatedAt && record._updatedAt > this.updatedAt) { - this.updatedAt = record._updatedAt; - } - } + changes.push(...data.update); } if (data.remove && data.remove.length > 0) { this.log(`${data.remove.length} records removed in sync`); + changes.push(...data.remove); + } + + changes = changes.sort((a, b) => { + const valueA = a._updatedAt || a._deletedAt; + const valueB = b._updatedAt || b._deletedAt; - for (const record of data.remove) { + if (valueA < valueB) { + return -1; + } + + if (valueA > valueB) { + return 1; + } + + return 0; + }); + + for (const record of changes) { + delete record.$loki; + + if (record._deletedAt) { this.collection.remove({ _id: record._id }); if (record._deletedAt && record._deletedAt > this.updatedAt) { this.updatedAt = record._deletedAt; } + } else { + this.collection.upsert({ _id: record._id }, _.omit(record, '_id')); + + if (record._updatedAt && record._updatedAt > this.updatedAt) { + this.updatedAt = record._updatedAt; + } } } @@ -198,6 +240,10 @@ class CachedCollection { } saveCache(data) { + if (this.useCache === false) { + return; + } + this.log('saving cache'); if (!data) { data = this.collection.find().fetch(); @@ -256,15 +302,8 @@ class CachedCollection { } if (this.useSync === true) { - let connectionWasOnline = true; - Tracker.autorun(() => { - const connected = Meteor.connection.status().connected; - - if (connected === true && connectionWasOnline === false) { - this.trySync(); - } - - connectionWasOnline = connected; + RocketChat.CachedCollectionManager.onReconnect(() => { + this.trySync(); }); } diff --git a/packages/rocketchat-lib/server/publications/settings.coffee b/packages/rocketchat-lib/server/publications/settings.coffee index 8b5c90c489cca8dca8e97f3578b768c5f6ddd03f..6e5fe56c46c6cbf9d9f50c488cfda1268a4e6cb8 100644 --- a/packages/rocketchat-lib/server/publications/settings.coffee +++ b/packages/rocketchat-lib/server/publications/settings.coffee @@ -31,6 +31,7 @@ Meteor.methods return { update: records.filter (record) -> return record._updatedAt > updatedAt + remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {hidden: { $ne: true }}, {fields: {_id: 1, _deletedAt: 1}}).fetch() } return records diff --git a/server/publications/room.js b/server/publications/room.js index 6a5965c4176f2e98b1de5353987fbeca07100492..7822a9d336afc68127d32a01249fd8fb3c05e02b 100644 --- a/server/publications/room.js +++ b/server/publications/room.js @@ -38,8 +38,9 @@ Meteor.methods({ return { update: data .filter(record => { return record._room && record._room._updatedAt > updatedAt; }) - .map(roomMap) - }; + .map(roomMap), + remove: RocketChat.models.Subscriptions.trashFindDeletedAfter(updatedAt, {'u._id': Meteor.userId()}, {fields: {_id: 1, _deletedAt: 1}}).fetch() + }; } return data.map(roomMap); diff --git a/server/publications/subscription.coffee b/server/publications/subscription.coffee index 41750dbedfca45107d5832c60cf77f7c6166aab8..79d0e75e12bfd531ebed9fcb4a18a5a808ab5f4b 100644 --- a/server/publications/subscription.coffee +++ b/server/publications/subscription.coffee @@ -35,6 +35,7 @@ Meteor.methods return { update: records.filter (record) -> return record._updatedAt > updatedAt + remove: RocketChat.models.Subscriptions.trashFindDeletedAfter(updatedAt, {'u._id': Meteor.userId()}, {fields: {_id: 1, _deletedAt: 1}}).fetch() } return records