Skip to content

Commit

Permalink
feat(core): unmanaged handlers after resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
wdavidw committed Mar 16, 2021
1 parent cb0127f commit 0f98f59
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 33 deletions.
35 changes: 30 additions & 5 deletions packages/core/lib/schedulers/native.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 26 additions & 4 deletions packages/core/src/schedulers/native.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ utils = require '../utils'

module.exports = (handlers, options = {}) ->
scheduler = null
# Managed handlers are resolved with the scheduler
# Managed handlers are resolved inside the scheduler promise. The promise
# fullfil with an array which length is the number of managed handlers.
# It is possible to defined `managed` globally for every handler and
# individually for each handler when calling `push` or `unshift`.
# By default, handlers passed in the scheduler creation are managed while
# handler pushed or unshifted are not.
# It is not possible to register managed handler once the scheduler has
# resolved.
options.managed ?= false
options.parallel ?= 1
state =
Expand All @@ -14,6 +21,13 @@ module.exports = (handlers, options = {}) ->
output: []
resolved: false
running: 0
has_pending_tasks = ->
pending = state.stack.some (task) ->
task.options.managed
pending
clear_managed_tasks = ->
state.stack = state.stack.filter (task) ->
not task.options.managed
promise = new Promise (resolve, reject) ->
scheduler =
state: state
Expand All @@ -23,20 +37,28 @@ module.exports = (handlers, options = {}) ->
unless state.resolved
if state.error
state.resolved = true
# Any pending managed task is stripped out after an error
clear_managed_tasks()
scheduler.pump()
return reject state.error
else unless state.stack.length
else unless has_pending_tasks()
state.resolved = true
scheduler.pump()
return resolve state.output
return unless state.stack.length
state.running++
item = state.stack.shift()
item = item
# A managed handler cannot be scheduled once the scheduler resolves
if item.options.managed and state.resolved
throw utils.error 'SCHEDULER_RESOLVED', [
'cannot execute a new handler,'
'scheduler already in resolved state.'
]
setImmediate ->
try
result = await item.handler.call()
state.running--
item.resolve.call null, result
# console.log options.managed, item.options.managed
state.output.push result if item.options.managed
setImmediate scheduler.pump
catch error
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/scheduler/creation.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{tags} = require '../test'
schedule = require '../../src/schedulers/native'

describe 'scheduler.instance', ->
describe 'scheduler.creation', ->
return unless tags.api

describe 'usage', ->
Expand Down
82 changes: 76 additions & 6 deletions packages/core/test/scheduler/options.managed.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{tags} = require '../test'
schedule = require '../../src/schedulers/native'

describe 'scheduler.flow options.flow', ->
describe 'scheduler.options.managed', ->
return unless tags.api

describe '`false`, default', ->
Expand Down Expand Up @@ -42,11 +42,11 @@ describe 'scheduler.flow options.flow', ->
.should.be.resolved()
.then -> stack.should.eql [1, 2, 'catchme']

describe 'push is not managed by default', ->
describe 'managed scheduler', ->

describe '`true`', ->
describe 'push managed handler', ->

it 'stop on first error', ->
it 'scheduler stop on first rejected error', ->
stack = []
scheduler = schedule(null, managed: true)
scheduler.push -> new Promise (resolve) ->
Expand All @@ -62,7 +62,7 @@ describe 'scheduler.flow options.flow', ->
.should.be.rejectedWith 'catchme'
.then -> stack.should.eql [1, 2]

it 'push synchronously', ->
it 'scheduler stop on first thrown error', ->
stack = []
scheduler = schedule(null, managed: true)
scheduler.push ->
Expand All @@ -78,7 +78,7 @@ describe 'scheduler.flow options.flow', ->
.should.be.rejectedWith 'catchme'
.then -> stack.should.eql [1, 2]

it 'push array', ->
it 'scheduler stop when an array reject an error', ->
stack = []
scheduler = schedule(null, managed: true)
scheduler.push [
Expand All @@ -94,4 +94,74 @@ describe 'scheduler.flow options.flow', ->
]
.should.be.rejectedWith 'catchme'
.then -> stack.should.eql [1, 2]

