wingbot-mongodb 3.1.1 → 3.2.0

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":67090,"argv":["/usr/local/bin/node","/Users/david/Development/wingbot-mongodb/node_modules/.bin/mocha","./test"],"execArgv":[],"cwd":"/Users/david/Development/wingbot-mongodb","time":1672231628548,"ppid":67089,"coverageFilename":"/Users/david/Development/wingbot-mongodb/.nyc_output/348f41df-6e7a-4377-9c78-40269fd1eaef.json","externalId":"","uuid":"348f41df-6e7a-4377-9c78-40269fd1eaef","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":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 +1 @@
1
- {"processes":{"348f41df-6e7a-4377-9c78-40269fd1eaef":{"parent":null,"children":[]}},"files":{"/Users/david/Development/wingbot-mongodb/src/BaseStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/defaultLogger.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/tokenFactory.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"],"/Users/david/Development/wingbot-mongodb/src/StateStorage.js":["348f41df-6e7a-4377-9c78-40269fd1eaef"]},"externalIds":{}}
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":{}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot-mongodb",
3
- "version": "3.1.1",
3
+ "version": "3.2.0",
4
4
  "description": "MongoDB storage for wingbot.ai",
5
5
  "main": "src/main.js",
6
6
  "scripts": {
@@ -8,6 +8,7 @@ const defaultLogger = require('./defaultLogger');
8
8
 
9
9
  const PAGE_SENDER_TIMESTAMP = 'pageId_1_senderId_1_timestamp_-1';
10
10
  const TIMESTAMP = 'timestamp_1';
11
+ const SENDER = 'senderId_1';
11
12
 
12
13
  /** @typedef {import('mongodb').Db} Db */
13
14
 
@@ -43,6 +44,12 @@ class ChatLogStorage extends BaseStorage {
43
44
  }, {
44
45
  name: TIMESTAMP
45
46
  });
47
+
48
+ this.addIndex({
49
+ senderId: 1
50
+ }, {
51
+ name: SENDER
52
+ });
46
53
  }
47
54
 
48
55
  this.muteErrors = true;
@@ -37,10 +37,10 @@ class StateStorage extends BaseStorage {
37
37
  * @param {Db|{():Promise<Db>}} mongoDb
38
38
  * @param {string} collectionName
39
39
  * @param {{error:Function,log:Function}} [log] - console like logger
40
- * @param {boolean} isCosmo
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, isCosmo);
43
+ super(mongoDb, collectionName, log, typeof isCosmo === 'number' || isCosmo);
44
44
 
45
45
  this.addIndex(
46
46
  { senderId: 1, pageId: 1 },
@@ -51,6 +51,10 @@ 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
+
54
58
  if (isCosmo) {
55
59
  this.addIndex(
56
60
  { name: 1 },
@@ -63,6 +67,20 @@ class StateStorage extends BaseStorage {
63
67
  );
64
68
  }
65
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);
66
84
  }
67
85
 
68
86
  /**
@@ -100,38 +118,59 @@ class StateStorage extends BaseStorage {
100
118
  * @returns {Promise<object>} - conversation state
101
119
  */
102
120
  async getOrCreateAndLock (senderId, pageId, defaultState = {}, timeout = 300) {
103
- const now = Date.now();
104
-
105
- const c = await this._getCollection();
106
-
107
- const $setOnInsert = {
108
- state: defaultState,
109
- lastSendError: null,
110
- off: false
111
- };
112
-
113
- const $set = {
114
- lock: now
115
- };
116
-
117
- const $lt = now - timeout;
118
-
119
- const res = await c.findOneAndUpdate({
120
- senderId,
121
- pageId,
122
- lock: { $lt }
123
- }, {
124
- $setOnInsert,
125
- $set
126
- }, {
127
- upsert: true,
128
- returnDocument: 'after',
129
- projection: {
130
- _id: 0
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
+ }
131
169
  }
132
- });
133
170
 
134
- return res.value;
171
+ throw e;
172
+ }
173
+
135
174
  }
136
175
 
137
176
  /**