Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#17 Modified reclaim to run on original engine with tests #21

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Queue.prototype._checkReclaim = function() {

function findOtherQueues(name) {
var res = [];
var storage = self._store.engine;
var storage = self._store.getOriginalEngine();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: One of the scenarios that triggers a switch to the in memory engine is a failure to getItem from localStorage, for example if a user has blocked localStorage access to a particular domain.
In this scenario how do we handle failures to get the reclaim and ack etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getItem just returns null if there is an error (ref). The check to see if we can get items from localStorage happens inside of the engine (ref).

This means that if the user has blocked localStorage, the initial defaultEngine will be inMemory. This will mean that this code path will work as expected.

for (var i = 0; i < storage.length; i++) {
var k = storage.key(i);
var parts = k.split('.');
Expand Down
9 changes: 9 additions & 0 deletions lib/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function Store(name, id, keys, optionalEngine) {
this.name = name;
this.keys = keys || {};
this.engine = optionalEngine || defaultEngine;
this.originalEngine = this.engine;
}

/**
Expand Down Expand Up @@ -52,6 +53,14 @@ Store.prototype.get = function(key) {
}
};

/**
* Get original engine
*/

Store.prototype.getOriginalEngine = function() {
return this.originalEngine;
};

/**
* Remove by Key.
*/
Expand Down
91 changes: 91 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,97 @@ describe('Queue', function() {
assert(queue.fn.calledWith('b'));
});

describe('while using in memory engine', function() {
beforeEach(function() {
queue._store._swapEngine();
});

it('should take over a queued task if a queue is abandoned', function() {
// a wild queue of interest appears
var foundQueue = new Store('test', 'fake-id', queue.keys);
foundQueue.set(foundQueue.keys.ACK, 0); // fake timers starts at time 0
foundQueue.set(foundQueue.keys.QUEUE, [{
item: 'a',
time: 0,
attemptNumber: 0
}]);

// wait for the queue to expire
clock.tick(queue.timeouts.RECLAIM_TIMEOUT);

queue.start();

// wait long enough for the other queue to expire and be reclaimed
clock.tick(
queue.timeouts.RECLAIM_TIMER
+ queue.timeouts.RECLAIM_WAIT * 2
);

assert(queue.fn.calledOnce);
assert(queue.fn.calledWith('a'));
});

it('should take over an in-progress task if a queue is abandoned', function() {
// set up a fake queue
var foundQueue = new Store('test', 'fake-id', queue.keys);
foundQueue.set(foundQueue.keys.ACK, -15000);
foundQueue.set(foundQueue.keys.IN_PROGRESS, {
'task-id': {
item: 'a',
time: 0,
attemptNumber: 0
}
});

// wait for the queue to expire
clock.tick(queue.timeouts.RECLAIM_TIMEOUT);

queue.start();

// wait long enough for the other queue to expire and be reclaimed
clock.tick(
queue.timeouts.RECLAIM_TIMER
+ queue.timeouts.RECLAIM_WAIT * 2
);

assert(queue.fn.calledOnce);
assert(queue.fn.calledWith('a'));
});

it('should take over multiple tasks if a queue is abandoned', function() {
// set up a fake queue
var foundQueue = new Store('test', 'fake-id', queue.keys);
foundQueue.set(foundQueue.keys.ACK, -15000);
foundQueue.set(foundQueue.keys.QUEUE, [{
item: 'a',
time: 0,
attemptNumber: 0
}]);
foundQueue.set(foundQueue.keys.IN_PROGRESS, {
'task-id': {
item: 'b',
time: 1,
attemptNumber: 0
}
});

// wait for the queue to expire
clock.tick(queue.timeouts.RECLAIM_TIMEOUT);

queue.start();

// wait long enough for the other queue to expire and be reclaimed
clock.tick(
queue.timeouts.RECLAIM_TIMER
+ queue.timeouts.RECLAIM_WAIT * 2
);

assert(queue.fn.calledTwice);
assert(queue.fn.calledWith('a'));
assert(queue.fn.calledWith('b'));
});
});

it('should respect maxAttempts when rejected', function() {
var calls = new Array(100);

Expand Down
6 changes: 6 additions & 0 deletions test/store.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ describe('Store', function() {
assert.strictEqual(store.engine, inMemoryEngine);
});

it('should not switch the original storage mechanism', function() {
assert.strictEqual(store.getOriginalEngine(), engine);
store._swapEngine();
assert.strictEqual(store.getOriginalEngine(), engine);
});

it('should swap upon quotaExceeded on set', function() {
var lsProxy = {
length: window.localStorage.length,
Expand Down