wingbot-mongodb 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +1 -0
- package/.nyc_output/6a7ed916-683a-43fd-8624-795a77e80a4a.json +1 -0
- package/.nyc_output/processinfo/{cb79cd4d-6c45-40e4-b29a-e38af10c7c7c.json → 6a7ed916-683a-43fd-8624-795a77e80a4a.json} +1 -1
- package/.nyc_output/processinfo/index.json +1 -1
- package/package.json +1 -1
- package/src/BaseStorage.js +66 -3
- package/src/StateStorage.js +30 -71
- package/.nyc_output/cb79cd4d-6c45-40e4-b29a-e38af10c7c7c.json +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"parent":null,"pid":
|
|
1
|
+
{"parent":null,"pid":69488,"argv":["/usr/local/bin/node","/Users/david/Development/wingbot-mongodb/node_modules/.bin/mocha","./test"],"execArgv":[],"cwd":"/Users/david/Development/wingbot-mongodb","time":1676391651316,"ppid":69487,"coverageFilename":"/Users/david/Development/wingbot-mongodb/.nyc_output/6a7ed916-683a-43fd-8624-795a77e80a4a.json","externalId":"","uuid":"6a7ed916-683a-43fd-8624-795a77e80a4a","files":["/Users/david/Development/wingbot-mongodb/src/BaseStorage.js","/Users/david/Development/wingbot-mongodb/src/defaultLogger.js","/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js","/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js","/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js","/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js","/Users/david/Development/wingbot-mongodb/src/tokenFactory.js","/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js","/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js","/Users/david/Development/wingbot-mongodb/src/StateStorage.js"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"processes":{"
|
|
1
|
+
{"processes":{"6a7ed916-683a-43fd-8624-795a77e80a4a":{"parent":null,"children":[]}},"files":{"/Users/david/Development/wingbot-mongodb/src/BaseStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/defaultLogger.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/tokenFactory.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"],"/Users/david/Development/wingbot-mongodb/src/StateStorage.js":["6a7ed916-683a-43fd-8624-795a77e80a4a"]},"externalIds":{}}
|
package/package.json
CHANGED
package/src/BaseStorage.js
CHANGED
|
@@ -33,12 +33,31 @@ function getNestedObjects (obj, nested, attr = null, ret = {}) {
|
|
|
33
33
|
|
|
34
34
|
class BaseStorage {
|
|
35
35
|
|
|
36
|
+
static netFailuresIntervalMs = 600000; // 10 minutes
|
|
37
|
+
|
|
38
|
+
static netFailuresCount = 0;
|
|
39
|
+
|
|
40
|
+
static _killing = null;
|
|
41
|
+
|
|
42
|
+
static _failStack = [];
|
|
43
|
+
|
|
44
|
+
static killer = () => setTimeout(() => {
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}, 10000);
|
|
47
|
+
|
|
48
|
+
static networkFailureErrorNames = [
|
|
49
|
+
'MongoServerSelectionError',
|
|
50
|
+
'MongoNetworkError',
|
|
51
|
+
'MongoNetworkTimeoutError',
|
|
52
|
+
'MongoTopologyClosedError'
|
|
53
|
+
];
|
|
54
|
+
|
|
36
55
|
/**
|
|
37
56
|
*
|
|
38
57
|
* @param {Db|{():Promise<Db>}} mongoDb
|
|
39
58
|
* @param {string} collectionName
|
|
40
59
|
* @param {{error:Function,log:Function}} [log] - console like logger
|
|
41
|
-
* @param {boolean} [isCosmo]
|
|
60
|
+
* @param {boolean|number} [isCosmo]
|
|
42
61
|
* @example
|
|
43
62
|
*
|
|
44
63
|
* const { BaseStorage } = require('winbot-mongodb');
|
|
@@ -67,7 +86,7 @@ class BaseStorage {
|
|
|
67
86
|
constructor (mongoDb, collectionName, log = defaultLogger, isCosmo = false) {
|
|
68
87
|
this._mongoDb = mongoDb;
|
|
69
88
|
this._collectionName = collectionName;
|
|
70
|
-
this._isCosmo = isCosmo;
|
|
89
|
+
this._isCosmo = typeof isCosmo === 'number' || isCosmo;
|
|
71
90
|
this._log = log;
|
|
72
91
|
|
|
73
92
|
/**
|
|
@@ -84,7 +103,11 @@ class BaseStorage {
|
|
|
84
103
|
|
|
85
104
|
this._fixtures = [];
|
|
86
105
|
|
|
87
|
-
if (isCosmo
|
|
106
|
+
if (typeof isCosmo === 'number') {
|
|
107
|
+
BaseStorage.netFailuresCount = isCosmo;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (this._isCosmo && !process.argv.some((a) => a.endsWith('mocha'))) {
|
|
88
111
|
process.nextTick(() => {
|
|
89
112
|
const hasUniqueIndex = this._indexes.some((i) => i.options.unique);
|
|
90
113
|
|
|
@@ -96,6 +119,45 @@ class BaseStorage {
|
|
|
96
119
|
}
|
|
97
120
|
}
|
|
98
121
|
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
* @template T
|
|
125
|
+
* @param {{():T}} fn
|
|
126
|
+
* @returns {Promise<T>}
|
|
127
|
+
*/
|
|
128
|
+
_catchNetworkIssues (fn) {
|
|
129
|
+
return Promise.resolve(fn())
|
|
130
|
+
.catch((e) => {
|
|
131
|
+
this._detectNetworkIssueException(e);
|
|
132
|
+
throw e;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @template {Error} T
|
|
138
|
+
* @param {T} e
|
|
139
|
+
* @returns {T}
|
|
140
|
+
*/
|
|
141
|
+
_detectNetworkIssueException (e) {
|
|
142
|
+
if (BaseStorage.netFailuresCount !== 0
|
|
143
|
+
&& BaseStorage.networkFailureErrorNames.includes(e.name)) {
|
|
144
|
+
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
BaseStorage._failStack.push(now);
|
|
147
|
+
|
|
148
|
+
if (BaseStorage._failStack.length >= BaseStorage.netFailuresCount
|
|
149
|
+
&& BaseStorage._failStack.shift() > (now - BaseStorage.netFailuresIntervalMs)
|
|
150
|
+
&& BaseStorage._killing === null) {
|
|
151
|
+
|
|
152
|
+
this._log.error(`${this._collectionName}: KILLING APP DUE FREQUENT NETWORK ERRORS ${BaseStorage._failStack.length}`, e);
|
|
153
|
+
|
|
154
|
+
// let it alive for following ten seconds to process all logs
|
|
155
|
+
BaseStorage._killing = BaseStorage.killer() || null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return e;
|
|
159
|
+
}
|
|
160
|
+
|
|
99
161
|
preHeat () {
|
|
100
162
|
return this._getCollection();
|
|
101
163
|
}
|
|
@@ -201,6 +263,7 @@ class BaseStorage {
|
|
|
201
263
|
this._collection = c;
|
|
202
264
|
} catch (e) {
|
|
203
265
|
this._collection = null;
|
|
266
|
+
this._detectNetworkIssueException(e);
|
|
204
267
|
throw e;
|
|
205
268
|
}
|
|
206
269
|
}
|
package/src/StateStorage.js
CHANGED
|
@@ -40,7 +40,7 @@ class StateStorage extends BaseStorage {
|
|
|
40
40
|
* @param {boolean|number} isCosmo - boolean or number of failures in last 10min to kill app
|
|
41
41
|
*/
|
|
42
42
|
constructor (mongoDb, collectionName = 'states', log = defaultLogger, isCosmo = false) {
|
|
43
|
-
super(mongoDb, collectionName, log,
|
|
43
|
+
super(mongoDb, collectionName, log, isCosmo);
|
|
44
44
|
|
|
45
45
|
this.addIndex(
|
|
46
46
|
{ senderId: 1, pageId: 1 },
|
|
@@ -51,10 +51,6 @@ class StateStorage extends BaseStorage {
|
|
|
51
51
|
{ name: LAST_INTERACTION_INDEX }
|
|
52
52
|
);
|
|
53
53
|
|
|
54
|
-
this._failStack = [];
|
|
55
|
-
|
|
56
|
-
this._failures = typeof isCosmo === 'number' ? isCosmo : 0;
|
|
57
|
-
|
|
58
54
|
if (isCosmo) {
|
|
59
55
|
this.addIndex(
|
|
60
56
|
{ name: 1 },
|
|
@@ -66,21 +62,6 @@ class StateStorage extends BaseStorage {
|
|
|
66
62
|
{ name: SEARCH }
|
|
67
63
|
);
|
|
68
64
|
}
|
|
69
|
-
|
|
70
|
-
this.failuresIntervalMs = 600000; // 10 minutes
|
|
71
|
-
|
|
72
|
-
this._killing = null;
|
|
73
|
-
|
|
74
|
-
this.networkFailureErrorNames = [
|
|
75
|
-
'MongoServerSelectionError',
|
|
76
|
-
'MongoNetworkError',
|
|
77
|
-
'MongoNetworkTimeoutError',
|
|
78
|
-
'MongoTopologyClosedError'
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
this.killer = () => setTimeout(() => {
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}, 10000);
|
|
84
65
|
}
|
|
85
66
|
|
|
86
67
|
/**
|
|
@@ -118,59 +99,37 @@ class StateStorage extends BaseStorage {
|
|
|
118
99
|
* @returns {Promise<object>} - conversation state
|
|
119
100
|
*/
|
|
120
101
|
async getOrCreateAndLock (senderId, pageId, defaultState = {}, timeout = 300) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const c = await this._getCollection();
|
|
124
|
-
|
|
125
|
-
const $setOnInsert = {
|
|
126
|
-
state: defaultState,
|
|
127
|
-
lastSendError: null,
|
|
128
|
-
off: false
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const $set = {
|
|
132
|
-
lock: now
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const $lt = now - timeout;
|
|
136
|
-
|
|
137
|
-
const res = await c.findOneAndUpdate({
|
|
138
|
-
senderId,
|
|
139
|
-
pageId,
|
|
140
|
-
lock: { $lt }
|
|
141
|
-
}, {
|
|
142
|
-
$setOnInsert,
|
|
143
|
-
$set
|
|
144
|
-
}, {
|
|
145
|
-
upsert: true,
|
|
146
|
-
returnDocument: 'after',
|
|
147
|
-
projection: {
|
|
148
|
-
_id: 0
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
return res.value;
|
|
153
|
-
} catch (e) {
|
|
154
|
-
if (this._failures !== 0
|
|
155
|
-
&& this.networkFailureErrorNames.includes(e.name)) {
|
|
156
|
-
|
|
157
|
-
now = Date.now();
|
|
158
|
-
this._failStack.push(now);
|
|
159
|
-
|
|
160
|
-
if (this._failStack.length >= this._failures
|
|
161
|
-
&& this._failStack.shift() > (now - this.failuresIntervalMs)
|
|
162
|
-
&& this._killing === null) {
|
|
163
|
-
|
|
164
|
-
this._log.error(`StateStorage: KILLING APP DUE FREQUENT NETWORK ERRORS ${this._failStack.length}`, e);
|
|
165
|
-
|
|
166
|
-
// let it alive for following ten seconds to process all logs
|
|
167
|
-
this._killing = this.killer() || null;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
102
|
+
const now = Date.now();
|
|
103
|
+
const c = await this._getCollection();
|
|
170
104
|
|
|
171
|
-
|
|
172
|
-
|
|
105
|
+
const $setOnInsert = {
|
|
106
|
+
state: defaultState,
|
|
107
|
+
lastSendError: null,
|
|
108
|
+
off: false
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const $set = {
|
|
112
|
+
lock: now
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const $lt = now - timeout;
|
|
116
|
+
|
|
117
|
+
const res = await this._catchNetworkIssues(() => c.findOneAndUpdate({
|
|
118
|
+
senderId,
|
|
119
|
+
pageId,
|
|
120
|
+
lock: { $lt }
|
|
121
|
+
}, {
|
|
122
|
+
$setOnInsert,
|
|
123
|
+
$set
|
|
124
|
+
}, {
|
|
125
|
+
upsert: true,
|
|
126
|
+
returnDocument: 'after',
|
|
127
|
+
projection: {
|
|
128
|
+
_id: 0
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
173
131
|
|
|
132
|
+
return res.value;
|
|
174
133
|
}
|
|
175
134
|
|
|
176
135
|
/**
|