Skip to content

Commit

Permalink
Merge pull request #152 from jharding/94-improve-transport-logic
Browse files Browse the repository at this point in the history
Improve transport logic (support batch requests)
  • Loading branch information
jharding committed Mar 30, 2013
2 parents 982581b + 122cd92 commit 3a77aea
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 27 deletions.
68 changes: 46 additions & 22 deletions src/transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
*/

var Transport = (function() {
var pendingRequests = 0, maxParallelRequests, requestCache;
var pendingRequestsCount = 0,
pendingRequests = {},
maxPendingRequests,
requestCache;

function Transport(o) {
utils.bindAll(this);
Expand All @@ -15,8 +18,8 @@ var Transport = (function() {
requestCache = requestCache || new RequestCache();

// shared between all instances, last instance to set it wins
maxParallelRequests = utils.isNumber(o.maxParallelRequests) ?
o.maxParallelRequests : maxParallelRequests || 6;
maxPendingRequests = utils.isNumber(o.maxParallelRequests) ?
o.maxParallelRequests : maxPendingRequests || 6;

this.url = o.url;
this.wildcard = o.wildcard || '%QUERY';
Expand All @@ -37,6 +40,32 @@ var Transport = (function() {

utils.mixin(Transport.prototype, {

// private methods
// ---------------

_sendRequest: function(url) {
var that = this, jqXhr = pendingRequests[url];

if (!jqXhr) {
incrementPendingRequests();
jqXhr = pendingRequests[url] =
$.ajax(url, this.ajaxSettings).always(always);
}

return jqXhr;

function always() {
decrementPendingRequests();
pendingRequests[url] = null;

// ensures request is always made for the last query
if (that.onDeckRequestArgs) {
that.get.apply(that, that.onDeckRequestArgs);
that.onDeckRequestArgs = null;
}
}
},

// public methods
// --------------

Expand All @@ -50,36 +79,31 @@ var Transport = (function() {
this.replace(this.url, encodedQuery) :
this.url.replace(this.wildcard, encodedQuery);

// in-memory cache hit
if (resp = requestCache.get(url)) {
cb && cb(resp);
cb && cb(this.filter ? this.filter(resp) : resp);
}

// under the pending request threshold, so fire off a request
else if (belowPendingRequestsThreshold()) {
incrementPendingRequests();
$.ajax(url, this.ajaxSettings).done(done).always(always);
this._sendRequest(url).done(done);
}

// at the pending request threshold, so hang out in the on deck circle
else {
this.onDeckRequestArgs = [].slice.call(arguments, 0);
}

// success callback
function done(resp) {
resp = that.filter ? that.filter(resp) : resp;
var data = that.filter ? that.filter(resp) : resp;

cb && cb(resp);
requestCache.set(url, resp);
}
cb && cb(data);

// comlete callback
function always() {
decrementPendingRequests();

// ensures request is always made for the latest query
if (that.onDeckRequestArgs) {
that.get.apply(that, that.onDeckRequestArgs);
that.onDeckRequestArgs = null;
}
// cache the resp and not the result of applying filter
// in case multiple datasets use the same url and
// have different filters
requestCache.set(url, resp);
}
}
});
Expand All @@ -90,14 +114,14 @@ var Transport = (function() {
// --------------

function incrementPendingRequests() {
pendingRequests++;
pendingRequestsCount++;
}

function decrementPendingRequests() {
pendingRequests--;
pendingRequestsCount--;
}

function belowPendingRequestsThreshold() {
return pendingRequests < maxParallelRequests;
return pendingRequestsCount < maxPendingRequests;
}
})();
31 changes: 26 additions & 5 deletions test/transport_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ describe('Transport', function() {
describe('when request is available in cache', function() {
beforeEach(function() {
this.spy = jasmine.createSpy();
this.requestCache.get.andReturn(successData);
this.requestCache.get.andReturn({ data: ['val'] });

this.transport.filter = jasmine.createSpy().andReturn(['val']);
this.transport.get('query', this.spy);
this.request = mostRecentAjaxRequest();
});
Expand All @@ -55,8 +56,12 @@ describe('Transport', function() {
expect(this.request).toBeNull();
});

it('should invoke callback with response from cache', function() {
expect(this.spy).toHaveBeenCalledWith(successData);
it('should call filter', function() {
expect(this.transport.filter).toHaveBeenCalled();
});

it('should invoke callback with data', function() {
expect(this.spy).toHaveBeenCalledWith(['val']);
});
});

Expand All @@ -80,14 +85,30 @@ describe('Transport', function() {

expect(this.request.url).toEqual('http://example.com?q=$$has%20space');
});

it('should piggyback off of pending requests', function() {
this.spy1 = jasmine.createSpy();
this.spy2 = jasmine.createSpy();
this.transport2 = new Transport({ url: 'http://example.com?q=%QUERY' });

this.transport.get('hazel', this.spy1);
this.transport2.get('hazel', this.spy2);

this.request = mostRecentAjaxRequest();
this.request.response(successResp);

expect(ajaxRequests.length).toBe(1);
expect(this.spy1).toHaveBeenCalledWith(successData);
expect(this.spy2).toHaveBeenCalledWith(successData);
});
});

describe('when at concurrent request threshold', function() {
beforeEach(function() {
this.goodRequests = [];

for (var i = 0; i < 3; i++) {
this.transport.get('good');
this.transport.get('good' + i);
this.goodRequests.push(mostRecentAjaxRequest());
}

Expand Down Expand Up @@ -153,7 +174,7 @@ describe('Transport', function() {
var requests = [];

for (var i = 0; i < 3; i++) {
this.transport.get('good');
this.transport.get('good' + i);
requests.push(mostRecentAjaxRequest());
}

Expand Down

0 comments on commit 3a77aea

Please sign in to comment.