Skip to main content

request/RequestQueueV2.js

  1. var RequestTypes = require("./RequestTypes");
  2. var sendSetRequest = require("./sendSetRequest");
  3. var GetRequest = require("./GetRequestV2");
  4. var falcorPathUtils = require("falcor-path-utils");
  5. /**
  6. * The request queue is responsible for queuing the operations to
  7. * the model"s dataSource.
  8. *
  9. * @param {Model} model -
  10. * @param {Scheduler} scheduler -
  11. */
  12. function RequestQueueV2(model, scheduler) {
  13. this.model = model;
  14. this.scheduler = scheduler;
  15. this.requests = this._requests = [];
  16. }
  17. RequestQueueV2.prototype = {
  18. /**
  19. * Sets the scheduler, but will not affect any current requests.
  20. */
  21. setScheduler: function(scheduler) {
  22. this.scheduler = scheduler;
  23. },
  24. /**
  25. * performs a set against the dataSource. Sets, though are not batched
  26. * currently could be batched potentially in the future. Since no batching
  27. * is required the setRequest action is simplified significantly.
  28. *
  29. * @param {JSONGraphEnvelope} jsonGraph -
  30. * @param {number} attemptCount
  31. * @param {Function} cb
  32. */
  33. set: function(jsonGraph, attemptCount, cb) {
  34. if (this.model._enablePathCollapse) {
  35. jsonGraph.paths = falcorPathUtils.collapse(jsonGraph.paths);
  36. }
  37. if (cb === undefined) {
  38. cb = attemptCount;
  39. attemptCount = undefined;
  40. }
  41. return sendSetRequest(jsonGraph, this.model, attemptCount, cb);
  42. },
  43. /**
  44. * Creates a get request to the dataSource. Depending on the current
  45. * scheduler is how the getRequest will be flushed.
  46. * @param {Array} requestedPaths -
  47. * @param {Array} optimizedPaths -
  48. * @param {number} attemptCount
  49. * @param {Function} cb -
  50. */
  51. get: function(requestedPaths, optimizedPaths, attemptCount, cb) {
  52. var self = this;
  53. var disposables = [];
  54. var count = 0;
  55. var requests = self._requests;
  56. var i, len;
  57. var oRemainingPaths = optimizedPaths;
  58. var rRemainingPaths = requestedPaths;
  59. var disposed = false;
  60. var request;
  61. if (cb === undefined) {
  62. cb = attemptCount;
  63. attemptCount = undefined;
  64. }
  65. for (i = 0, len = requests.length; i < len; ++i) {
  66. request = requests[i];
  67. if (request.type !== RequestTypes.GetRequest) {
  68. continue;
  69. }
  70. // The request has been sent, attempt to jump on the request
  71. // if possible.
  72. if (request.sent) {
  73. if (this.model._enableRequestDeduplication) {
  74. var results = request.add(rRemainingPaths, oRemainingPaths, refCountCallback);
  75. // Checks to see if the results were successfully inserted
  76. // into the outgoing results. Then our paths will be reduced
  77. // to the complement.
  78. if (results[0]) {
  79. rRemainingPaths = results[1];
  80. oRemainingPaths = results[2];
  81. disposables[disposables.length] = results[3];
  82. ++count;
  83. // If there are no more remaining paths then exit the loop.
  84. if (!oRemainingPaths.length) {
  85. break;
  86. }
  87. }
  88. }
  89. }
  90. // If there is an unsent request, then we can batch and leave.
  91. else {
  92. request.batch(rRemainingPaths, oRemainingPaths, refCountCallback);
  93. oRemainingPaths = null;
  94. rRemainingPaths = null;
  95. ++count;
  96. break;
  97. }
  98. }
  99. // After going through all the available requests if there are more
  100. // paths to process then a new request must be made.
  101. if (oRemainingPaths && oRemainingPaths.length) {
  102. request = new GetRequest(self.scheduler, self, attemptCount);
  103. requests[requests.length] = request;
  104. ++count;
  105. var disposable = request.batch(rRemainingPaths, oRemainingPaths, refCountCallback);
  106. disposables[disposables.length] = disposable;
  107. }
  108. // This is a simple refCount callback.
  109. function refCountCallback(err, data, hasInvalidatedResult) {
  110. if (disposed) {
  111. return;
  112. }
  113. --count;
  114. // If the count becomes 0, then its time to notify the
  115. // listener that the request is done.
  116. if (count === 0) {
  117. cb(err, data, hasInvalidatedResult);
  118. }
  119. }
  120. // When disposing the request all of the outbound requests will be
  121. // disposed of.
  122. return function() {
  123. if (disposed || count === 0) {
  124. return;
  125. }
  126. disposed = true;
  127. var length = disposables.length;
  128. for (var idx = 0; idx < length; ++idx) {
  129. disposables[idx]();
  130. }
  131. };
  132. },
  133. /**
  134. * Removes the request from the request queue.
  135. */
  136. removeRequest: function(request) {
  137. var requests = this._requests;
  138. var i = requests.length;
  139. while (--i >= 0) {
  140. if (requests[i].id === request.id) {
  141. requests.splice(i, 1);
  142. break;
  143. }
  144. }
  145. }
  146. };
  147. module.exports = RequestQueueV2;