Add a fora test case.

This adds three test cases and fixes which exercise what we think is
going wrong in the "five-oh-fora" situation.
This commit is contained in:
Elliot Glaysher 2018-04-17 14:14:13 -07:00
parent ee18157026
commit 4a62502074
2 changed files with 600 additions and 162 deletions

View File

@ -21,11 +21,14 @@
test-pinned-in-live
test-live-build-that-blocks
test-live-and-once
test-live-two-deep
test-slim
test-ride
test-ride-scry-succeed
test-ride-scry-fail
test-ride-scry-block
test-ride-scry-promote
test-five-oh-fora
==
++ test-is-schematic-live
~& %test-is-schematic-live
@ -529,6 +532,63 @@
:- state-by-ship.+>+<.ford
(my [~nul *ford-state:ford-turbo]~)
::
++ test-live-two-deep
~& %test-live-two-deep
::
=/ scry-42 (scry-succeed ~1234.5.6 [%noun !>(42)])
=/ scry-43 (scry-succeed ~1234.5.7 [%noun !>(43)])
::
=/ ford (ford-turbo now=~1234.5.6 eny=0xdead.beef scry=scry-42)
::
=^ moves ford
%- call:ford
:* duct=~ type=~ %make ~nul
[%same [%scry %c care=%x rail=[[~nul %desk] /bar/foo]]]
==
%+ welp
%- expect-eq !>
:- moves
:~ :* duct=~ %give %made ~1234.5.6 %complete %result
%same %result [%scry %noun !>(42)]
==
:* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk
`[%mult [%da ~1234.5.6] (sy [%x /foo/bar]~)]
== ==
::
=. ford (ford now=~1234.5.7 eny=0xbeef.dead scry=scry-43)
=^ moves2 ford
%- take:ford
:* wire=/~nul/clay-sub/~nul/desk duct=~
^= wrapped-sign ^- (hypo sign:ford) :- *type
[%c %wris [%da ~1234.5.7] (sy [%x /foo/bar]~)]
==
%+ welp
%- expect-eq !>
:- moves2
:~ :* duct=~ %give %made ~1234.5.7 %complete %result
%same %result [%scry %noun !>(43)]
==
:* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk
`[%mult [%da ~1234.5.7] (sy [%x /foo/bar]~)]
== ==
::
=. ford (ford now=~1234.5.8 eny=0xbeef.dead scry=scry-is-forbidden)
=^ moves3 ford
(call:ford [duct=~ type=~ %kill ~nul])
::
%+ welp
%- expect-eq !>
:- moves3
:~ :* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk ~
== ==
::
%- expect-eq !>
:- state-by-ship.+>+<.ford
(my [~nul *ford-state:ford-turbo]~)
::
++ test-slim
~& %test-slim
::
@ -711,10 +771,238 @@
:- state-by-ship.+>+<.ford
(my [~nul *ford-state:ford-turbo]~)
::
++ test-ride-scry-promote
~& %test-ride-scry-promote
::
=/ scry-type=type [%atom %tas ~]
::
=/ scry-results=(map [term beam] cage)
%- my :~
:- [%cx [[~nul %desk %da ~1234.5.6] /bar/foo]]
[%noun scry-type %it-doesnt-matter]
::
:- [%cx [[~nul %desk %da ~1234.5.7] /bar/foo]]
[%noun scry-type %changed]
==
::
=/ scry (scry-with-results scry-results)
=/ ford (ford-turbo now=~1234.5.6 eny=0xdead.beef scry=scry)
::
=/ formula=hoon (ream '`@tas`%constant')
=/ subject-schematic=schematic:ford [%scry %c %x [~nul %desk] /bar/foo]
::
=/ ride=schematic:ford [%ride formula subject-schematic]
::
=^ moves ford (call:ford [duct=~[/ride] type=~ %make ~nul ride])
::
%+ welp
%- expect-eq !>
:- moves
:~ :* duct=~[/ride] %give %made ~1234.5.6 %complete
[%result [%ride scry-type %constant]]
==
:* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk
`[%mult [%da ~1234.5.6] (sy [%x /foo/bar] ~)]
== ==
::
=. ford (ford now=~1234.5.7 eny=0xbeef.dead scry=scry)
::
=^ moves2 ford
%- take:ford
:* wire=/~nul/clay-sub/~nul/desk duct=~
^= wrapped-sign ^- (hypo sign:ford) :- *type
[%c %wris [%da ~1234.5.7] (sy [%x /foo/bar]~)]
==
::
%+ welp
%- expect-eq !>
:- moves2
:~ :* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk
`[%mult [%da ~1234.5.7] (sy [%x /foo/bar] ~)]
== ==
::
=. ford (ford now=~1234.5.8 eny=0xbeef.dead scry=scry-is-forbidden)
=^ moves3 ford
(call:ford [duct=~[/ride] type=~ %kill ~nul])
::
%+ welp
%- expect-eq !>
:- moves3
:~ :* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk ~
== ==
::
%- expect-eq !>
:- state-by-ship.+>+<.ford
(my [~nul *ford-state:ford-turbo]~)
::
++ test-five-oh-fora
~& %test-five-oh-fora
::
=/ scry-results=(map [term beam] cage)
%- my :~
:- [%cx [[~nul %desk %da ~1234.5.6] /a/posts]]
[%noun !>([title='post-a' contents="post-a-contents"])]
::
:- [%cx [[~nul %desk %da ~1234.5.6] /b/posts]]
[%noun !>([title='post-b' contents="post-b-contents"])]
::
:- [%cx [[~nul %desk %da ~1234.5.8] /a/posts]]
[%noun !>([title='post-a' contents="post-a-contents-changed"])]
==
::
=/ scry (scry-with-results scry-results)
=/ ford (ford-turbo now=~1234.5.6 eny=0xdead.beef scry=scry)
::
=/ post-a=schematic:ford [%scry [%c %x [~nul %desk] /a/posts]]
=/ title-a=schematic:ford [%ride (ream '!: title') post-a]
::
=/ post-b=schematic:ford [%scry [%c %x [~nul %desk] /b/posts]]
=/ title-b=schematic:ford [%ride (ream '!: title') post-b]
::
=/ sidebar=schematic:ford [title-a title-b]
::
=/ rendered-a=schematic:ford [post-a sidebar]
=/ rendered-b=schematic:ford [post-b sidebar]
:: first, ask ford to build rendered-a
::
=^ moves ford (call:ford [duct=~[/post-a] type=~ %make ~nul rendered-a])
::
?> ?=([^ ^ ~] moves)
%+ welp
%- check-post-made :*
move=i.moves
duct=~[/post-a]
date=~1234.5.6
title='post-a'
contents="post-a-contents"
==
%+ welp
%- expect-eq !>
:- i.t.moves
:* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk
`[%mult [%da ~1234.5.6] (sy [%x /posts/a] [%x /posts/b] ~)]
==
::
=. ford (ford now=~1234.5.7 eny=0xbeef.dead scry=scry)
::
=^ moves2 ford (call:ford [duct=~[/post-b] type=~ %make ~nul rendered-b])
::
?> ?=([^ ~] moves2)
%+ welp
%- check-post-made :*
move=i.moves2
duct=~[/post-b]
date=~1234.5.7
title='post-b'
contents="post-b-contents"
==
::
=. ford (ford now=~1234.5.8 eny=0xbeef.dead scry=scry)
::
=^ moves3 ford
%- take:ford
:* wire=/~nul/clay-sub/~nul/desk duct=~
^= wrapped-sign ^- (hypo sign:ford) :- *type
[%c %wris [%da ~1234.5.8] (sy [%x /posts/a]~)]
==
::
?> ?=([^ ^ ~] moves3)
%+ welp
%- check-post-made :*
move=i.moves3
duct=~[/post-a]
date=~1234.5.8
title='post-a'
contents="post-a-contents-changed"
==
::
=. ford (ford now=~1234.5.9 eny=0xbeef.dead scry=scry-is-forbidden)
::
=^ moves4 ford (call:ford [duct=~[/post-b] type=~ %kill ~nul])
::
%+ welp
%- expect-eq !>
[moves4 ~]
::
=. ford (ford now=~1234.5.10 eny=0xbeef.dead scry=scry-is-forbidden)
::
=^ moves5 ford (call:ford [duct=~[/post-a] type=~ %kill ~nul])
::
%+ welp
%- expect-eq !>
:- moves5
:~ :* duct=~ %pass wire=/~nul/clay-sub/~nul/desk
%c %warp [~nul ~nul] %desk ~
== ==
::
%- expect-eq !>
:- state-by-ship.+>+<.ford
(my [~nul *ford-state:ford-turbo]~)
::
:: |utilities: helper arms
::
::+| utilities
++ check-post-made
|= $: move=move:ford-turbo
=duct
date=@da
title=@tas
contents=tape
==
^- wall
::
?> ?=([* %give %made @da %complete %result ^ *] move)
=/ result result.p.card.move
?> ?=([%result %scry %noun type-a=* @tas *] head.result)
?> ?=([%result ^ *] tail.result)
?> ?=([%result %ride type-title-a=* %post-a] head.tail.result)
?> ?=([%result %ride type-title-b=* %post-b] tail.tail.result)
::
;: welp
%- expect-eq !>
[duct.move duct]
::
%- expect-eq !>
[date.p.card.move date]
::
%- expect-eq !>
:- head.result(p.q.cage *type)
[%result %scry %noun *type [title=title contents=contents]]
::
%- expect-eq !>
:- (~(nest ut p.q.cage.head.result) | -:!>([title='' contents=""]))
&
::
%- expect-eq !>
:- head.tail.result(p.vase *type)
[%result %ride *type 'post-a']
::
%- expect-eq !>
:- (~(nest ut p.vase.head.tail.result) | -:!>(''))
&
::
%- expect-eq !>
:- tail.tail.result(p.vase *type)
[%result %ride *type 'post-b']
::
%- expect-eq !>
:- (~(nest ut p.vase.tail.tail.result) | -:!>(''))
&
==
::
:: +scry-with-results
++ scry-with-results
|= results=(map [=term =beam] cage)
|= [* (unit (set monk)) =term =beam]
^- (unit (unit cage))
::
~| scry-with-results+[term=term beam=beam]
::
[~ ~ (~(got by results) [term beam])]
:: +scry-succeed: produces a scry function with a known request and answer
::
++ scry-succeed
@ -759,4 +1047,5 @@
::
~| scry-is-forbidden+[beam+beam term+term]
!!
--
--

View File

@ -792,6 +792,9 @@
:: next-builds: builds to perform in the next iteration
::
next-builds=(set build)
:: candidate-builds: builds which might go into next-builds.
::
candidate-builds=(list build)
:: blocked builds: mappings between blocked and blocking builds
::
$= blocked-builds
@ -948,24 +951,32 @@
--
=, format
|%
:: +build-to-tank: convert :build to a printable format
:: +build-to-tape: convert :build to a printable format
::
++ build-to-tank
++ build-to-tape
|= =build
^- tank
^- tape
::
=+ [date schematic]=build
=/ enclose |=(tape "[{+<}]")
=/ date=@da date.build
=/ schematic=schematic schematic.build
::
:- %leaf
%+ weld (trip (scot %da date))
%+ weld " "
%- enclose
%+ welp (trip (scot %da date))
%+ welp " "
::
%- trip
?+ -.schematic
-.schematic
::
%$ %literal
^ %autocons
?+ -.schematic
(trip -.schematic)
::
%$
"literal"
::
^
%- enclose
;:(welp $(build [date head.schematic]) " " $(build [date tail.schematic]))
::
%scry
(spud (en-beam (extract-beam dependency.schematic ~)))
==
:: +unify-jugs: make a new jug, unifying sets for all keys
::
@ -1122,6 +1133,25 @@
%vale cage.result
%volt cage.result
==
:: +build-results-equal: check if two build results are the same value
::
:: We must perform a bidirectional nest check on the types because types
:: aren't guaranteed to be equal; this isn't a problem because the result
:: can be used equivalently.
::
++ build-results-equal
|= [old=build-result new=build-result]
^- ?
::
=+ old-cage=(result-to-cage old)
=+ new-cage=(result-to-cage new)
::
?& =(p.old-cage p.new-cage)
=(q.q.old-cage q.q.new-cage)
(~(nest ut p.q.old-cage) | p.q.new-cage)
(~(nest ut p.q.new-cage) | p.q.old-cage)
==
:: +date-from-schematic: finds the latest pin date from this schematic tree.
::
++ date-from-schematic
@ -1329,7 +1359,7 @@
(~(put ju dependency-updates) date dependency)
:: rebuild dependency builds at the new date
::
%- execute
%- execute-loop
%- sy
%+ turn dependencies
|=(=dependency `build`[date [%scry dependency]])
@ -1394,7 +1424,10 @@
::
=/ sub-builds (~(get ju sub-builds.components.state) i.builds)
::
$(builds (welp t.builds ~(tap in sub-builds)))
=/ new-builds=(list ^build)
(drop (~(find-next by-schematic builds-by-schematic.state) i.builds))
::
$(builds :(welp t.builds ~(tap in sub-builds) new-builds))
::
:: remove mapping from :duct to :build
::
@ -1416,7 +1449,9 @@
::
=. ..execute (execute builds)
::
?~ next-builds.state
?: ?& ?=(~ next-builds.state)
?=(~ candidate-builds.state)
==
..execute
::
$(builds ~)
@ -1431,45 +1466,60 @@
++ execute
|= builds=(set build)
^+ ..execute
:: builds that we know we aren't going to be able to run this event
::
=| rejected-builds=(set build)
::
|^ ^+ ..execute
::
=^ gathered-builds ..execute (gather builds)
=. candidate-builds.state
(weld candidate-builds.state ~(tap in builds))
::
=/ state-diffs=(list state-diff) (turn gathered-builds make)
=. ..$ gather
::
=/ state-diffs=(list state-diff)
(turn ~(tap in next-builds.state) make)
::
=. next-builds.state ~
::
(reduce state-diffs)
:: +gather: collect builds to be run in a batch: wraps +gather-internal
::
++ gather
|= builds=(set build)
^- [(list build) _..execute]
:: enqueue :next-builds into the set of builds we may run
^+ ..$
|-
::
=/ unified (~(uni in next-builds.state) builds)
=. next-builds.state ~
?~ candidate-builds.state
..^$
::
=^ gathered ..execute (gather-internal ~(tap in unified))
=* gathered-builds -.gathered
:: convert to set and back to de-duplicate
=/ next i.candidate-builds.state
=> .(candidate-builds.state t.candidate-builds.state)
::
[~(tap in (sy gathered-builds)) ..execute]
:: +gather-internal: collect builds to be run in a batch
$(..^$ (gather-build next))
:: +gather-build: looks at a single candidate build
::
++ gather-internal
=| gathered=(list build)
=/ can-promote=? &
::
|= builds=(list build)
^+ [[gathered can-promote] ..execute]
::
?~ builds
[[gathered can-promote] ..execute]
::
=/ build=build i.builds
:: This gate inspects a single build. It might move it to :next-builds,
:: or promote it using an old build. It also might add this builds
:: sub-builds to :candidate-builds. Or it might move itself to
:: :rejected-builds, which means we know it can't be run this pass
:: through the event loop.
::
++ gather-build
|= =build
^+ ..^$
:: normalize :date.build for a %pin schematic
::
=? date.build ?=(%pin -.schematic.build) date.schematic.build
:: check if we've already rejected this build for this event
::
?: (~(has in rejected-builds) build)
..^$
:: if we already have a result for this build, don't rerun the build
::
=^ current-result results.state (access-cache build)
?: ?=([~ %result *] current-result)
..^$
:: place :build in :state if it isn't already there
::
=: builds-by-date.state
@ -1485,7 +1535,7 @@
:: if no previous builds exist, we need to run :build
::
?~ old-build
$(builds t.builds, can-promote |, gathered [build gathered])
..^$(next-builds.state (~(put in next-builds.state) build))
:: copy :old-build's live listeners
::
=/ old-live-listeners=(list listener)
@ -1500,92 +1550,92 @@
%_ state
listeners
(~(put ju listeners.state) build listener)
::
builds-by-listener
(~(put by builds-by-listener.state) duct.listener [build &])
==
:: if any dependencies have changed, we need to rebuild :build
::
?: (dependencies-changed build)
$(builds t.builds, can-promote |, gathered [build gathered])
..^$(next-builds.state (~(put in next-builds.state) build))
:: if we don't have :u.old-build's result cached, we need to run :build
::
=^ old-cache-line results.state (access-cache u.old-build)
?~ old-cache-line
$(builds t.builds, can-promote |, gathered [build gathered])
..^$(next-builds.state (~(put in next-builds.state) build))
:: if :u.old-build's result has been wiped, we need to run :build
::
?: ?=(%tombstone -.u.old-cache-line)
$(builds t.builds, can-promote |, gathered [build gathered])
..^$(next-builds.state (~(put in next-builds.state) build))
:: old-subs: sub-builds of :u.old-build
::
=/ old-subs=(list ^build)
=/ old-subs-original=(list ^build)
~(tap in (fall (~(get by sub-builds.components.state) u.old-build) ~))
:: copy to avoid the tmi problem
::
=/ old-subs old-subs-original
:: if :u.old-build had no sub-builds, promote it
::
?~ old-subs
?~ old-subs-original
=^ wiped-rebuild ..execute (promote-build u.old-build date.build)
?~ wiped-rebuild
$(builds t.builds, can-promote &)
=? next-builds.state
?=(^ wiped-rebuild)
(~(put in next-builds.state) u.wiped-rebuild)
::
$(builds t.builds, can-promote &, gathered [u.wiped-rebuild gathered])
:: tmi problem
=^ unblocked-clients state (mark-as-done build)
=. candidate-builds.state
(welp unblocked-clients candidate-builds.state)
::
..^$
::
=> .(old-subs `(list ^build)`old-subs)
:: recursively check if :old-subs can be promoted or gathered
=/ new-subs (turn old-subs |=(^build +<(date date.build)))
:: link all :new-subs to :build in :components.state
::
=. ..gather-internal
=. state
%+ roll new-subs
::
|- ^+ ..gather-internal
?~ old-subs ..gather-internal
|= [new-sub=^build state=_state]
::
=/ old-sub=^build i.old-subs
=/ new-sub=^build old-sub(date date.build)
%_ state
sub-builds.components
(~(put ju sub-builds.components.state) build new-sub)
::
=^ old-sub-result results.state (access-cache old-sub)
?~ old-sub-result
$(old-subs t.old-subs, can-promote |, gathered [new-sub gathered])
::
?: ?=(%tombstone -.u.old-sub-result)
$(old-subs t.old-subs, can-promote |, gathered [new-sub gathered])
::
=^ new-sub-result results.state (access-cache new-sub)
?~ new-sub-result
=^ sub-gathered ..execute (gather-internal ~[new-sub])
=+ [sub-gathered-builds sub-can-promote]=sub-gathered
::
?> =(sub-can-promote (~(has by new.rebuilds.state) old-sub))
::
%_ $
old-subs t.old-subs
can-promote &(can-promote sub-can-promote)
gathered (welp sub-gathered-builds gathered)
==
:: if the rebuild has been wiped, we need to rerun it
::
:: Note: It might make sense to check if :old-sub and :new-sub
:: are linked in :rebuilds.state, in case one is a tombstone,
:: in which case we could copy the other result.
::
?: ?=(%tombstone -.u.new-sub-result)
$(old-subs t.old-subs, can-promote |, gathered [new-sub gathered])
::
?: =(build-result.u.new-sub-result build-result.u.old-sub-result)
$(old-subs t.old-subs)
::
$(old-subs t.old-subs, can-promote |, gathered [new-sub gathered])
client-builds.components
(~(put ju client-builds.components.state) new-sub build)
==
:: if all subs are in old.rebuilds.state, promote ourselves
::
?: can-promote
:: no sub-builds changed, so we can promote the old build
::
?: (levy new-subs ~(has in old.rebuilds.state))
=^ wiped-rebuild ..execute (promote-build u.old-build date.build)
?~ wiped-rebuild
$(builds t.builds)
=? next-builds.state
?=(^ wiped-rebuild)
(~(put in next-builds.state) u.wiped-rebuild)
::
$(builds t.builds, gathered [u.wiped-rebuild gathered])
:: some sub-builds changed, so :build needs to be rerun
=^ unblocked-clients state (mark-as-done build)
=. candidate-builds.state
(welp unblocked-clients candidate-builds.state)
::
..^$
:: all new-subs have results, some are not rebuilds
::
$(builds t.builds, gathered [build gathered])
?: (levy new-subs is-build-cached)
::
..^$(next-builds.state (~(put in next-builds.state) build))
:: otherwise, not all new subs have results.
::
:: If all of our sub-builds finish immediately (i.e. promoted),
:: they'll add us back to :candidate-builds.state.
::
=. blocked-builds.state
%+ roll (skip new-subs is-build-cached)
|= [new-sub=^build blocked-builds=_blocked-builds.state]
::
%_ blocked-builds
sub-builds
(~(put ju sub-builds.blocked-builds) build new-sub)
::
client-builds
(~(put ju client-builds.blocked-builds) new-sub build)
==
::
..^$(candidate-builds.state :(welp new-subs candidate-builds.state))
:: +promote-build: promote result of :build to newer :date
::
:: Also promotes live listeners, links the two builds in :rebuilds.state,
@ -1606,6 +1656,24 @@
::
=. rebuilds.state (link-rebuilds old-build new-build)
::
?> (~(has ju builds-by-date.state) date.new-build schematic.new-build)
::
=. components.state
%+ roll
=- ~(tap in (fall - ~))
(~(get by sub-builds.components.state) old-build)
::
|= [old-sub=build components=_components.state]
::
=/ new-sub=build old-sub(date date)
%_ components
sub-builds
(~(put ju sub-builds.components) new-build new-sub)
::
client-builds
(~(put ju client-builds.components) new-sub new-build)
==
::
=. state (promote-live-listeners old-build new-build)
::
=. ..execute (send-mades new-build (root-once-listeners new-build))
@ -1694,6 +1762,12 @@
::
(~(put by latest-by-disc.state) disc date.build.made)
==
:: clear the components
::
:: TODO: We'll need something like this when we implement %alts,
:: but as written, this breaks test-ride-scry-block.
::
::=. components.state (unlink-sub-builds build.made)
:: process :sub-builds.made
::
=. state
@ -1733,6 +1807,8 @@
?- -.result.made
%build-result
::
?> (~(has ju builds-by-date.state) date.build.made schematic.build.made)
::
=. results.state
%+ ~(put by results.state) build.made
[%result last-accessed=now build-result.result.made]
@ -1741,27 +1817,8 @@
=- ~(tap in (fall - ~))
(~(get by client-builds.blocked-builds.state) build.made)
::
=. blocked-builds.state
%+ roll client-builds
::
|= [client=build blocked-builds=_blocked-builds.state]
::
%_ blocked-builds
sub-builds
(~(del ju sub-builds.blocked-builds) client build.made)
::
client-builds
(~(del ju client-builds.blocked-builds) build.made client)
==
::
=. next-builds.state
%+ roll client-builds
::
|= [client=build next-builds=_next-builds.state]
::
?: (is-build-blocked client)
next-builds
(~(put in next-builds) client)
=^ unblocked-clients state (mark-as-done build.made)
=. next-builds.state (~(gas in next-builds.state) unblocked-clients)
::
=/ previous-build
(~(find-previous by-schematic builds-by-schematic.state) build.made)
@ -1781,7 +1838,9 @@
::
=/ same-result=?
?& ?=([~ %result *] previous-result)
=(build-result.result.made build-result.u.previous-result)
%+ build-results-equal
build-result.result.made
build-result.u.previous-result
==
::
=? rebuilds.state
@ -1793,6 +1852,47 @@
=? ..execute
!same-result
(send-mades build.made (root-live-listeners build.made))
:: rerun any old clients, updated to the current time
::
=? state
&(!same-result ?=(^ previous-build))
::
=/ clients-to-rebuild=(list build)
%+ turn
%+ weld
=- ~(tap in (fall - ~))
(~(get by client-builds.components.state) u.previous-build)
::
=/ older-build (~(get by old.rebuilds.state) u.previous-build)
?~ older-build
~
::
=- ~(tap in (fall - ~))
(~(get by client-builds.components.state) u.older-build)
::
|= old-client=build
old-client(date date.build.made)
::
%+ roll clients-to-rebuild
|= [client=build state=_state]
::
%_ state
::
next-builds
(~(put in next-builds.state) client)
::
client-builds.components
(~(put ju client-builds.components.state) build.made client)
::
sub-builds.components
(~(put ju sub-builds.components.state) client build.made)
::
builds-by-date
(~(put ju builds-by-date.state) date.client schematic.client)
::
builds-by-schematic
(~(put by-schematic builds-by-schematic.state) client)
==
::
=? ..execute
?=(^ previous-build)
@ -1851,8 +1951,8 @@
client-builds.blocked-builds
(~(put ju client-builds.blocked-builds.state) block build.made)
::
next-builds
(~(put in next-builds.state) block)
candidate-builds
[block candidate-builds.state]
==
::
$(state-diffs t.state-diffs)
@ -1903,20 +2003,6 @@
++ make
|= =build
^- state-diff
:: ^- $: :: result: result of running a build
:: ::
:: $= result
:: $% :: %build-result: the build completed
:: ::
:: [%build-result =build-result]
:: :: %blocks: :build is waiting on other builds or a dependency
:: ::
:: [%blocks builds=(list ^build)]
:: ==
:: :: possibly mutated version of the +per-event core
:: ::
:: _this
:: ==
:: accessed-builds: builds accessed/depended on during this run.
::
=| accessed-builds=(list ^build)
@ -2178,10 +2264,12 @@
=/ sub-build=^build [date.build kid]
::
=. accessed-builds [sub-build accessed-builds]
:: +access-cache will mutate :results.state
::
:: TODO: we don't (and don't want to) propagate results.state.
:: It's okay to ignore this because the accessed-builds get gathered
:: and merged during the +reduce step.
::
=^ maybe-cache-line results.state (access-cache sub-build)
=/ maybe-cache-line -:(access-cache sub-build)
?~ maybe-cache-line
[~ accessed-builds]
::
@ -2247,10 +2335,43 @@
:: if :local-result does not nest in :type, produce an error
::
?. -:(nets:wa type `^type`p.q.local-cage)
~& [%scry-nest-fail term=term beam=beam]
[~ ~]
::
[~ ~ `(cask)`local-cage]
:: +mark-as-done: store :build as complete and produce any unblocked clients
::
:: We may not know about these unblocked clients, so we register them in
:: the state.
::
++ mark-as-done
|= =build
^- [(list ^build) _state]
::
=/ client-builds=(list ^build)
~(tap in (fall (~(get by client-builds.blocked-builds.state) build) ~))
::
=. blocked-builds.state
%+ roll client-builds
::
|= [client=^build blocked-builds=_blocked-builds.state]
::
%_ blocked-builds
sub-builds
(~(del ju sub-builds.blocked-builds) client build)
::
client-builds
(~(del ju client-builds.blocked-builds) build client)
==
::
:_ state
::
%+ roll client-builds
::
|= [client=^build next-builds=(list ^build)]
::
?: (is-build-blocked client)
next-builds
[client next-builds]
:: +send-mades: send one %made move for :build per listener in :listeners
::
++ send-mades
@ -2270,6 +2391,27 @@
%made date.build %complete build-result.u.result
==
==
:: +unlink-sub-builds
::
++ unlink-sub-builds
|= =build
^+ components.state
::
=/ kids=(list ^build)
~(tap in (~(get ju sub-builds.components.state) build))
%_ components.state
:: remove the mapping from :build to its sub-builds
::
sub-builds
(~(del by sub-builds.components.state) build)
:: for each +build in :kids, remove :build from its clients
::
client-builds
%+ roll kids
|= [kid=^build clients=_client-builds.components.state]
(~(del ju clients) kid build)
==
:: +promote-live-listeners: move live listeners from :old to :new
::
++ promote-live-listeners
@ -2293,21 +2435,22 @@
listeners
=- (~(put ju -) new listener)
(~(del ju listeners.state) old listener)
::
builds-by-listener
(~(put by builds-by-listener.state) duct.listener [new &])
==
::
%+ roll ~(tap in (fall (~(get by root-builds.state) old) ~))
|= [=listener state=_state]
::
=? root-builds.state
(is-listener-live listener)
::
?. (is-listener-live listener)
state
%_ state
::
root-builds
=- (~(put ju -) new listener)
(~(del ju root-builds.state) old listener)
::
state
builds-by-listener
(~(put by builds-by-listener.state) duct.listener [new &])
==
:: +root-live-listeners: live listeners for which :build is the root build
::
++ root-live-listeners
@ -2341,6 +2484,12 @@
?. ?=(%scry -.schematic.build)
|
(~(has by blocks.state) dependency.schematic.build build)
:: +is-build-cached:
::
++ is-build-cached
|= =build
^- ?
?=([~ %result *] (~(get by results.state) build))
:: +is-build-live: whether this is a live or a once build
::
++ is-build-live
@ -2394,14 +2543,12 @@
=/ mutant=cache-line original(last-accessed now)
::
[`mutant (~(put by results.state) build mutant)]
:: +finalize: convert per-event state to moves and per sistent state
:: +finalize: convert per-event state to moves and persistent state
::
:: Converts :done-live-roots to %made +move's, performs +duct
:: accounting, and runs +cleanup on completed once builds and
:: stale live builds.
::
:: TODO: needs rework to support live builds
::
++ finalize
^- [(list move) ford-state]
:: once we're done, +flop :moves to put them in chronological order
@ -2492,6 +2639,10 @@
++ cleanup
|= =build
^+ this
:: does this build even exist?!
::
?. (~(has ju builds-by-date.state) date.build schematic.build)
this
::
:: if something depends on this build, no-op and return
::
@ -2499,6 +2650,12 @@
(~(has by old.rebuilds.state) build)
(~(has by listeners.state) build)
==
:: ~& :* %cleanup-no-op
:: build=(build-to-tape build)
:: has-client-builds=(~(has by client-builds.components.state) build)
:: has-old-rebuilds=(~(has by old.rebuilds.state) build)
:: listeners=(~(get by listeners.state) build)
:: ==
this
:: remove :build from :state, starting with its cache line
::
@ -2548,7 +2705,7 @@
^- ?
=/ other-build [date schematic.build]
=/ listeners=(set listener)
(fall (~(get by root-builds.state) other-build) ~)
(fall (~(get by listeners.state) other-build) ~)
::
(lien ~(tap in listeners) is-listener-live)
::
@ -2563,23 +2720,15 @@
::
=/ kids=(list ^build)
~(tap in (~(get ju sub-builds.components.state) build))
:: remove the mapping from :build to its sub-builds
::
=. sub-builds.components.state
(~(del by sub-builds.components.state) build)
:: for each +build in :kids, remove :build from its clients
::
=. client-builds.components.state
%+ roll kids
|= [kid=^build clients=_client-builds.components.state]
(~(del ju clients) kid build)
=. components.state (unlink-sub-builds build)
:: if there is a newer rebuild of :build, delete the linkage
::
=/ rebuild (~(get by new.rebuilds.state) build)
=? rebuilds.state ?=(^ rebuild)
%_ rebuilds.state
new (~(del by new.rebuilds.state) build)
old (~(del by old.rebuilds.state) build)
old (~(del by old.rebuilds.state) u.rebuild)
==
:: recurse on :kids
::