urbit/pkg/arvo/sys/vane/behn.hoon

318 lines
8.3 KiB
Plaintext
Raw Normal View History

:: %behn, just a timer
!:
2016-11-24 07:25:07 +03:00
!? 164
::
=, behn
2020-12-06 11:38:37 +03:00
|= our=ship
=> |%
2020-12-08 03:47:06 +03:00
+$ move [p=duct q=(wite note gift)]
+$ note :: out request $->
$~ [%b %wait *@da] ::
$% $: %b :: to self
2020-12-08 03:47:06 +03:00
$>(%wait task) :: set timer
== ::
$: %d :: to %dill
2020-12-08 03:47:06 +03:00
$>(%flog task:dill) :: log output
== == ::
+$ sign
2020-12-08 03:22:26 +03:00
$~ [%behn %wake ~]
$% [%behn $>(%wake gift)]
==
::
+$ behn-state
2020-05-27 09:59:07 +03:00
$: %2
timers=(tree [key=@da val=(qeu duct)])
unix-duct=duct
next-wake=(unit @da)
2019-05-01 00:58:51 +03:00
drips=drip-manager
==
::
2020-05-27 09:59:07 +03:00
++ timer-map ((ordered-map ,@da ,(qeu duct)) lte)
2020-05-20 07:40:39 +03:00
::
2019-05-01 00:58:51 +03:00
+$ drip-manager
$: count=@ud
movs=(map @ud vase)
==
::
+$ timer [date=@da =duct]
--
2016-11-24 07:25:07 +03:00
::
=>
~% %behn ..part ~
|%
2019-01-30 04:15:54 +03:00
++ per-event
=| moves=(list move)
2020-12-06 11:38:37 +03:00
|= [[now=@da =duct] state=behn-state]
2018-12-03 22:45:50 +03:00
::
2019-01-30 04:15:54 +03:00
|%
::
2022-06-17 09:11:49 +03:00
+| %helpers
2019-01-30 04:15:54 +03:00
::
2022-06-17 09:11:49 +03:00
++ this .
++ emit |=(m=move this(moves [m moves]))
++ abet
2019-01-30 04:15:54 +03:00
^+ [moves state]
2022-06-17 09:11:49 +03:00
:: moves are statefully pre-flopped to ensure that
:: any prepended %doze is emitted first
::
2022-06-17 09:11:49 +03:00
=. moves (flop moves)
=/ new=(unit @da) (bind (pry:timer-map timers.state) head)
:: emit %doze if needed
::
2022-06-17 09:11:49 +03:00
=? ..this
?~ unix-duct.state |
=/ dif=[old=(unit @da) new=(unit @da)] [next-wake.state new]
?+ dif ~|([%unpossible dif] !!)
[~ ~] | :: no-op
[~ ^] & :: set
[^ ~] & :: clear
[^ ^] !=(u.old.dif u.new.dif) :: set if changed
==
(emit(next-wake.state new) [unix-duct.state %give %doze new])
::
2022-06-17 09:11:49 +03:00
[moves state]
::
2022-06-17 09:11:49 +03:00
+| %entry-points
::
2022-06-17 09:11:49 +03:00
++ call
|= [=task error=(unit tang)]
^+ this
?: ?& ?=(^ error)
!?=(%wake -.task)
==
:: XX more and better error handling
::
~& %behn-crud-not-wake^-.task
(emit [duct %slip %d %flog %crud -.task u.error])
::
?- -.task
%born this(next-wake.state ~, unix-duct.state duct)
%drip (drip p.task)
%huck (emit [duct %give %heck syn.task])
%rest this(timers.state (unset-timer [p.task duct]))
%trim this
%vega this
%wait this(timers.state (set-timer [p.task duct]))
%wake (wake(next-wake.state ~) error)
==
2019-05-01 00:58:51 +03:00
::
2022-06-18 05:20:16 +03:00
:: +take-drip: the future is now, %give the deferred move
2019-05-01 00:58:51 +03:00
::
++ take-drip
|= [num=@ud error=(unit tang)]
2022-06-17 09:11:49 +03:00
^+ this
2019-05-01 00:58:51 +03:00
=/ drip (~(got by movs.drips.state) num)
2022-06-17 09:11:49 +03:00
%- emit(movs.drips.state (~(del by movs.drips.state) num))
=/ card [%give %meta drip]
?~ error
[duct card]
=/ =tang
(weld u.error `tang`[leaf/"drip failed" ~])
:: XX should be
:: [duct %hurl fail/tang card]
::
[duct %pass /drip-slog %d %flog %crud %drip-fail tang]
::
+| %tasks
::
2022-06-18 05:20:16 +03:00
:: +drip: enqueue a future gift (as a vase), %pass ourselves a %wait
2022-06-17 09:11:49 +03:00
::
++ drip
|= vax=vase
^+ this
%. [duct %pass /drip/(scot %ud count.drips.state) %b %wait +(now)]
%= emit
movs.drips.state (~(put by movs.drips.state) count.drips.state vax)
count.drips.state +(count.drips.state)
==
::
2022-06-18 05:20:16 +03:00
:: +wake: unix says wake up; process the elapsed timer (or forward error)
2019-01-30 04:15:54 +03:00
::
++ wake
|= error=(unit tang)
2022-06-17 09:11:49 +03:00
^+ this
2020-05-20 07:40:39 +03:00
?: =(~ timers.state)
2022-06-17 09:11:49 +03:00
:: no-op on spurious but innocuous unix wakeups
::
2019-07-31 02:11:19 +03:00
~? ?=(^ error) %behn-wake-no-timer^u.error
2022-06-17 09:11:49 +03:00
this
2020-05-27 09:59:07 +03:00
=/ [=timer later-timers=_timers.state] pop-timer
2020-05-20 07:40:39 +03:00
?: (gth date.timer now)
2022-06-17 09:11:49 +03:00
:: no-op if timer is early, (+abet will reset)
::
this
:: pop the first timer and notify client vane,
:: forwarding error if present
2019-02-12 02:34:08 +03:00
::
2022-06-18 05:20:16 +03:00
:: XX %wake errors should be signaled out-of-band
:: [duct.timer %hurl goof %give %wake ~]
::
2022-06-17 09:11:49 +03:00
(emit(timers.state later-timers) [duct.timer %give %wake error])
::
2022-06-17 09:11:49 +03:00
+| %implementation
::
2020-05-27 09:59:07 +03:00
:: +pop-timer: dequeue and produce earliest timer
::
++ pop-timer
^+ [*timer timers.state]
=^ [date=@da dux=(qeu ^duct)] timers.state (pop:timer-map timers.state)
=^ dut dux ~(get to dux)
:- [date dut]
?: =(~ dux)
timers.state
2020-05-27 09:59:07 +03:00
(put:timer-map timers.state date dux)
:: +set-timer: set a timer, maintaining order
2019-01-30 04:15:54 +03:00
::
++ set-timer
~% %set-timer ..part ~
2019-01-30 04:15:54 +03:00
|= t=timer
2020-05-20 07:40:39 +03:00
^+ timers.state
2020-05-27 09:59:07 +03:00
=/ found (find-ducts date.t)
(put:timer-map timers.state date.t (~(put to found) duct.t))
:: +find-ducts: get timers at date
::
:: TODO: move to +ordered-map
::
++ find-ducts
|= date=@da
^- (qeu ^duct)
?~ timers.state ~
?: =(date key.n.timers.state)
val.n.timers.state
?: (lte date key.n.timers.state)
$(timers.state l.timers.state)
$(timers.state r.timers.state)
2019-01-30 04:15:54 +03:00
:: +unset-timer: cancel a timer; if it already expired, no-op
::
++ unset-timer
2019-02-12 02:34:08 +03:00
|= t=timer
2020-05-20 07:40:39 +03:00
^+ timers.state
2020-05-27 09:59:07 +03:00
=/ [found=? dux=(qeu ^duct)]
=/ dux (find-ducts date.t)
|- ^- [found=? dux=(qeu ^duct)]
?~ dux |+~
?: =(duct.t n.dux) &+~(nip to `(qeu ^duct)`dux)
=^ found-left=? l.dux $(dux l.dux)
2020-05-27 09:59:07 +03:00
?: found-left &+dux
=^ found-rite=? r.dux $(dux r.dux)
[found-rite dux]
2020-05-27 09:59:07 +03:00
?. found timers.state
?: =(~ dux)
+:(del:timer-map timers.state date.t)
(put:timer-map timers.state date.t dux)
--
2019-01-30 04:15:54 +03:00
--
::
=| behn-state
=* state -
2020-12-06 11:38:37 +03:00
|= [now=@da eny=@uvJ rof=roof]
2019-01-30 04:15:54 +03:00
=* behn-gate .
^?
|%
2020-12-08 03:47:06 +03:00
:: +call: handle a +task:behn request
2019-01-30 04:15:54 +03:00
::
++ call
~% %behn-call ..part ~
2019-01-30 04:15:54 +03:00
|= $: hen=duct
2020-02-11 01:03:03 +03:00
dud=(unit goof)
2020-12-08 03:47:06 +03:00
wrapped-task=(hobo task)
2019-01-30 04:15:54 +03:00
==
^- [(list move) _behn-gate]
2020-12-08 03:47:06 +03:00
=/ =task ((harden task) wrapped-task)
2020-12-06 11:38:37 +03:00
=/ event-core (per-event [now hen] state)
2019-01-30 04:15:54 +03:00
=^ moves state
2022-06-17 09:11:49 +03:00
abet:(call:event-core task ?~(dud ~ `tang.u.dud))
2019-01-30 04:15:54 +03:00
[moves behn-gate]
:: +load: migrate an old state to a new behn version
2016-11-24 07:25:07 +03:00
::
++ load
|= old=behn-state
2019-01-30 04:15:54 +03:00
^+ behn-gate
2019-08-01 21:37:28 +03:00
behn-gate(state old)
:: +scry: view timer state
::
:: TODO: not referentially transparent w.r.t. elapsed timers,
:: which might or might not show up in the product
2016-11-24 07:25:07 +03:00
::
++ scry
2020-12-08 00:52:12 +03:00
^- roon
|= [lyc=gang car=term bem=beam]
2016-11-24 07:25:07 +03:00
^- (unit (unit cage))
2020-12-08 00:52:12 +03:00
=* ren car
2020-11-24 00:06:50 +03:00
=* why=shop &/p.bem
=* syd q.bem
=* lot=coin $/r.bem
=* tyl s.bem
::
::TODO don't special-case whey scry
::
2020-05-07 11:51:08 +03:00
?: &(=(ren %$) =(tyl /whey))
=/ maz=(list mass)
:~ timers+&+timers.state
==
``mass+!>(maz)
:: only respond for the local identity, %$ desk, current timestamp
::
?. ?& =(&+our why)
=([%$ %da now] lot)
=(%$ syd)
==
~
:: /bx/debug/timers (list [@da duct]) all timers and their ducts
:: /bx/timers (list @da) all timer timestamps
:: /bx/timers/next (unit @da) the very next timer to fire
:: /bx/timers/[da] (list @da) all timers up to and including da
::
?. ?=(%x ren) ~
?+ tyl [~ ~]
[%debug %timers ~]
:^ ~ ~ %noun
!> ^- (list [@da duct])
2020-05-27 09:59:07 +03:00
%- zing
%+ turn (tap:timer-map timers)
|= [date=@da q=(qeu duct)]
%+ turn ~(tap to q)
|=(d=duct [date d])
::
[%timers ~]
:^ ~ ~ %noun
!> ^- (list @da)
%- zing
%+ turn (tap:timer-map timers)
|= [date=@da q=(qeu duct)]
(reap ~(wyt in q) date)
::
[%timers %next ~]
:^ ~ ~ %noun
!> ^- (unit @da)
(bind (pry:timer-map timers) head)
::
[%timers @ ~]
?~ til=(slaw %da i.t.tyl)
[~ ~]
:^ ~ ~ %noun
!> ^- (list @da)
2020-06-25 20:25:44 +03:00
=/ tiz=(list [date=@da q=(qeu duct)])
(tap:timer-map timers)
|- ^- (list @da)
?~ tiz ~
?: (gth date.i.tiz u.til) ~
%+ weld
(reap ~(wyt in q.i.tiz) date.i.tiz)
$(tiz t.tiz)
==
2016-11-24 07:25:07 +03:00
::
++ stay state
2019-01-30 04:15:54 +03:00
++ take
2020-12-06 11:38:37 +03:00
|= [tea=wire hen=duct dud=(unit goof) hin=sign]
2019-01-30 04:15:54 +03:00
^- [(list move) _behn-gate]
?^ dud
~|(%behn-take-dud (mean tang.u.dud))
::
2019-05-01 00:58:51 +03:00
?> ?=([%drip @ ~] tea)
2020-12-06 11:38:37 +03:00
=/ event-core (per-event [now hen] state)
2019-05-01 00:58:51 +03:00
=^ moves state
2022-06-17 09:11:49 +03:00
abet:(take-drip:event-core (slav %ud i.t.tea) error.hin)
2019-05-01 00:58:51 +03:00
[moves behn-gate]
2016-11-24 07:25:07 +03:00
--