UNPKG

14.6 kBJavaScriptView Raw
1'use strict';
2
3var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
4
5var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
6
7var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
8
9var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
10
11var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12
13var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14
15var _createClass2 = require('babel-runtime/helpers/createClass');
16
17var _createClass3 = _interopRequireDefault(_createClass2);
18
19function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
21var Promise = require('bluebird');
22var _ = require('lodash');
23
24/**
25 * Service infrastructure failures recovery.
26 *
27 * @mixin
28 * @memberof chat-service
29 * @see chat-service.ChatService.event:storeConsistencyFailure
30 */
31
32var RecoveryAPI = function () {
33 function RecoveryAPI(state, transport, execUserCommand, instanceUID) {
34 (0, _classCallCheck3.default)(this, RecoveryAPI);
35
36 this.state = state;
37 this.transport = transport;
38 this.instanceUID = instanceUID;
39 this.execUserCommand = execUserCommand;
40 }
41
42 (0, _createClass3.default)(RecoveryAPI, [{
43 key: 'checkUserSockets',
44 value: function checkUserSockets(user) {
45 var _this = this;
46
47 var userName = user.userName;
48
49 return user.userState.getSocketsToInstance().then(function (sockets) {
50 return Promise.each(_.toPairs(sockets), function (_ref) {
51 var _ref2 = (0, _slicedToArray3.default)(_ref, 2);
52
53 var socket = _ref2[0];
54 var instance = _ref2[1];
55
56 if (instance === _this.instanceUID) {
57 if (!_this.transport.getSocket(socket)) {
58 return user.userState.removeSocket(socket);
59 }
60 }
61 return Promise.resolve();
62 });
63 }).then(function () {
64 return user.userState.getSocketsToRooms();
65 }).then(function (data) {
66 var args = _.values(data);
67 return _.intersection.apply(_, (0, _toConsumableArray3.default)(args));
68 }).then(function (rooms) {
69 return Promise.each(rooms, function (roomName) {
70 return _this.state.getRoom(roomName).then(function (room) {
71 return room.roomState.hasInList('userlist', userName);
72 }).then(function (isPresent) {
73 return isPresent ? Promise.resolve() : user.removeFromRoom(roomName);
74 }).catchReturn();
75 });
76 });
77 }
78 }, {
79 key: 'checkRoomJoined',
80 value: function checkRoomJoined(room) {
81 var _this2 = this;
82
83 var roomName = room.roomName;
84
85 return room.getList(null, 'userlist', true).then(function (userlist) {
86 return Promise.each(userlist, function (userName) {
87 return _this2.state.getUser(userName).then(function (user) {
88 return user.userState.getRoomToSockets(roomName).then(function (sockets) {
89 if (!sockets || !sockets.length) {
90 return user.removeFromRoom(roomName);
91 } else {
92 return Promise.resolve();
93 }
94 }).catchReturn().then(function () {
95 return room.checkAcess(userName);
96 }).catch(function () {
97 return user.removeFromRoom(roomName);
98 });
99 }).catchReturn();
100 });
101 });
102 }
103
104 /**
105 * Sync user to sockets associations.
106 *
107 * @param {string} userName User name.
108 * @param {callback} [cb] Optional callback.
109 *
110 * @return {Promise<undefined>} Promise that resolves without any data.
111 */
112
113 }, {
114 key: 'userStateSync',
115 value: function userStateSync(userName, cb) {
116 var _this3 = this;
117
118 return this.state.getUser(userName).then(function (user) {
119 return _this3.checkUserSockets(user);
120 }).asCallback(cb);
121 }
122
123 /**
124 * Sync room to users associations.
125 *
126 * @param {string} roomName Room name.
127 * @param {callback} [cb] Optional callback.
128 *
129 * @return {Promise<undefined>} Promise that resolves without any data.
130 */
131
132 }, {
133 key: 'roomStateSync',
134 value: function roomStateSync(roomName, cb) {
135 var _this4 = this;
136
137 return this.state.getRoom(roomName).then(function (room) {
138 return _this4.checkRoomJoined(room);
139 }).asCallback(cb);
140 }
141
142 /**
143 * Fixes an instance data after an incorrect service shutdown.
144 *
145 * @param {string} id Instance id.
146 * @param {callback} [cb] Optional callback.
147 *
148 * @return {Promise<undefined>} Promise that resolves without any data.
149 */
150
151 }, {
152 key: 'instanceRecovery',
153 value: function instanceRecovery(id, cb) {
154 var _this5 = this;
155
156 return this.state.getInstanceSockets(id).then(function (sockets) {
157 return Promise.each(_.toPairs(sockets), function (_ref3) {
158 var _ref4 = (0, _slicedToArray3.default)(_ref3, 2);
159
160 var id = _ref4[0];
161 var userName = _ref4[1];
162
163 return _this5.state.getUser(userName).then(function (user) {
164 return user.removeSocket(id);
165 }).catchReturn();
166 });
167 }).asCallback(cb);
168 }
169
170 /**
171 * Gets an instance heartbeat.
172 *
173 * @param {string} id Instance id.
174 * @param {callback} [cb] Optional callback.
175 *
176 * @return {Promise<number>} Heartbeat timestamp.
177 */
178
179 }, {
180 key: 'getInstanceHeartbeat',
181 value: function getInstanceHeartbeat(id, cb) {
182 return this.state.getInstanceHeartbeat(id).asCallback(cb);
183 }
184 }]);
185 return RecoveryAPI;
186}();
187
188module.exports = RecoveryAPI;
189//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZWNvdmVyeUFQSS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxJQUFNLFVBQVUsUUFBUSxVQUFSLENBQWhCO0FBQ0EsSUFBTSxJQUFJLFFBQVEsUUFBUixDQUFWOztBQUVBOzs7Ozs7OztJQU9NLFc7QUFFSix1QkFBYSxLQUFiLEVBQW9CLFNBQXBCLEVBQStCLGVBQS9CLEVBQWdELFdBQWhELEVBQTZEO0FBQUE7O0FBQzNELFNBQUssS0FBTCxHQUFhLEtBQWI7QUFDQSxTQUFLLFNBQUwsR0FBaUIsU0FBakI7QUFDQSxTQUFLLFdBQUwsR0FBbUIsV0FBbkI7QUFDQSxTQUFLLGVBQUwsR0FBdUIsZUFBdkI7QUFDRDs7OztxQ0FFaUIsSSxFQUFNO0FBQUE7O0FBQUEsVUFDaEIsUUFEZ0IsR0FDSCxJQURHLENBQ2hCLFFBRGdCOztBQUV0QixhQUFPLEtBQUssU0FBTCxDQUFlLG9CQUFmLEdBQXNDLElBQXRDLENBQTJDLG1CQUFXO0FBQzNELGVBQU8sUUFBUSxJQUFSLENBQWEsRUFBRSxPQUFGLENBQVUsT0FBVixDQUFiLEVBQWlDLGdCQUF3QjtBQUFBOztBQUFBLGNBQXRCLE1BQXNCO0FBQUEsY0FBZCxRQUFjOztBQUM5RCxjQUFJLGFBQWEsTUFBSyxXQUF0QixFQUFtQztBQUNqQyxnQkFBSSxDQUFDLE1BQUssU0FBTCxDQUFlLFNBQWYsQ0FBeUIsTUFBekIsQ0FBTCxFQUF1QztBQUNyQyxxQkFBTyxLQUFLLFNBQUwsQ0FBZSxZQUFmLENBQTRCLE1BQTVCLENBQVA7QUFDRDtBQUNGO0FBQ0QsaUJBQU8sUUFBUSxPQUFSLEVBQVA7QUFDRCxTQVBNLENBQVA7QUFRRCxPQVRNLEVBU0osSUFUSSxDQVNDLFlBQU07QUFDWixlQUFPLEtBQUssU0FBTCxDQUFlLGlCQUFmLEVBQVA7QUFDRCxPQVhNLEVBV0osSUFYSSxDQVdDLGdCQUFRO0FBQ2QsWUFBSSxPQUFPLEVBQUUsTUFBRixDQUFTLElBQVQs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Ozs7Ozs7Ozs7Ozt5Q0FRc0IsRSxFQUFJLEUsRUFBSTtBQUM1QixhQUFPLEtBQUssS0FBTCxDQUFXLG9CQUFYLENBQWdDLEVBQWhDLEVBQW9DLFVBQXBDLENBQStDLEVBQS9DLENBQVA7QUFDRDs7Ozs7QUFJSCxPQUFPLE9BQVAsR0FBaUIsV0FBakIiLCJmaWxlIjoiUmVjb3ZlcnlBUEkuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuY29uc3QgUHJvbWlzZSA9IHJlcXVpcmUoJ2JsdWViaXJkJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuXG4vKipcbiAqIFNlcnZpY2UgaW5mcmFzdHJ1Y3R1cmUgZmFpbHVyZXMgcmVjb3ZlcnkuXG4gKlxuICogQG1peGluXG4gKiBAbWVtYmVyb2YgY2hhdC1zZXJ2aWNlXG4gKiBAc2VlIGNoYXQtc2VydmljZS5DaGF0U2VydmljZS5ldmVudDpzdG9yZUNvbnNpc3RlbmN5RmFpbHVyZVxuICovXG5jbGFzcyBSZWNvdmVyeUFQSSB7XG5cbiAgY29uc3RydWN0b3IgKHN0YXRlLCB0cmFuc3BvcnQsIGV4ZWNVc2VyQ29tbWFuZCwgaW5zdGFuY2VVSUQpIHtcbiAgICB0aGlzLnN0YXRlID0gc3RhdGVcbiAgICB0aGlzLnRyYW5zcG9ydCA9IHRyYW5zcG9ydFxuICAgIHRoaXMuaW5zdGFuY2VVSUQgPSBpbnN0YW5jZVVJRFxuICAgIHRoaXMuZXhlY1VzZXJDb21tYW5kID0gZXhlY1VzZXJDb21tYW5kXG4gIH1cblxuICBjaGVja1VzZXJTb2NrZXRzICh1c2VyKSB7XG4gICAgbGV0IHsgdXNlck5hbWUgfSA9IHVzZXJcbiAgICByZXR1cm4gdXNlci51c2VyU3RhdGUuZ2V0U29ja2V0c1RvSW5zdGFuY2UoKS50aGVuKHNvY2tldHMgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UuZWFjaChfLnRvUGFpcnMoc29ja2V0cyksIChbc29ja2V0LCBpbnN0YW5jZV0pID0+IHtcbiAgICAgICAgaWYgKGluc3RhbmNlID09PSB0aGlzLmluc3RhbmNlVUlEKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLnRyYW5zcG9ydC5nZXRTb2NrZXQoc29ja2V0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHVzZXIudXNlclN0YXRlLnJlbW92ZVNvY2tldChzb2NrZXQpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgfSlcbiAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB1c2VyLnVzZXJTdGF0ZS5nZXRTb2NrZXRzVG9Sb29tcygpXG4gICAgfSkudGhlbihkYXRhID0+IHtcbiAgICAgIGxldCBhcmdzID0gXy52YWx1ZXMoZGF0YSlcbiAgICAgIHJldHVybiBfLmludGVyc2VjdGlvbiguLi5hcmdzKVxuICAgIH0pLnRoZW4ocm9vbXMgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UuZWFjaChyb29tcywgcm9vbU5hbWUgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRSb29tKHJvb21OYW1lKVxuICAgICAgICAgIC50aGVuKHJvb20gPT4gcm9vbS5yb29tU3RhdGUuaGFzSW5MaXN0KCd1c2VybGlzdCcsIHVzZXJOYW1lKSlcbiAgICAgICAgICAudGhlbihpc1ByZXNlbnQgPT5cbiAgICAgICAgICAgICAgICBpc1ByZXNlbnQgPyBQcm9taXNlLnJlc29sdmUoKSA6IHVzZXIucmVtb3ZlRnJvbVJvb20ocm9vbU5hbWUpKVxuICAgICAgICAgIC5jYXRjaFJldHVybigpXG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICBjaGVja1Jvb21Kb2luZWQgKHJvb20pIHtcbiAgICBsZXQgeyByb29tTmFtZSB9ID0gcm9vbVxuICAgIHJldHVybiByb29tLmdldExpc3QobnVsbCwgJ3VzZXJsaXN0JywgdHJ1ZSkudGhlbih1c2VybGlzdCA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5lYWNoKHVzZXJsaXN0LCB1c2VyTmFtZSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFVzZXIodXNlck5hbWUpLnRoZW4odXNlciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHVzZXIudXNlclN0YXRlLmdldFJvb21Ub1NvY2tldHMocm9vbU5hbWUpLnRoZW4oc29ja2V0cyA9PiB7XG4gICAgICAgICAgICBpZiAoIXNvY2tldHMgfHwgIXNvY2tldHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIHJldHVybiB1c2VyLnJlbW92ZUZyb21Sb29tKHJvb21OYW1lKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkuY2F0Y2hSZXR1cm4oKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gcm9vbS5jaGVja0FjZXNzKHVzZXJOYW1lKSlcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB1c2VyLnJlbW92ZUZyb21Sb29tKHJvb21OYW1lKSlcbiAgICAgICAgfSkuY2F0Y2hSZXR1cm4oKVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFN5bmMgdXNlciB0byBzb2NrZXRzIGFzc29jaWF0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIFVzZXIgbmFtZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aG91dCBhbnkgZGF0YS5cbiAgICovXG4gIHVzZXJTdGF0ZVN5bmMgKHVzZXJOYW1lLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFVzZXIodXNlck5hbWUpXG4gICAgICAudGhlbih1c2VyID0+IHRoaXMuY2hlY2tVc2VyU29ja2V0cyh1c2VyKSlcbiAgICAgIC5hc0NhbGxiYWNrKGNiKVxuICB9XG5cbiAgLyoqXG4gICAqIFN5bmMgcm9vbSB0byB1c2VycyBhc3NvY2lhdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByb29tTmFtZSBSb29tIG5hbWUuXG4gICAqIEBwYXJhbSB7Y2FsbGJhY2t9IFtjYl0gT3B0aW9uYWwgY2FsbGJhY2suXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhvdXQgYW55IGRhdGEuXG4gICAqL1xuICByb29tU3RhdGVTeW5jIChyb29tTmFtZSwgY2IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRSb29tKHJvb21OYW1lKVxuICAgICAgLnRoZW4ocm9vbSA9PiB0aGlzLmNoZWNrUm9vbUpvaW5lZChyb29tKSlcbiAgICAgIC5hc0NhbGxiYWNrKGNiKVxuICB9XG5cbiAgLyoqXG4gICAqIEZpeGVzIGFuIGluc3RhbmNlIGRhdGEgYWZ0ZXIgYW4gaW5jb3JyZWN0IHNlcnZpY2Ugc2h1dGRvd24uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJbnN0YW5jZSBpZC5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aG91dCBhbnkgZGF0YS5cbiAgICovXG4gIGluc3RhbmNlUmVjb3ZlcnkgKGlkLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldEluc3RhbmNlU29ja2V0cyhpZCkudGhlbihzb2NrZXRzID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLmVhY2goXy50b1BhaXJzKHNvY2tldHMpLCAoW2lkLCB1c2VyTmFtZV0pID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUuZ2V0VXNlcih1c2VyTmFtZSlcbiAgICAgICAgICAudGhlbih1c2VyID0+IHVzZXIucmVtb3ZlU29ja2V0KGlkKSlcbiAgICAgICAgICAuY2F0Y2hSZXR1cm4oKVxuICAgICAgfSlcbiAgICB9KS5hc0NhbGxiYWNrKGNiKVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYW4gaW5zdGFuY2UgaGVhcnRiZWF0LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSW5zdGFuY2UgaWQuXG4gICAqIEBwYXJhbSB7Y2FsbGJhY2t9IFtjYl0gT3B0aW9uYWwgY2FsbGJhY2suXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8bnVtYmVyPn0gSGVhcnRiZWF0IHRpbWVzdGFtcC5cbiAgICovXG4gIGdldEluc3RhbmNlSGVhcnRiZWF0IChpZCwgY2IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRJbnN0YW5jZUhlYXJ0YmVhdChpZCkuYXNDYWxsYmFjayhjYilcbiAgfVxuXG59XG5cbm1vZHVsZS5leHBvcnRzID0gUmVjb3ZlcnlBUElcbiJdfQ==
\No newline at end of file