it 'dont accept handler once fulfilled', ->
scheduler = schedule(null, managed: true)
scheduler.push -> new Promise (resolve) ->
resolve()
scheduler
.then ->
scheduler.push (->)
.should.be.rejectedWith
code: 'SCHEDULER_RESOLVED'
message: [
'SCHEDULER_RESOLVED:'
'cannot execute a new handler,'
'scheduler already in resolved state.'
].join ' '

it 'dont accept handler once rejected', ->
scheduler = schedule(null, managed: true)
scheduler.push -> new Promise (, reject) ->
reject()
scheduler
.catch ->
scheduler.push (->)
.should.be.rejectedWith
code: 'SCHEDULER_RESOLVED'
message: [
'SCHEDULER_RESOLVED:'
'cannot execute a new handler,'
'scheduler already in resolved state.'
].join ' '

describe 'push unmanaged handler', ->

it 'are called but not returnd', ->
stack = []
scheduler = schedule(null, managed: true)
scheduler.push -> new Promise (resolve) ->
stack.push 1
resolve 1
scheduler.push -> new Promise (resolve, reject) ->
stack.push 2
resolve 2
handler = scheduler.push (-> new Promise (resolve) ->
resolve [...stack, 3]
),
managed: false
scheduler
.should.be.resolvedWith [1, 2]
.then ->
handler
.should.be.resolvedWith [1, 2, 3]

it 'are called after an error', ->
stack = []
scheduler = schedule(null, managed: true)
scheduler.push -> new Promise (resolve) ->
stack.push 1
resolve 1
scheduler.push -> new Promise (resolve, reject) ->
stack.push 2
reject Error stack.join ','
prom = scheduler.push (-> new Promise (resolve) ->
stack.push 3
resolve [...stack, 3]
),
managed: false
scheduler
.should.be.rejectedWith '1,2'
.catch ->
prom.should.be.resolvedWith [1, 2, 3]

6 changes: 3 additions & 3 deletions packages/core/test/scheduler/pause.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{tags} = require '../test'
schedule = require '../../src/schedulers/native'

describe 'scheduler.flow', ->
describe 'scheduler.pause', ->
return unless tags.api

it 'pause in options', ->
Expand All @@ -27,11 +27,11 @@ describe 'scheduler.flow', ->
stack.push 1
resolve 1
scheduler.pause()
prom1 = scheduler.push -> new Promise (resolve) ->
prom2 = scheduler.push -> new Promise (resolve) ->
stack.push 2
resolve 2
setTimeout ->
scheduler.state.stack.length.should.eql 1
scheduler.resume()
, 50
scheduler
Promise.all [prom1, prom2]
22 changes: 11 additions & 11 deletions packages/core/test/scheduler/promise.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{tags} = require '../test'
schedule = require '../../src/schedulers/native'

describe 'scheduler.instance.promise', ->
describe 'scheduler.promise', ->
return unless tags.api

describe 'instantiate handlers with error', ->
Expand All @@ -13,21 +13,21 @@ describe 'scheduler.instance.promise', ->
->
stack.push 1
true
,
->
stack.push 2
throw Error 'catchme'
,
->
stack.push 3
true
]
,
->
stack.push 2
throw Error 'catchme'
,
->
stack.push 3
true
]
.should.be.rejectedWith 'catchme'
.then -> stack.should.eql [1, 2]

it 'asynchronously', ->
stack = []
scheduler = schedule [
schedule [
->
stack.push 1
true
Expand Down
6 changes: 3 additions & 3 deletions packages/core/test/scheduler/push.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ describe 'scheduler.push', ->

it 'run asynchronously', ->
stack = []
scheduler = schedule()
scheduler.push ->
scheduler = schedule(null)
task = scheduler.push ->
stack.push 2
new Promise (accept, reject) ->
accept()
stack.push 1
scheduler.then ->
task.then ->
stack.should.eql [1, 2]

describe 'push parallel error', ->
Expand Down

0 comments on commit 0f98f59

Please sign in to comment.