wingbot 3.66.0 → 3.66.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.66.0",
3
+ "version": "3.66.2",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/BotApp.js CHANGED
@@ -91,6 +91,7 @@ class BotApp {
91
91
  } = options;
92
92
 
93
93
  this._returnSenderOptions = {
94
+ dontWaitForDeferredOps: processorOptions.dontWaitForDeferredOps,
94
95
  textFilter,
95
96
  logStandbyEvents,
96
97
  confidentInputFilter
@@ -312,8 +313,8 @@ class BotApp {
312
313
  const sender = new ReturnSender(options, senderId, message, this._senderLogger);
313
314
  sender.propagatesWaitEvent = true;
314
315
  const res = await this._processor.processMessage(message, pageId, sender, { appId });
315
- await this._processSenderResponses(sender, senderId, pageId, headers);
316
-
316
+ sender.defer(this._processSenderResponses(sender, senderId, pageId, headers));
317
+ await sender.waitForDeferredOps();
317
318
  return {
318
319
  status: res.status,
319
320
  // yes, it should be just mid
@@ -337,7 +338,8 @@ class BotApp {
337
338
 
338
339
  const sender = await this.createSender(senderId, pageId, message, secret, appId);
339
340
  const res = await this._processor.processMessage(message, pageId, sender, { appId });
340
- await this._processSenderResponses(sender, senderId, pageId, headers);
341
+ sender.defer(this._processSenderResponses(sender, senderId, pageId, headers));
342
+ await sender.waitForDeferredOps();
341
343
 
342
344
  return {
343
345
  status: res.status,
@@ -111,17 +111,21 @@ const DUMMY_ROUTE = { id: 0, path: null, resolvers: [] };
111
111
  * @param {object} state
112
112
  * @param {string} pageId
113
113
  * @returns {string}
114
- */
114
+ */
115
115
 
116
116
  /**
117
117
  * @template {BaseConfiguration} [C=object]
118
- * @typedef {object} BotContext
118
+ * @typedef {object} BuildRouterContext
119
119
  * @prop {LinkTranslator} [linksTranslator] - function, that translates links globally
120
120
  * @prop {ConfigStorage} [configStorage] - function, that translates links globally
121
121
  * @prop {boolean} [allowForbiddenSnippetWords] - disable security rule
122
122
  * @prop {Middleware} [defaultPlugin] - to be able to test configurations without plugins
123
123
  * @prop {RouteConfig[]} [routeConfigs] - list of disabled routes
124
124
  * @prop {C} [configuration] - context data
125
+ */
126
+
127
+ /**
128
+ * @typedef {object} BotContextExtention
125
129
  * @prop {LinksMap} [linksMap]
126
130
  * @prop {boolean} [isLastIndex]
127
131
  * @prop {boolean} [isLastMessage]
@@ -140,6 +144,11 @@ const DUMMY_ROUTE = { id: 0, path: null, resolvers: [] };
140
144
  * @prop {string|number} [resolverId] - only for text messages with random characters
141
145
  */
142
146
 
147
+ /**
148
+ * @template {BaseConfiguration} [C=object]
149
+ * @typedef {BotContextExtention & BuildRouterContext<C>} BotContext
150
+ */
151
+
143
152
  /**
144
153
  * Build bot from Wingbot configuration file or snapshot url
145
154
  *
@@ -156,12 +165,7 @@ class BuildRouter extends Router {
156
165
  * @constructor
157
166
  * @param {BotConfig|Block} block
158
167
  * @param {Plugins} plugins - custom code blocks resource
159
- * @param {object} context - the building context
160
- * @param {object} [context.linksTranslator] - function, that translates links globally
161
- * @param {ConfigStorage} [context.configStorage] - function, that translates links globally
162
- * @param {boolean} [context.allowForbiddenSnippetWords] - disable security rule
163
- * @param {RouteConfig[]} [context.routeConfigs] - list of disabled routes
164
- * @param {C} [context.configuration]
168
+ * @param {BuildRouterContext<C>} context - the building context
165
169
  * @param {fetch} [fetchFn] - override a request function
166
170
  * @example
167
171
  *
package/src/Processor.js CHANGED
@@ -403,7 +403,7 @@ class Processor extends EventEmitter {
403
403
  const result = await this
404
404
  ._dispatch(message, pageId, messageSender, responderData, preloadPromise);
405
405
 
406
- await preloadPromise;
406
+ messageSender.defer(preloadPromise, this.options.log);
407
407
  return result;
408
408
  }
409
409
 
@@ -419,7 +419,7 @@ class Processor extends EventEmitter {
419
419
  } = await this
420
420
  ._processMessage(message, pageId, messageSender, responderData, preloadPromise));
421
421
 
422
- await this._emitInteractionEvent(req, res, messageSender, state, data);
422
+ messageSender.defer(this._emitInteractionEvent(req, res, messageSender, state, data));
423
423
 
424
424
  return messageSender.finished(req, res, null, errorHandler);
425
425
  } catch (e) {
@@ -579,7 +579,7 @@ class Processor extends EventEmitter {
579
579
  let req;
580
580
  let res;
581
581
 
582
- let emitPromise = Promise.resolve();
582
+ // let emitPromise = Promise.resolve();
583
583
 
584
584
  try {
585
585
  // ensure the request was not processed
@@ -776,7 +776,7 @@ class Processor extends EventEmitter {
776
776
  }
777
777
 
778
778
  if (fromEvent) {
779
- emitPromise = this._emitEvent(req, res);
779
+ messageSender.defer(this._emitEvent(req, res), this.options.log);
780
780
  }
781
781
  }
782
782
 
@@ -822,13 +822,22 @@ class Processor extends EventEmitter {
822
822
 
823
823
  } catch (e) {
824
824
  await this.stateStorage.saveState(originalState);
825
- await emitPromise;
825
+ // await emitPromise;
826
826
  Object.assign(e, { req, res });
827
827
  throw e;
828
828
  }
829
829
 
830
+ if (postbackAcumulator.length === 0) {
831
+ messageSender.defer(this.stateStorage.saveState(stateObject));
832
+ return {
833
+ req, res, data: res.data, state: stateObject.state
834
+ };
835
+ }
836
+
830
837
  try {
838
+
831
839
  await this.stateStorage.saveState(stateObject);
840
+
832
841
  // process postbacks
833
842
  const {
834
843
  state = stateObject.state,
@@ -842,7 +851,7 @@ class Processor extends EventEmitter {
842
851
  res.senderMeta
843
852
  );
844
853
 
845
- await emitPromise; // probably has been resolved this time
854
+ // await emitPromise; // probably has been resolved this time
846
855
 
847
856
  return {
848
857
  req, res, data, state
@@ -31,6 +31,7 @@ const extractText = require('./transcript/extractText');
31
31
 
32
32
  /**
33
33
  * @typedef {object} ReturnSenderOptions
34
+ * @prop {boolean} [dontWaitForDeferredOps]
34
35
  * @prop {textFilter} [textFilter] - filter for saving the texts
35
36
  * @prop {boolean} [logStandbyEvents] - log the standby events
36
37
  * @prop {textFilter} [confidentInputFilter] - filter for confident input (@CONFIDENT)
@@ -42,6 +43,16 @@ const extractText = require('./transcript/extractText');
42
43
  * @prop {string|number} [attachmentId]
43
44
  */
44
45
 
46
+ /**
47
+ * @callback DeferOperation
48
+ * @returns {Promise<any>}
49
+ */
50
+
51
+ /**
52
+ * @typedef {object} ErrorLogger
53
+ * @prop {Function} error
54
+ */
55
+
45
56
  /**
46
57
  * Text filter function
47
58
  *
@@ -147,6 +158,44 @@ class ReturnSender {
147
158
  this._gotAnotherEventDefer = null;
148
159
  this._anotherEventPromise = null;
149
160
  this._gotAnotherEvent();
161
+
162
+ this._skipWaitForDeferred = options.dontWaitForDeferredOps;
163
+ this._opQueue = new Set();
164
+ }
165
+
166
+ async waitForDeferredOps () {
167
+ if (this._skipWaitForDeferred) {
168
+ return;
169
+ }
170
+ await Promise.all(Array.from(this._opQueue.values()));
171
+ if (this._throwAtTheEnd) {
172
+ const e = this._throwAtTheEnd;
173
+ this._throwAtTheEnd = null;
174
+ throw e;
175
+ }
176
+ }
177
+
178
+ /**
179
+ *
180
+ * @param {DeferOperation|Promise} operation
181
+ * @param {ErrorLogger} logger
182
+ */
183
+ defer (operation, logger = console) {
184
+ const promise = (typeof operation === 'function'
185
+ ? Promise.resolve(operation())
186
+ : operation
187
+ )
188
+ .catch((e) => {
189
+ if (this._skipWaitForDeferred === false) {
190
+ this._throwAtTheEnd = e;
191
+ }
192
+ // eslint-disable-next-line no-console
193
+ logger.error('DEFER# - op failed', e);
194
+ })
195
+ .then(() => {
196
+ this._opQueue.delete(promise);
197
+ });
198
+ this._opQueue.add(promise);
150
199
  }
151
200
 
152
201
  set simulatesOptIn (value) {
@@ -578,27 +627,29 @@ class ReturnSender {
578
627
  if (!this._logger || meta.flag === ResponseFlag.DO_NOT_LOG) {
579
628
  // noop
580
629
  } else if (error) {
581
- await Promise.resolve(this._logger
582
- .error(error, this._senderId, sent, incomming, meta));
630
+ this.defer(Promise.resolve(this._logger
631
+ .error(error, this._senderId, sent, incomming, meta)));
583
632
  } else if (this._sendLogs) {
584
633
  this._sendLogs = false;
585
- await Promise.resolve(this._logger
586
- .log(this._senderId, sent, incomming, meta));
634
+ this.defer(Promise.resolve(this._logger
635
+ .log(this._senderId, sent, incomming, meta)));
587
636
  }
588
637
  } catch (e) {
589
638
  console.log('meta', meta); // eslint-disable-line no-console
590
- await Promise.resolve(reportError(e, this._incommingMessage, this._senderId));
639
+ this.defer(Promise.resolve(reportError(e, this._incommingMessage, this._senderId)));
591
640
  }
592
641
 
593
642
  if (error) {
594
643
  // @ts-ignore
595
644
  const { code = 500, message } = error;
596
- await Promise.resolve(reportError(error, this._incommingMessage, this._senderId));
645
+ this.defer(Promise.resolve(reportError(error, this._incommingMessage, this._senderId)));
646
+ await this.waitForDeferredOps();
597
647
  return { status: code, error: message, results: this.results };
598
648
  }
599
649
 
600
650
  const somethingSent = this._results.length > 0;
601
651
 
652
+ await this.waitForDeferredOps();
602
653
  return {
603
654
  status: somethingSent ? 200 : 204,
604
655
  results: this._results
package/src/Tester.js CHANGED
@@ -227,7 +227,10 @@ class Tester {
227
227
  Object.assign(message, { features: this.features });
228
228
  }
229
229
 
230
- const messageSender = new ReturnSender({}, senderId, message, this.senderLogger);
230
+ const messageSender = new ReturnSender({
231
+ dontWaitForDeferredOps: false
232
+ }, senderId, message, this.senderLogger);
233
+
231
234
  messageSender.simulatesOptIn = true;
232
235
 
233
236
  const res = await this.processor
@@ -1,32 +0,0 @@
1
- /*
2
- * @author Vašek Strnad
3
- */
4
- 'use strict';
5
-
6
- const Responder = require('./Responder');
7
- const { senderFactory } = require('./tools');
8
-
9
- function responderFactory (options = { token: null }, senderLogger = console, sender = undefined) {
10
-
11
- const senderFnFactory = senderFactory(
12
- options.token,
13
- senderLogger,
14
- undefined,
15
- sender
16
- );
17
-
18
- const factoryFn = function factory (
19
- senderId,
20
- senderFn = null,
21
- pageId = undefined,
22
- senderHandler = undefined
23
- ) {
24
-
25
- const sendFn = senderFn || senderFnFactory(null, pageId, senderHandler);
26
- return new Responder(false, senderId, sendFn, options.token, options);
27
- };
28
-
29
- return factoryFn;
30
- }
31
-
32
- module.exports = responderFactory;