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.
@@ -1 +1 @@
1
- {"parent":null,"pid":24990,"argv":["/usr/local/bin/node","/Users/david/Development/wingbot-mongodb/node_modules/.bin/mocha","./test"],"execArgv":[],"cwd":"/Users/david/Development/wingbot-mongodb","time":1676028268542,"ppid":24989,"coverageFilename":"/Users/david/Development/wingbot-mongodb/.nyc_output/cb79cd4d-6c45-40e4-b29a-e38af10c7c7c.json","externalId":"","uuid":"cb79cd4d-6c45-40e4-b29a-e38af10c7c7c","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
+ {"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":{"cb79cd4d-6c45-40e4-b29a-e38af10c7c7c":{"parent":null,"children":[]}},"files":{"/Users/david/Development/wingbot-mongodb/src/BaseStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/defaultLogger.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/tokenFactory.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"],"/Users/david/Development/wingbot-mongodb/src/StateStorage.js":["cb79cd4d-6c45-40e4-b29a-e38af10c7c7c"]},"externalIds":{}}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot-mongodb",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "MongoDB storage for wingbot.ai",
5
5
  "main": "src/main.js",
6
6
  "scripts": {
@@ -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 && !process.argv.some((a) => a.endsWith('mocha'))) {
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
  }
@@ -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, typeof isCosmo === 'number' || isCosmo);
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
- let now = Date.now();
122
- try {
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
- throw e;
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
  /**