Guest User

Untitled

a guest
Aug 15th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.41 KB | None | 0 0
  1. import EventEmitter from 'events';
  2. import onFinished from 'on-finished';
  3.  
  4. /*
  5. * RequestQueue to ensure that only a single request is executing at a time.
  6. *
  7. * This middleware intercepts requests as they come in by delaying executing of
  8. * next() until previous requests finish processing. This complements external
  9. * server configuration via haproxy or similar that restricts concurrent
  10. * requests. This per-process queue allows an application level guarantee of
  11. * mutual exclusion of requests. This allows that behavior to be depended
  12. * upon, allowing for safe (but careful) use of global state. Additionally,
  13. * this allows for lifecycle hooks to be added for the periods when no request
  14. * is currently executing, before or after the request has been run. These are
  15. * ideal points to install behavior to reset global state or perform actions
  16. * against the server at a "clean state" point in time.
  17. */
  18. export default class RequestQueue extends EventEmitter {
  19. constructor() {
  20. super();
  21. this.queue = [];
  22. this.current = null;
  23.  
  24. this.outerMiddleware = this.outerMiddleware.bind(this);
  25. this.innerMiddleware = this.innerMiddleware.bind(this);
  26. this.finishCurrent = this.finishCurrent.bind(this);
  27. }
  28.  
  29. process() {
  30. if (!this.current) {
  31. this.current = this.queue.shift();
  32. this.emit('queueLength', this.queue.length);
  33.  
  34. if (this.current) {
  35. this.emit('beforeRequest');
  36. this.current.start();
  37. }
  38. } else {
  39. this.emit('queueLength', this.queue.length);
  40. }
  41. }
  42.  
  43. /*
  44. * Outer middleware must be the very first middleware installed on the app.
  45. * This intercepts and begins queueing the request.
  46. */
  47. outerMiddleware(req, res, next) {
  48. const job = { req, res, start: next };
  49.  
  50. this.push(job);
  51. }
  52.  
  53. /*
  54. * Inner middleware must be last middleware installed before endpoints. This
  55. * is only necessary because on-finished executes its callbacks in the order
  56. * in which they were installed. We need this to be innermost so that we
  57. * advance the queue only after the request and all other on-finished
  58. * callbacks complete.
  59. *
  60. * Not adding this middleware will result in the queue never being drained.
  61. */
  62. innerMiddleware(req, res, next) {
  63. onFinished(res, this.finishCurrent);
  64. next();
  65. }
  66.  
  67.  
  68. push(job) {
  69. this.queue.push(job);
  70. this.process();
  71. }
  72.  
  73. finishCurrent() {
  74. this.current = null;
  75. this.emit('afterRequest');
  76. this.process();
  77. }
  78. }
Add Comment
Please, Sign In to add comment