-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(core): Wrong ignore of source libraries
- Loading branch information
Showing
3 changed files
with
168 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,7 +66,6 @@ typings/ | |
|
||
dist/ | ||
bin/ | ||
lib/ | ||
docs/ | ||
.coveralls.yml | ||
tags | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { findWith, last, is, isEmpty } from "@asd14/m" | ||
import isDeepEqual from "fast-deep-equal" | ||
|
||
/** | ||
* Unique, sequential, promise based queue | ||
* | ||
* @example | ||
* const queue = buildQueue() | ||
* | ||
* queue.enqueue(Users.login, { | ||
* args:{ | ||
* body: {email: "[email protected]", password: "secret"} | ||
* } | ||
* }) | ||
* .then(...) | ||
* .catch(...) | ||
* | ||
* @returns {object<enqueue, dequeue>} | ||
*/ | ||
export const buildQueue = () => { | ||
const jobsList = [] | ||
let isProcessing = false | ||
|
||
return { | ||
enqueue({ id, fn, args }) { | ||
const runningJob = findWith({ | ||
id, | ||
args: source => isDeepEqual(source, args), | ||
})(jobsList) | ||
|
||
if (is(runningJob)) { | ||
return runningJob.fnPromise | ||
} | ||
|
||
let deferredResolve = null | ||
let deferredReject = null | ||
const fnResultPromise = new Promise((resolve, reject) => { | ||
deferredResolve = resolve | ||
deferredReject = reject | ||
}) | ||
|
||
// add job at begining of queue | ||
jobsList.unshift({ | ||
id, | ||
args, | ||
fn, | ||
fnResultPromise, | ||
onResolve: results => { | ||
deferredResolve(results) | ||
}, | ||
onReject: error => { | ||
deferredReject(error) | ||
}, | ||
}) | ||
|
||
// start processing jobs | ||
this.dequeue() | ||
|
||
// return promise that will be resolved after fn is called and resolved | ||
return fnResultPromise | ||
}, | ||
|
||
dequeue() { | ||
const shouldStartRunningJobs = !isProcessing && !isEmpty(jobsList) | ||
|
||
if (!shouldStartRunningJobs) { | ||
return undefined | ||
} | ||
|
||
const { fn, args, onResolve, onReject } = last(jobsList) | ||
|
||
// no jobs will be started until current one finishes | ||
isProcessing = true | ||
|
||
return Promise.resolve() | ||
.then(() => { | ||
// Need to remove ourselves before job.fn resolves. If another | ||
// action of the same signature runs right after it will return this | ||
// job because job still exists in queue | ||
jobsList.pop() | ||
|
||
return fn(...args) | ||
}) | ||
.then(onResolve) | ||
.catch(onReject) | ||
.finally(() => { | ||
// process next in queue | ||
isProcessing = false | ||
this.dequeue() | ||
}) | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* eslint-disable no-loop-func */ | ||
import test from "tape" | ||
import { map } from "@asd14/m" | ||
|
||
import { buildQueue } from "./queue" | ||
|
||
test("Promise Queue - Promise based unique elements queue", t => { | ||
const queue = buildQueue() | ||
|
||
let findCountBatch1 = 0 | ||
let findDateBatch1 = null | ||
let findCountBatch2 = 0 | ||
let findDateBatch2 = null | ||
|
||
const jobs = [ | ||
// add job with same arguments | ||
...map(() => | ||
queue.enqueue({ | ||
fn: () => { | ||
findCountBatch1++ | ||
findDateBatch1 = new Date() | ||
|
||
return new Promise(resolve => { | ||
setTimeout(() => { | ||
resolve([{ id: 1, name: "test" }]) | ||
}, 100) | ||
}) | ||
}, | ||
args: [ | ||
{ | ||
path: "/todos", | ||
query: { limit: 10 }, | ||
}, | ||
], | ||
}) | ||
)([1, 2, 3, 4, 5]), | ||
// add job with different arguments | ||
...map(() => | ||
queue.enqueue({ | ||
fn: () => { | ||
findCountBatch2++ | ||
findDateBatch2 = new Date() | ||
|
||
return new Promise(resolve => { | ||
setTimeout(() => { | ||
resolve([{ id: 1, name: "test" }]) | ||
}, 100) | ||
}) | ||
}, | ||
args: [ | ||
{ | ||
path: "/todos", | ||
query: { limit: 20 }, | ||
}, | ||
], | ||
}) | ||
)([1, 2, 3, 4, 5]), | ||
] | ||
|
||
Promise.all(jobs).then(() => { | ||
t.equals( | ||
findCountBatch1 === 1 && findCountBatch2 === 1, | ||
true, | ||
"Same signature jobs enqueued at the same times should run once" | ||
) | ||
|
||
t.equals( | ||
findDateBatch1 < findDateBatch2, | ||
true, | ||
"Different signature jobs should run sequentially" | ||
) | ||
|
||
t.end() | ||
}) | ||
}) |