From 3817896ae7964a55eec32b127ee2c5ba599a377c Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Thu, 23 May 2019 12:26:53 -0700 Subject: [PATCH 01/12] transaction apps --- app/baby.hoon | 38 +++++++++++++ lib/tapp.hoon | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/trad.hoon | 142 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 app/baby.hoon create mode 100644 lib/tapp.hoon create mode 100644 lib/trad.hoon diff --git a/app/baby.hoon b/app/baby.hoon new file mode 100644 index 000000000..7a09dc0f4 --- /dev/null +++ b/app/baby.hoon @@ -0,0 +1,38 @@ +/+ tapp +:: +:: Preamble +:: +=> + |% + +$ state + $: count=@ud + == + +$ command cord + ++ tapp (^tapp state command) + -- +=, create-tapp=create-tapp:tapp +=, trad=trad:tapp +=, tapp-core=tapp-core:tapp +=, tapp-trad=tapp-trad:tapp +=, helpers:tapp +:: +:: The app +:: +%- create-tapp +^- tapp-core +|_ [=bowl:gall state] +++ handle-command + |= =command + =/ m tapp-trad + ^- form:m + =/ =hiss:eyre + :* purl=(rash command auri:de-purl:html) + meth=%get + math=~ + body=~ + == + ;< ~ bind:m (send-hiss hiss) + ;< =httr:eyre bind:m expect-sigh + ~& [%fetched count httr] + (pure:m +(count)) +-- diff --git a/lib/tapp.hoon b/lib/tapp.hoon new file mode 100644 index 000000000..6cba68dda --- /dev/null +++ b/lib/tapp.hoon @@ -0,0 +1,155 @@ +/+ trad +=, trad-lib=trad +|* [state-type=mold command-type=mold] +|% +:: +:: The form of a tapp +:: +++ tapp-core + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + -- +:: +++ trad-lib (^trad-lib sign card) +++ trad trad:trad-lib +:: +:: Possible async calls +:: ++$ card + $% [%hiss wire ~ %httr %hiss hiss:eyre] + == +:: +:: Possible async responses +:: ++$ sign + $% [%sigh =httr:eyre] + == ++$ move (pair bone card) +++ tapp-trad (trad state-type) ++$ tapp-state + $: waiting=(qeu command-type) + active=(unit eval-form:eval:tapp-trad) + app-state=state-type + == +++ helpers + =, trad-input=trad-input:trad-lib + |% + ++ just-do + |= =card + =/ m (trad ,~) + ^- form:m + |= trad-input + [[/ card]~ ~ %done ~] + :: + ++ send-hiss + |= =hiss:eyre + =/ m (trad ,~) + ^- form:m + (just-do %hiss / ~ %httr %hiss hiss) + :: + ++ expect-sigh + =/ m (trad ,httr:eyre) + ^- form:m + |= =trad-input + ?~ trad-input + [~ ~ %wait ~] + ?: ?=(%sigh -.u.trad-input) + [~ ~ %done httr.u.trad-input] + ~| [%expected-sigh got=-.u.trad-input] + !! + -- +++ create-tapp + |= handler=tapp-core + |_ [=bowl:gall tapp-state] + ++ this-tapp . + :: + :: Start a command + :: + ++ poke-noun + |= command=command-type + ^- (quip move _this-tapp) + =. waiting (~(put to waiting) command) + ?^ active + ~& [%waiting-until-current-trad-finishes waiting] + `this-tapp + start-trad + :: + :: Pass response to trad + :: + ++ sigh-httr + |= [=wire =httr:eyre] + ^- (quip move _this-tapp) + (take-trad `[%sigh httr]) + :: + :: Failed http request + :: + ++ sigh-tang + |= [=wire =tang] + ^- (quip move _this-tapp) + (fail-trad %failed-sigh tang) + :: + :: Continue computing trad + :: + ++ take-trad + |= =trad-input:trad-lib + ^- (quip move _this-tapp) + =/ m tapp-trad + ?~ active + ~| %no-active-trad !! + =^ r=[moves=(list move) =eval-result:eval:m] u.active + (take:eval:m u.active ost.bowl /trad trad-input) + => .(active `(unit eval-form:eval:tapp-trad)`active) :: TMI + =^ moves=(list move) this-tapp + ?- -.eval-result.r + %next `this-tapp + %fail (fail-trad err.eval-result.r) + %done (done-trad value.eval-result.r) + == + [(weld moves.r moves) this-tapp] + :: + :: Called on trad failure + :: + ++ fail-trad + |= err=(pair term tang) + ^- (quip move _this-tapp) + %- (slog leaf+"tapp command failed" leaf+(trip p.err) q.err) + finish-trad + :: + :: Called on trad success + :: + ++ done-trad + |= state=state-type + ^- (quip move _this-tapp) + ~& %trad-done + =. app-state state + finish-trad + :: + :: Called whether trad failed or succeeded + :: + ++ finish-trad + ^- (quip move _this-tapp) + =. active ~ + =. waiting +:~(get to waiting) + start-trad + :: + :: Try to start next command + :: + ++ start-trad + ^- (quip move _this-tapp) + ?. =(~ active) + ~| %trad-already-active !! + =/ next=(unit command-type) ~(top to waiting) + ?~ next + `this-tapp + =. active + :- ~ + ^- eval-form:eval:tapp-trad + %- from-form:eval:tapp-trad + ^- form:tapp-trad + (~(handle-command handler bowl app-state) u.next) + (take-trad ~) + -- +-- diff --git a/lib/trad.hoon b/lib/trad.hoon new file mode 100644 index 000000000..2dedde904 --- /dev/null +++ b/lib/trad.hoon @@ -0,0 +1,142 @@ +|* [input-type=mold card-type=mold] +|% ++$ trad-input (unit input-type) ++$ trad-move (pair bone card-type) +:: +:: notes: notes to send immediately. These will go out even if a +:: later stage of the process fails, so they shouldn't have any +:: semantic effect on the rest of the system. Path is +:: included exclusively for documentation and |verb. +:: effects: moves to send after the process ends. +:: wait: don't move on, stay here. The next sign should come back +:: to this same callback. +:: cont: continue process with new callback. +:: fail: abort process; don't send effects +:: done: finish process; send effects +:: +++ trad-output-raw + |* a=mold + $~ [~ ~ %done *a] + $: notes=(list [path card-type]) + effects=(list card-type) + $= next + $% [%wait ~] + [%cont self=(trad-form-raw a)] + [%fail err=(pair term tang)] + [%done value=a] + == + == +:: +++ trad-form-raw + |* a=mold + $-(trad-input (trad-output-raw a)) +:: +++ trad-fail + |= err=(pair term tang) + |= trad-input + [~ ~ %fail err] +:: +++ trad + |* a=mold + |% + ++ output (trad-output-raw a) + ++ form (trad-form-raw a) + ++ pure + |= arg=a + ^- form + |= trad-input + [~ ~ %done arg] + :: + ++ bind + |* b=mold + |= [m-b=(trad-form-raw b) fun=$-(b form)] + ^- form + |= input=trad-input + =/ b-res=(trad-output-raw b) + (m-b input) + ^- output + :+ notes.b-res effects.b-res + ?- -.next.b-res + %wait [%wait ~] + %cont [%cont ..$(m-b self.next.b-res)] + %fail [%fail err.next.b-res] + %done [%cont (fun value.next.b-res)] + == + :: + :: The trad monad must be evaluted in a particular way to maintain + :: its monadic character. +take:eval implements this. + :: + ++ eval + |% + :: Indelible state of a trad + :: + +$ eval-form + $: effects=(list card-type) + =form + == + :: + :: Convert initial form to eval-form + :: + ++ from-form + |= =form + ^- eval-form + [~ form] + :: + :: The cases of results of +take + :: + +$ eval-result + $% [%next ~] + [%fail err=(pair term tang)] + [%done value=a] + == + :: + :: Take a new sign and run the trad against it + :: + ++ take + :: moves: accumulate throughout recursion the moves to be + :: produced now + =| moves=(list trad-move) + |= [=eval-form =bone =our=wire =trad-input] + ^- [[(list trad-move) =eval-result] _eval-form] + :: run the trad callback + :: + =/ =output (form.eval-form trad-input) + :: add notes to moves + :: + =. moves + %+ welp + moves + %+ turn notes.output + |= [=path card=card-type] + ^- trad-move + [bone card] + :: add effects to list to be produced when done + :: + =. effects.eval-form + (weld effects.eval-form effects.output) + :: if done, produce effects + :: + =? moves ?=(%done -.next.output) + %+ welp + moves + %+ turn effects.eval-form + |= card=card-type + ^- trad-move + [bone card] + :: case-wise handle next steps + :: + ?- -.next.output + %wait [[moves %next ~] eval-form] + %fail [[moves %fail err.next.output] eval-form] + %done [[moves %done value.next.output] eval-form] + %cont + :: recurse to run continuation with initialization input + :: + %_ $ + form.eval-form self.next.output + trad-input ~ + == + == + -- + -- +-- From ece6bba79b91fb40d9a9f691056665a78f254ee1 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Fri, 24 May 2019 19:42:37 -0700 Subject: [PATCH 02/12] bigger poc --- app/baby.hoon | 103 ++++++++++++++++++++++++++++++++++++++++++-------- lib/tapp.hoon | 42 +++++++++++++++++++- 2 files changed, 129 insertions(+), 16 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index 7a09dc0f4..5fd5dd223 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -1,3 +1,8 @@ +:: Little app to demonstrate the structure of programs written with the +:: transaction monad. +:: +:: Fetches the top comment of each of the top 10 stories from Hacker News +:: /+ tapp :: :: Preamble @@ -5,34 +10,102 @@ => |% +$ state - $: count=@ud + $: top-comments=(list tape) == +$ command cord ++ tapp (^tapp state command) + :: -- -=, create-tapp=create-tapp:tapp +=> + |% + :: Helper function to print a comment + :: + ++ comment-to-tang + |= =tape + ^- tang + %+ welp + %+ turn (rip 10 (crip tape)) + |= line=cord + leaf+(trip line) + [leaf+""]~ + :: + :: All the URLs we fetch from + :: + ++ urls + =/ base "https://hacker-news.firebaseio.com/v0/" + :* top-stories=(weld base "topstories.json") + item=|=(item=@ud `tape`:(welp base "item/" +>:(scow %ui item) ".json")) + == +-- =, trad=trad:tapp -=, tapp-core=tapp-core:tapp =, tapp-trad=tapp-trad:tapp =, helpers:tapp :: :: The app :: -%- create-tapp -^- tapp-core +%- create-tapp:tapp +^- tapp-core:tapp |_ [=bowl:gall state] +:: +:: Main function +:: ++ handle-command |= =command =/ m tapp-trad ^- form:m - =/ =hiss:eyre - :* purl=(rash command auri:de-purl:html) - meth=%get - math=~ - body=~ - == - ;< ~ bind:m (send-hiss hiss) - ;< =httr:eyre bind:m expect-sigh - ~& [%fetched count httr] - (pure:m +(count)) + :: + :: If requested to print, just print what we have in our state + :: + ?: =(command 'print') + ~& 'Top comments:' + %- (slog (zing (turn top-comments comment-to-tang))) + (pure:m top-comments) + :: + :: Otherwise, fetch the top HN stories + :: + =. top-comments ~ + ;< =top-stories=json bind:m (fetch-json top-stories:urls) + =/ top-stories=(list @ud) + ((ar ni):dejs:format top-stories-json) + :: + :: Loop through the first 10 stories + :: + =. top-stories (scag 10 top-stories) + |- ^- form:m + =* loop $ + :: + :: If done, print the results + :: + ?~ top-stories + (handle-command 'print') + :: + :: Else, fetch the story info + :: + ~& "fetching item #{+>:(scow %ui i.top-stories)}" + ;< =story-info=json bind:m (fetch-json (item:urls i.top-stories)) + =/ story-comments=(unit (list @ud)) + ((ot kids+(ar ni) ~):dejs-soft:format story-info-json) + :: + :: If no comments, say so + :: + ?: |(?=(~ story-comments) ?=(~ u.story-comments)) + =. top-comments ["" top-comments] + loop(top-stories t.top-stories) + :: + :: Else, fetch comment info + :: + ;< =comment-info=json bind:m (fetch-json (item:urls i.u.story-comments)) + =/ comment-text=(unit tape) + ((ot text+sa ~):dejs-soft:format comment-info-json) + :: + :: If no text (eg comment deleted), record that + :: + ?~ comment-text + =. top-comments ["" top-comments] + loop(top-stories t.top-stories) + :: + :: Else, add text to state + :: + =. top-comments [u.comment-text top-comments] + loop(top-stories t.top-stories) -- diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 6cba68dda..855e1246d 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -60,11 +60,52 @@ [~ ~ %done httr.u.trad-input] ~| [%expected-sigh got=-.u.trad-input] !! + :: + ++ extract-httr-body + |= =httr:eyre + =/ m (trad ,cord) + ^- form:m + ?. =(2 (div p.httr 100)) + (trad-fail:trad-lib %httr-error >p.httr< >+.httr< ~) + ?~ r.httr + (trad-fail:trad-lib %expected-httr-body >httr< ~) + (pure:m q.u.r.httr) + :: + ++ parse-json + |= =cord + =/ m (trad ,json) + ^- form:m + =/ json=(unit json) (de-json:html cord) + ?~ json + (trad-fail:trad-lib %json-parse-error ~) + (pure:m u.json) + :: + ++ fetch-json + |= url=tape + =/ m (trad ,json) + ^- form:m + =/ =hiss:eyre + :* purl=(scan url auri:de-purl:html) + meth=%get + math=~ + body=~ + == + ;< ~ bind:m (send-hiss hiss) + ;< =httr:eyre bind:m expect-sigh + ;< =cord bind:m (extract-httr-body httr) + (parse-json cord) -- ++ create-tapp |= handler=tapp-core |_ [=bowl:gall tapp-state] ++ this-tapp . + ++ prep + |= old-state=* + ^- (quip move _this-tapp) + =/ old ((soft tapp-state) old-state) + ?~ old + `this-tapp + `this-tapp(+<+ u.old) :: :: Start a command :: @@ -123,7 +164,6 @@ ++ done-trad |= state=state-type ^- (quip move _this-tapp) - ~& %trad-done =. app-state state finish-trad :: From 9eb10aaec177f9c984018534df9745e2a63c6c33 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Sat, 25 May 2019 19:17:18 -0700 Subject: [PATCH 03/12] better stdio --- app/baby.hoon | 11 +++++-- lib/tapp.hoon | 83 +++++++-------------------------------------------- 2 files changed, 19 insertions(+), 75 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index 5fd5dd223..48caf4b70 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -3,7 +3,7 @@ :: :: Fetches the top comment of each of the top 10 stories from Hacker News :: -/+ tapp +/+ tapp, stdio :: :: Preamble :: @@ -14,7 +14,6 @@ == +$ command cord ++ tapp (^tapp state command) - :: -- => |% @@ -39,7 +38,7 @@ -- =, trad=trad:tapp =, tapp-trad=tapp-trad:tapp -=, helpers:tapp +=, stdio :: :: The app :: @@ -57,6 +56,8 @@ :: If requested to print, just print what we have in our state :: ?: =(command 'print') + ~& 'drumroll please...' + ;< ~ bind:m (wait (add now.bowl ~s5)) ~& 'Top comments:' %- (slog (zing (turn top-comments comment-to-tang))) (pure:m top-comments) @@ -64,6 +65,10 @@ :: Otherwise, fetch the top HN stories :: =. top-comments ~ + :: + :: If this whole thing takes more than 5 seconds, cancel it + :: + %+ (set-timeout _top-comments) (add now.bowl ~s5) ;< =top-stories=json bind:m (fetch-json top-stories:urls) =/ top-stories=(list @ud) ((ar ni):dejs:format top-stories-json) diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 855e1246d..3e359075f 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -1,4 +1,7 @@ +/- tapp /+ trad +=, card=card:tapp +=, sign=sign:tapp =, trad-lib=trad |* [state-type=mold command-type=mold] |% @@ -16,17 +19,6 @@ ++ trad-lib (^trad-lib sign card) ++ trad trad:trad-lib :: -:: Possible async calls -:: -+$ card - $% [%hiss wire ~ %httr %hiss hiss:eyre] - == -:: -:: Possible async responses -:: -+$ sign - $% [%sigh =httr:eyre] - == +$ move (pair bone card) ++ tapp-trad (trad state-type) +$ tapp-state @@ -34,67 +26,6 @@ active=(unit eval-form:eval:tapp-trad) app-state=state-type == -++ helpers - =, trad-input=trad-input:trad-lib - |% - ++ just-do - |= =card - =/ m (trad ,~) - ^- form:m - |= trad-input - [[/ card]~ ~ %done ~] - :: - ++ send-hiss - |= =hiss:eyre - =/ m (trad ,~) - ^- form:m - (just-do %hiss / ~ %httr %hiss hiss) - :: - ++ expect-sigh - =/ m (trad ,httr:eyre) - ^- form:m - |= =trad-input - ?~ trad-input - [~ ~ %wait ~] - ?: ?=(%sigh -.u.trad-input) - [~ ~ %done httr.u.trad-input] - ~| [%expected-sigh got=-.u.trad-input] - !! - :: - ++ extract-httr-body - |= =httr:eyre - =/ m (trad ,cord) - ^- form:m - ?. =(2 (div p.httr 100)) - (trad-fail:trad-lib %httr-error >p.httr< >+.httr< ~) - ?~ r.httr - (trad-fail:trad-lib %expected-httr-body >httr< ~) - (pure:m q.u.r.httr) - :: - ++ parse-json - |= =cord - =/ m (trad ,json) - ^- form:m - =/ json=(unit json) (de-json:html cord) - ?~ json - (trad-fail:trad-lib %json-parse-error ~) - (pure:m u.json) - :: - ++ fetch-json - |= url=tape - =/ m (trad ,json) - ^- form:m - =/ =hiss:eyre - :* purl=(scan url auri:de-purl:html) - meth=%get - math=~ - body=~ - == - ;< ~ bind:m (send-hiss hiss) - ;< =httr:eyre bind:m expect-sigh - ;< =cord bind:m (extract-httr-body httr) - (parse-json cord) - -- ++ create-tapp |= handler=tapp-core |_ [=bowl:gall tapp-state] @@ -102,6 +33,7 @@ ++ prep |= old-state=* ^- (quip move _this-tapp) + ~& %tapp-loaded =/ old ((soft tapp-state) old-state) ?~ old `this-tapp @@ -132,6 +64,13 @@ ^- (quip move _this-tapp) (fail-trad %failed-sigh tang) :: + ++ wake + |= [=wire error=(unit tang)] + ^- (quip move _this-tapp) + ?^ error + (fail-trad %timer-fire-failed u.error) + (take-trad `[%wake ~]) + :: :: Continue computing trad :: ++ take-trad From 2fd87c815b538d8d433686709a23bef2cebb58aa Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Sat, 25 May 2019 22:14:08 -0700 Subject: [PATCH 04/12] add contracts to trad and time-related stdio functions --- app/baby.hoon | 11 +-- lib/stdio.hoon | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/tapp.hoon | 60 ++++++++++++---- lib/trad.hoon | 58 ++++++++++++---- sur/tapp.hoon | 25 +++++++ 5 files changed, 305 insertions(+), 33 deletions(-) create mode 100644 lib/stdio.hoon create mode 100644 sur/tapp.hoon diff --git a/app/baby.hoon b/app/baby.hoon index 48caf4b70..850d50e26 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -57,7 +57,8 @@ :: ?: =(command 'print') ~& 'drumroll please...' - ;< ~ bind:m (wait (add now.bowl ~s5)) + ;< now=@da bind:m get-time + ;< ~ bind:m (wait (add now ~s3)) ~& 'Top comments:' %- (slog (zing (turn top-comments comment-to-tang))) (pure:m top-comments) @@ -66,16 +67,16 @@ :: =. top-comments ~ :: - :: If this whole thing takes more than 5 seconds, cancel it + :: If this whole thing takes more than 15 seconds, cancel it :: - %+ (set-timeout _top-comments) (add now.bowl ~s5) + %+ (set-timeout _top-comments) (add now.bowl ~s15) ;< =top-stories=json bind:m (fetch-json top-stories:urls) =/ top-stories=(list @ud) ((ar ni):dejs:format top-stories-json) :: - :: Loop through the first 10 stories + :: Loop through the first 5 stories :: - =. top-stories (scag 10 top-stories) + =. top-stories (scag 5 top-stories) |- ^- form:m =* loop $ :: diff --git a/lib/stdio.hoon b/lib/stdio.hoon new file mode 100644 index 000000000..44fafa4da --- /dev/null +++ b/lib/stdio.hoon @@ -0,0 +1,184 @@ +:: Standard input/input functions. +:: +:: These are all asynchronous computations, which means they produce a +:: form:(trad A) for some type A. You can always tell what they +:: produce by checking their first three lines. +:: +:: Functions with the word "raw" in their name are for internal use +:: only because they carry a high salmonella risk. More specifcally, +:: improper use of them may result in side effects that the tapp +:: runtime doesn't know about and can't undo in case the transaction +:: fails. +:: +/- tapp-sur=tapp +/+ trad +=, card=card:tapp-sur +=, sign=sign:tapp-sur +=, contract=contract:tapp-sur +=+ (trad sign card contract) +|% +:: +:: Raw power +:: +++ send-raw-card + |= =card + =/ m (trad ,~) + ^- form:m + |= trad-input + [[/ card]~ ~ ~ %done ~] +:: +:: Add or remove a contract +:: +++ set-raw-contract + |= [add=? =contract] + =/ m (trad ,~) + ^- form:m + |= trad-input + [~ ~ (silt [add contract]~) %done ~] +:: +:: ---- +:: +:: HTTP requests +:: +++ send-hiss + |= =hiss:eyre + =/ m (trad ,~) + ^- form:m + ;< ~ bind:m (send-raw-card %hiss / ~ %httr %hiss hiss) + (set-raw-contract & %hiss ~) +:: +:: Wait until we get an HTTP response +:: +++ take-sigh-raw + =/ m (trad ,httr:eyre) + ^- form:m + |= =trad-input + :^ ~ ~ ~ + ?~ in.trad-input + [%wait ~] + ?. ?=(%sigh -.sign.u.in.trad-input) + [%fail %expected-sigh >got=-.sign.u.in.trad-input< ~] + [%done httr.sign.u.in.trad-input] +:: +:: Wait until we get an HTTP response and unset contract +:: +++ take-sigh + =/ m (trad ,httr:eyre) + ^- form:m + ;< =httr:eyre bind:m take-sigh-raw + ;< ~ bind:m (set-raw-contract | %hiss ~) + (pure:m httr) +:: +:: Extract body from raw httr +:: +++ extract-httr-body + |= =httr:eyre + =/ m (trad ,cord) + ^- form:m + ?. =(2 (div p.httr 100)) + (trad-fail %httr-error >p.httr< >+.httr< ~) + ?~ r.httr + (trad-fail %expected-httr-body >httr< ~) + (pure:m q.u.r.httr) +:: +:: Parse cord to json +:: +++ parse-json + |= =cord + =/ m (trad ,json) + ^- form:m + =/ json=(unit json) (de-json:html cord) + ?~ json + (trad-fail %json-parse-error ~) + (pure:m u.json) +:: +:: Fetch json at given url +:: +++ fetch-json + |= url=tape + =/ m (trad ,json) + ^- form:m + =/ =hiss:eyre + :* purl=(scan url auri:de-purl:html) + meth=%get + math=~ + body=~ + == + ;< ~ bind:m (send-hiss hiss) + ;< =httr:eyre bind:m take-sigh + ;< =cord bind:m (extract-httr-body httr) + (parse-json cord) +:: +:: ---- +:: +:: Time is what keeps everything from happening at once +:: +++ get-time + =/ m (trad ,@da) + ^- form:m + |= =trad-input + [~ ~ ~ %done now.bowl.trad-input] +:: +:: Set a timer +:: +++ send-wait + |= at=@da + =/ m (trad ,~) + ^- form:m + ;< ~ bind:m (send-raw-card %wait /(scot %da at) at) + (set-raw-contract & %wait at) +:: +:: Wait until we get a wake event +:: +++ take-wake-raw + =/ m (trad ,@da) + ^- form:m + |= =trad-input + :^ ~ ~ ~ + ?~ in.trad-input + [%wait ~] + ?. ?=(%wake -.sign.u.in.trad-input) + [%fail %expected-wake >got=-.sign.u.in.trad-input< ~] + ?~ wire.u.in.trad-input + [%fail %expected-wake-time ~] + =/ at=(unit @da) (slaw %da i.wire.u.in.trad-input) + ?~ at + [%fail %expected-wake-time-da >wire< ~] + [%done u.at] +:: +:: Wait until we get a wake event and unset contract +:: +++ take-wake + =/ m (trad ,~) + ^- form:m + ;< at=@da bind:m take-wake-raw + (set-raw-contract | %wait at) +:: +:: Wait until time +:: +++ wait + |= until=@da + =/ m (trad ,~) + ^- form:m + ;< ~ bind:m (send-wait until) + take-wake +:: +:: Cancel computation if not done by time +:: +++ set-timeout + |* computation-result=mold + =/ m (trad ,computation-result) + |= [when=@da computation=form:m] + ^- form:m + ;< ~ bind:m (send-wait when) + |= =trad-input + =* loop $ + ?: ?& ?=([~ * %wake *] in.trad-input) + =(/(scot %da when) wire.u.in.trad-input) + == + [~ ~ (silt [| %wait when]~) %fail %trad-timeout ~] + =/ c-res (computation trad-input) + ?. ?=(%cont -.next.c-res) + c-res + c-res(self.next ..loop(computation self.next.c-res)) +-- diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 3e359075f..3d24b281b 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -2,6 +2,7 @@ /+ trad =, card=card:tapp =, sign=sign:tapp +=, contract=contract:tapp =, trad-lib=trad |* [state-type=mold command-type=mold] |% @@ -16,7 +17,7 @@ *form:tapp-trad -- :: -++ trad-lib (^trad-lib sign card) +++ trad-lib (^trad-lib sign card contract) ++ trad trad:trad-lib :: +$ move (pair bone card) @@ -55,21 +56,21 @@ ++ sigh-httr |= [=wire =httr:eyre] ^- (quip move _this-tapp) - (take-trad `[%sigh httr]) + (take-trad bowl `[wire %sigh httr]) :: :: Failed http request :: ++ sigh-tang |= [=wire =tang] ^- (quip move _this-tapp) - (fail-trad %failed-sigh tang) + (oob-fail-trad %failed-sigh tang) :: ++ wake |= [=wire error=(unit tang)] ^- (quip move _this-tapp) ?^ error - (fail-trad %timer-fire-failed u.error) - (take-trad `[%wake ~]) + (oob-fail-trad %timer-fire-failed u.error) + (take-trad bowl `[wire %wake ~]) :: :: Continue computing trad :: @@ -78,41 +79,55 @@ ^- (quip move _this-tapp) =/ m tapp-trad ?~ active + :: Can't cancel HTTP requests, so we might get answers after end + :: of computation + :: + ?: ?=([~ @ %sigh *] in.trad-input) + `this-tapp ~| %no-active-trad !! =^ r=[moves=(list move) =eval-result:eval:m] u.active - (take:eval:m u.active ost.bowl /trad trad-input) + (take:eval:m u.active ost.bowl trad-input) => .(active `(unit eval-form:eval:tapp-trad)`active) :: TMI =^ moves=(list move) this-tapp ?- -.eval-result.r %next `this-tapp - %fail (fail-trad err.eval-result.r) - %done (done-trad value.eval-result.r) + %fail (fail-trad [contracts err]:eval-result.r) + %done (done-trad [contracts value]:eval-result.r) == [(weld moves.r moves) this-tapp] :: + :: Fails currently-running trad + :: + ++ oob-fail-trad + (cury fail-trad contracts:(need active)) + :: :: Called on trad failure :: ++ fail-trad - |= err=(pair term tang) + |= [contracts=(set contract) err=(pair term tang)] ^- (quip move _this-tapp) %- (slog leaf+"tapp command failed" leaf+(trip p.err) q.err) - finish-trad + (finish-trad contracts) :: :: Called on trad success :: ++ done-trad - |= state=state-type + |= [contracts=(set contract) state=state-type] ^- (quip move _this-tapp) =. app-state state - finish-trad + (finish-trad contracts) :: :: Called whether trad failed or succeeded :: ++ finish-trad + |= contracts=(set contract) ^- (quip move _this-tapp) + =^ moves-1 this-tapp (cancel-contracts contracts) =. active ~ =. waiting +:~(get to waiting) - start-trad + =^ moves-2 this-tapp start-trad + [(weld moves-1 moves-2) this-tapp] + :: :: :: Try to start next command :: @@ -129,6 +144,23 @@ %- from-form:eval:tapp-trad ^- form:tapp-trad (~(handle-command handler bowl app-state) u.next) - (take-trad ~) + (take-trad bowl ~) + :: + :: Cancel outstanding contracts + :: + ++ cancel-contracts + |= contracts=(set contract) + ^- (quip move this-tapp) + [(zing (turn ~(tap in contracts) cancel-contract)) this-tapp] + :: + :: Cancel individual contract + :: + ++ cancel-contract + |= =contract + ^- (list move) + ?- -.contract + %wait [ost.bowl %rest /(scot %da at.contract) at.contract]~ + %hiss ~ :: can't cancel; will ignore response + == -- -- diff --git a/lib/trad.hoon b/lib/trad.hoon index 2dedde904..36eeedf05 100644 --- a/lib/trad.hoon +++ b/lib/trad.hoon @@ -1,6 +1,6 @@ -|* [input-type=mold card-type=mold] +|* [input-type=mold card-type=mold contract-type=mold] |% -+$ trad-input (unit input-type) ++$ trad-input [=bowl:gall in=(unit [=wire sign=input-type])] +$ trad-move (pair bone card-type) :: :: notes: notes to send immediately. These will go out even if a @@ -16,9 +16,10 @@ :: ++ trad-output-raw |* a=mold - $~ [~ ~ %done *a] + $~ [~ ~ ~ %done *a] $: notes=(list [path card-type]) effects=(list card-type) + contracts=(set [add=? contract=contract-type]) $= next $% [%wait ~] [%cont self=(trad-form-raw a)] @@ -34,7 +35,7 @@ ++ trad-fail |= err=(pair term tang) |= trad-input - [~ ~ %fail err] + [~ ~ ~ %fail err] :: ++ trad |* a=mold @@ -45,7 +46,7 @@ |= arg=a ^- form |= trad-input - [~ ~ %done arg] + [~ ~ ~ %done arg] :: ++ bind |* b=mold @@ -55,7 +56,7 @@ =/ b-res=(trad-output-raw b) (m-b input) ^- output - :+ notes.b-res effects.b-res + :^ notes.b-res effects.b-res contracts.b-res ?- -.next.b-res %wait [%wait ~] %cont [%cont ..$(m-b self.next.b-res)] @@ -72,6 +73,7 @@ :: +$ eval-form $: effects=(list card-type) + contracts=(set contract-type) =form == :: @@ -80,14 +82,14 @@ ++ from-form |= =form ^- eval-form - [~ form] + [~ ~ form] :: :: The cases of results of +take :: +$ eval-result $% [%next ~] - [%fail err=(pair term tang)] - [%done value=a] + [%fail contracts=(set contract-type) err=(pair term tang)] + [%done contracts=(set contract-type) value=a] == :: :: Take a new sign and run the trad against it @@ -96,8 +98,9 @@ :: moves: accumulate throughout recursion the moves to be :: produced now =| moves=(list trad-move) - |= [=eval-form =bone =our=wire =trad-input] + |= [=eval-form =bone =trad-input] ^- [[(list trad-move) =eval-result] _eval-form] + =* take-loop $ :: run the trad callback :: =/ =output (form.eval-form trad-input) @@ -114,6 +117,33 @@ :: =. effects.eval-form (weld effects.eval-form effects.output) + :: add or remove contracts + :: + =. . + =* loop-result . + =/ new=(list [add=? contract=contract-type]) + ~(tap in contracts.output) + |- ^+ loop-result + =* loop $ + ?~ new + loop-result + ?: add.i.new + ?: (~(has in contracts.eval-form) contract.i.new) + %= loop-result + next.output [%fail %contract-already-exists >contract.i.new< ~] + == + %= loop + contracts.eval-form (~(put in contracts.eval-form) contract.i.new) + new t.new + == + ?: (~(has in contracts.eval-form) contract.i.new) + %= loop + contracts.eval-form (~(del in contracts.eval-form) contract.i.new) + new t.new + == + %= loop-result + next.output [%fail %contract-doesnt-exist >contract.i.new< ~] + == :: if done, produce effects :: =? moves ?=(%done -.next.output) @@ -127,14 +157,14 @@ :: ?- -.next.output %wait [[moves %next ~] eval-form] - %fail [[moves %fail err.next.output] eval-form] - %done [[moves %done value.next.output] eval-form] + %fail [[moves %fail contracts.eval-form err.next.output] eval-form] + %done [[moves %done contracts.eval-form value.next.output] eval-form] %cont :: recurse to run continuation with initialization input :: - %_ $ + %_ take-loop form.eval-form self.next.output - trad-input ~ + trad-input [bowl.trad-input ~] == == -- diff --git a/sur/tapp.hoon b/sur/tapp.hoon new file mode 100644 index 000000000..bbbd04651 --- /dev/null +++ b/sur/tapp.hoon @@ -0,0 +1,25 @@ +|% +:: +:: Possible async calls +:: ++$ card + $% [%hiss wire ~ %httr %hiss hiss:eyre] + [%them wire ~] + [%wait wire @da] + [%rest wire @da] + == +:: +:: Possible async responses +:: ++$ sign + $% [%sigh =httr:eyre] + [%wake (unit tang)] + == +:: +:: Outstanding contracts +:: ++$ contract + $% [%wait at=@da] + [%hiss ~] + == +-- From 9d1e8601e304a547540a1db490e85f64f1bece7a Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 13:23:06 -0700 Subject: [PATCH 05/12] add app poking to stdio --- app/baby.hoon | 6 +++++- app/sitter.hoon | 30 ++++++++++++++++++++++++++++++ lib/stdio.hoon | 21 +++++++++++++++++++++ lib/tapp.hoon | 16 ++++++++-------- sur/tapp.hoon | 2 ++ 5 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 app/sitter.hoon diff --git a/app/baby.hoon b/app/baby.hoon index 850d50e26..ec0313a27 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -13,7 +13,11 @@ $: top-comments=(list tape) == +$ command cord - ++ tapp (^tapp state command) + +$ poke-data + $% [%noun cord] + == + ++ tapp (^tapp state command poke-data) + ++ stdio (^stdio poke-data) -- => |% diff --git a/app/sitter.hoon b/app/sitter.hoon new file mode 100644 index 000000000..4e6f64514 --- /dev/null +++ b/app/sitter.hoon @@ -0,0 +1,30 @@ +/+ tapp, stdio +=> + |% + +$ subscription-state + $: her=ship + app=term + == + +$ state + $: subscription=(unit subscription-state) + == + +$ command cord + +$ poke-data + $% [%noun cord] + == + ++ tapp (^tapp state command poke-data) + ++ stdio (^stdio poke-data) + -- +=, trad=trad:tapp +=, tapp-trad=tapp-trad:tapp +=, stdio +%- create-tapp:tapp +^- tapp-core:tapp +|_ [=bowl:gall state] +++ handle-command + |= =command + =/ m tapp-trad + ^- form:m + ;< ~ bind:m (poke-app [our.bowl %baby] %noun 'print') + (pure:m subscription) +-- diff --git a/lib/stdio.hoon b/lib/stdio.hoon index 44fafa4da..d7bbc8d8b 100644 --- a/lib/stdio.hoon +++ b/lib/stdio.hoon @@ -12,6 +12,8 @@ :: /- tapp-sur=tapp /+ trad +|* poke-data=mold +=/ tapp-sur (tapp-sur poke-data) =, card=card:tapp-sur =, sign=sign:tapp-sur =, contract=contract:tapp-sur @@ -36,6 +38,15 @@ |= trad-input [~ ~ (silt [add contract]~) %done ~] :: +:: Send effect +:: +++ send-effect + |= =card + =/ m (trad ,~) + ^- form:m + |= trad-input + [~ [card]~ ~ %done ~] +:: :: ---- :: :: HTTP requests @@ -181,4 +192,14 @@ ?. ?=(%cont -.next.c-res) c-res c-res(self.next ..loop(computation self.next.c-res)) +:: +:: ---- +:: +:: Apps +:: +++ poke-app + |= [[her=ship app=term] =poke-data] + =/ m (trad ,~) + ^- form:m + (send-effect %poke / [her app] poke-data) -- diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 3d24b281b..e4a9001be 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -1,11 +1,11 @@ -/- tapp +/- tapp-sur=tapp /+ trad -=, card=card:tapp -=, sign=sign:tapp -=, contract=contract:tapp -=, trad-lib=trad -|* [state-type=mold command-type=mold] +|* [state-type=mold command-type=mold poke-data=mold] |% +++ tapp-sur (^tapp-sur poke-data) +++ card card:tapp-sur +++ sign sign:tapp-sur +++ contract contract:tapp-sur :: :: The form of a tapp :: @@ -17,7 +17,7 @@ *form:tapp-trad -- :: -++ trad-lib (^trad-lib sign card contract) +++ trad-lib (^trad sign card contract) ++ trad trad:trad-lib :: +$ move (pair bone card) @@ -34,7 +34,7 @@ ++ prep |= old-state=* ^- (quip move _this-tapp) - ~& %tapp-loaded + ~& [%tapp-loaded dap.bowl] =/ old ((soft tapp-state) old-state) ?~ old `this-tapp diff --git a/sur/tapp.hoon b/sur/tapp.hoon index bbbd04651..3e2cce9da 100644 --- a/sur/tapp.hoon +++ b/sur/tapp.hoon @@ -1,3 +1,4 @@ +|* poke-data=mold |% :: :: Possible async calls @@ -7,6 +8,7 @@ [%them wire ~] [%wait wire @da] [%rest wire @da] + [%poke wire dock poke-data] == :: :: Possible async responses From 96a2baabec38f7ab096e572e7685028f2f15d4ae Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 15:37:42 -0700 Subject: [PATCH 06/12] more useful +diff and +sigh --- sys/vane/gall.hoon | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/vane/gall.hoon b/sys/vane/gall.hoon index 6728f2eb6..9aa5e8911 100644 --- a/sys/vane/gall.hoon +++ b/sys/vane/gall.hoon @@ -682,13 +682,18 @@ =+ ^= arg ^- vase %- slop ?: =(0 p.u.cug) - [!>(`path`+.pax) !>(cag)] + [!>(`path`+.pax) (ap-cage cag)] [!>((slag (dec p.u.cug) `path`+.pax)) q.cag] =^ cam +>.$ (ap-call q.u.cug arg) ?^ cam (ap-pump:(ap-lame q.u.cug u.cam) | her pax) (ap-pump & her pax) :: + ++ ap-cage :: cage to tagged vase + |= cag/cage + ^- vase + (slop `vase`[[%atom %tas `p.cag] p.cag] q.cag) + :: ++ ap-pump :: update subscription ~/ %ap-pump |= {oak/? her/ship pax/path} @@ -1094,7 +1099,7 @@ =+ ^= arg ^- vase %- slop ?: =(0 p.u.cug) - [!>(`path`pax) !>(cag)] + [!>(`path`pax) (ap-cage cag)] [!>((slag (dec p.u.cug) `path`pax)) q.cag] =^ cam +>.$ (ap-call q.u.cug arg) ?^ cam (ap-lame q.u.cug u.cam) From 40c4ea45d22ce02b36033736e580555f6da83aab Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 15:38:14 -0700 Subject: [PATCH 07/12] add subscriptions to stdio --- app/baby.hoon | 22 +++++-- app/sitter.hoon | 32 ++++++++-- lib/stdio.hoon | 71 ++++++++++++++++++++-- lib/tapp.hoon | 155 +++++++++++++++++++++++++++++++++++++++++------- lib/trad.hoon | 30 +++++----- sur/tapp.hoon | 5 +- 6 files changed, 261 insertions(+), 54 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index ec0313a27..11081b3b5 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -16,8 +16,12 @@ +$ poke-data $% [%noun cord] == - ++ tapp (^tapp state command poke-data) - ++ stdio (^stdio poke-data) + +$ out-peer-data + $% [%comments (list tape)] + == + +$ in-peer-data ~ + ++ tapp (^tapp state command poke-data out-peer-data in-peer-data) + ++ stdio (^stdio poke-data out-peer-data) -- => |% @@ -46,8 +50,8 @@ :: :: The app :: -%- create-tapp:tapp -^- tapp-core:tapp +%- create-tapp-poke-peer:tapp +^- tapp-core-poke-peer:tapp |_ [=bowl:gall state] :: :: Main function @@ -84,9 +88,10 @@ |- ^- form:m =* loop $ :: - :: If done, print the results + :: If done, tell subscriers and print the results :: ?~ top-stories + ;< ~ bind:m (give-result /comments %comments top-comments) (handle-command 'print') :: :: Else, fetch the story info @@ -118,4 +123,11 @@ :: =. top-comments [u.comment-text top-comments] loop(top-stories t.top-stories) +:: +++ handle-peer + |= =path + =/ m tapp-trad + ^- form:m + ~& [%baby-take-peer path] + (pure:m top-comments) -- diff --git a/app/sitter.hoon b/app/sitter.hoon index 4e6f64514..0f80cac79 100644 --- a/app/sitter.hoon +++ b/app/sitter.hoon @@ -2,8 +2,8 @@ => |% +$ subscription-state - $: her=ship - app=term + $: target=[her=ship app=term] + =path == +$ state $: subscription=(unit subscription-state) @@ -12,19 +12,39 @@ +$ poke-data $% [%noun cord] == - ++ tapp (^tapp state command poke-data) - ++ stdio (^stdio poke-data) + +$ out-peer-data ~ + +$ in-peer-data + $% [%comments comments=(list tape)] + == + ++ tapp (^tapp state command poke-data out-peer-data in-peer-data) + ++ stdio (^stdio poke-data out-peer-data) -- =, trad=trad:tapp =, tapp-trad=tapp-trad:tapp =, stdio -%- create-tapp:tapp -^- tapp-core:tapp +%- create-tapp-poke-diff:tapp +^- tapp-core-poke-diff:tapp |_ [=bowl:gall state] ++ handle-command |= =command =/ m tapp-trad ^- form:m + ?: =(command 'pull') + ?~ subscription + (trad-fail %no-subscription ~) + ;< ~ bind:m (pull-app [target path]:u.subscription) + (pure:m ~) ;< ~ bind:m (poke-app [our.bowl %baby] %noun 'print') + ;< ~ bind:m (peer-app [our.bowl %baby] /comments) + =. subscription `[[our.bowl %baby] /comments] + ;< ~ bind:m (wait (add now.bowl ~s3)) + (pure:m subscription) +:: +++ handle-diff + |= [[her=ship app=term] =path data=in-peer-data] + =/ m tapp-trad + ^- form:m + ?> ?=(%comments -.data) + ~& sitter-got-data=(lent comments.data) (pure:m subscription) -- diff --git a/lib/stdio.hoon b/lib/stdio.hoon index d7bbc8d8b..ea30c1192 100644 --- a/lib/stdio.hoon +++ b/lib/stdio.hoon @@ -1,4 +1,4 @@ -:: Standard input/input functions. +:: Standard input/output functions. :: :: These are all asynchronous computations, which means they produce a :: form:(trad A) for some type A. You can always tell what they @@ -12,8 +12,8 @@ :: /- tapp-sur=tapp /+ trad -|* poke-data=mold -=/ tapp-sur (tapp-sur poke-data) +|* [poke-data=mold out-peer-data=mold] +=/ tapp-sur (tapp-sur poke-data out-peer-data) =, card=card:tapp-sur =, sign=sign:tapp-sur =, contract=contract:tapp-sur @@ -26,7 +26,7 @@ |= =card =/ m (trad ,~) ^- form:m - |= trad-input + |= =trad-input [[/ card]~ ~ ~ %done ~] :: :: Add or remove a contract @@ -38,14 +38,25 @@ |= trad-input [~ ~ (silt [add contract]~) %done ~] :: -:: Send effect +:: Send effect on current bone :: ++ send-effect |= =card =/ m (trad ,~) ^- form:m + ;< =bone bind:m + |= =trad-input + [~ ~ ~ %done ost.bowl.trad-input] + (send-effect-on-bone bone card) +:: +:: Send effect on particular bone +:: +++ send-effect-on-bone + |= [=bone =card] + =/ m (trad ,~) + ^- form:m |= trad-input - [~ [card]~ ~ %done ~] + [~ [bone card]~ ~ %done ~] :: :: ---- :: @@ -202,4 +213,52 @@ =/ m (trad ,~) ^- form:m (send-effect %poke / [her app] poke-data) +:: +++ peer-app + |= [[her=ship app=term] =path] + =/ m (trad ,~) + ^- form:m + =/ =wire (weld /(scot %p her)/[app] path) + (send-effect %peer wire [her app] path) +:: +++ pull-app + |= [[her=ship app=term] =path] + =/ m (trad ,~) + ^- form:m + =/ =wire (weld /(scot %p her)/[app] path) + (send-effect %pull wire [her app] ~) +:: +:: ---- +:: +:: Handle subscriptions +:: +:: Get bones at particular path; for internal use only +:: +++ get-bones-on-path + |= =the=path + =/ m (trad ,(list bone)) + ^- form:m + |= =trad-input + :^ ~ ~ ~ + :- %done + %+ murn ~(tap by sup.bowl.trad-input) + |= [ost=bone her=ship =sub=path] + ^- (unit bone) + ?. =(the-path sub-path) + ~ + `ost +:: +:: Give a result to subscribers on particular path +:: +++ give-result + |= [=path =out-peer-data] + =/ m (trad ,~) + ^- form:m + ;< bones=(list bone) bind:m (get-bones-on-path path) + |- ^- form:m + =* loop $ + ?~ bones + (pure:m ~) + ;< ~ bind:m (send-effect-on-bone i.bones %diff out-peer-data) + loop(bones t.bones) -- diff --git a/lib/tapp.hoon b/lib/tapp.hoon index e4a9001be..a5716f005 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -1,21 +1,21 @@ /- tapp-sur=tapp /+ trad -|* [state-type=mold command-type=mold poke-data=mold] +|* $: state-type=mold + command-type=mold + poke-data=mold + out-peer-data=mold + in-peer-data=mold + == |% -++ tapp-sur (^tapp-sur poke-data) +++ tapp-sur (^tapp-sur poke-data out-peer-data) ++ card card:tapp-sur ++ sign sign:tapp-sur ++ contract contract:tapp-sur -:: -:: The form of a tapp -:: -++ tapp-core - $_ ^| - |_ [bowl:gall state-type] - ++ handle-command - |~ command-type - *form:tapp-trad - -- +++ command + $% [%poke command=command-type] + [%peer =path] + [%diff =dock =path =in-peer-data] + == :: ++ trad-lib (^trad sign card contract) ++ trad trad:trad-lib @@ -23,12 +23,95 @@ +$ move (pair bone card) ++ tapp-trad (trad state-type) +$ tapp-state - $: waiting=(qeu command-type) + $: waiting=(qeu command) active=(unit eval-form:eval:tapp-trad) app-state=state-type == -++ create-tapp - |= handler=tapp-core +:: +:: The form of a tapp that only handles pokes +:: +++ tapp-core-poke + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + -- +:: +++ create-tapp-poke + |= handler=tapp-core-poke + %- create-tapp-poke-peer + |_ [=bowl:gall state=state-type] + ++ handle-command ~(handle-command handler bowl state) + ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) + -- +:: +:: The form of a tapp that only handles pokes and peers +:: +++ tapp-core-poke-peer + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + :: + ++ handle-peer + |~ path + *form:tapp-trad + -- +:: +++ create-tapp-poke-peer + |= handler=tapp-core-poke-peer + %- create-tapp-all + |_ [=bowl:gall state=state-type] + ++ handle-command ~(handle-command handler bowl state) + ++ handle-peer ~(handle-peer handler bowl state) + ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) + -- +:: +:: The form of a tapp that only handles pokes and diffs +:: +++ tapp-core-poke-diff + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + :: + ++ handle-diff + |~ [dock path in-peer-data] + *form:tapp-trad + -- +:: +++ create-tapp-poke-diff + |= handler=tapp-core-poke-diff + %- create-tapp-all + |_ [=bowl:gall state=state-type] + ++ handle-command ~(handle-command handler bowl state) + ++ handle-peer |=(=path (trad-fail:trad-lib %no-peer-handler >path< ~)) + ++ handle-diff ~(handle-diff handler bowl state) + -- +:: +:: The form of a tapp +:: +++ tapp-core-all + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + :: + ++ handle-peer + |~ path + *form:tapp-trad + :: + ++ handle-diff + |~ [dock path in-peer-data] + *form:tapp-trad + -- +:: +++ create-tapp-all + |= handler=tapp-core-all |_ [=bowl:gall tapp-state] ++ this-tapp . ++ prep @@ -45,12 +128,36 @@ ++ poke-noun |= command=command-type ^- (quip move _this-tapp) - =. waiting (~(put to waiting) command) + =. waiting (~(put to waiting) %poke command) ?^ active ~& [%waiting-until-current-trad-finishes waiting] `this-tapp start-trad :: + :: Receive subscription request + :: + ++ peer + |= =path + ^- (quip move _this-tapp) + =. waiting (~(put to waiting) %peer path) + ?^ active + `this-tapp + start-trad + :: + :: Receive subscription response + :: + ++ diff + |= [=wire =in-peer-data] + ^- (quip move _this-tapp) + ?> ?=([@ @ *] wire) + =/ her (slav %p i.wire) + =* app i.t.wire + =* pax t.t.wire + =. waiting (~(put to waiting) %diff [her app] pax in-peer-data) + ?^ active + `this-tapp + start-trad + :: :: Pass response to trad :: ++ sigh-httr @@ -106,7 +213,12 @@ ++ fail-trad |= [contracts=(set contract) err=(pair term tang)] ^- (quip move _this-tapp) - %- (slog leaf+"tapp command failed" leaf+(trip p.err) q.err) + %- %- slog + :* leaf+(trip dap.bowl) + leaf+"tapp command failed" + leaf+(trip p.err) + q.err + == (finish-trad contracts) :: :: Called on trad success @@ -135,15 +247,18 @@ ^- (quip move _this-tapp) ?. =(~ active) ~| %trad-already-active !! - =/ next=(unit command-type) ~(top to waiting) + =/ next=(unit command) ~(top to waiting) ?~ next `this-tapp =. active :- ~ - ^- eval-form:eval:tapp-trad %- from-form:eval:tapp-trad ^- form:tapp-trad - (~(handle-command handler bowl app-state) u.next) + ?- -.u.next + %poke (~(handle-command handler bowl app-state) command.u.next) + %peer (~(handle-peer handler bowl app-state) path.u.next) + %diff (~(handle-diff handler bowl app-state) +.u.next) + == (take-trad bowl ~) :: :: Cancel outstanding contracts diff --git a/lib/trad.hoon b/lib/trad.hoon index 36eeedf05..f032896a7 100644 --- a/lib/trad.hoon +++ b/lib/trad.hoon @@ -3,22 +3,23 @@ +$ trad-input [=bowl:gall in=(unit [=wire sign=input-type])] +$ trad-move (pair bone card-type) :: -:: notes: notes to send immediately. These will go out even if a -:: later stage of the process fails, so they shouldn't have any -:: semantic effect on the rest of the system. Path is -:: included exclusively for documentation and |verb. -:: effects: moves to send after the process ends. -:: wait: don't move on, stay here. The next sign should come back -:: to this same callback. -:: cont: continue process with new callback. -:: fail: abort process; don't send effects -:: done: finish process; send effects +:: notes: notes to send immediately. These will go out even if a +:: later stage of the process fails, so they shouldn't have +:: any semantic effect on the rest of the system. Path is +:: included exclusively for documentation and |verb. +:: effects: moves to send after the process ends. +:: contracts: stuff to cancel at end of transaction. +:: wait: don't move on, stay here. The next sign should come back +:: to this same callback. +:: cont: continue process with new callback. +:: fail: abort process; don't send effects +:: done: finish process; send effects :: ++ trad-output-raw |* a=mold $~ [~ ~ ~ %done *a] $: notes=(list [path card-type]) - effects=(list card-type) + effects=(list trad-move) contracts=(set [add=? contract=contract-type]) $= next $% [%wait ~] @@ -72,7 +73,7 @@ :: Indelible state of a trad :: +$ eval-form - $: effects=(list card-type) + $: effects=(list trad-move) contracts=(set contract-type) =form == @@ -149,10 +150,7 @@ =? moves ?=(%done -.next.output) %+ welp moves - %+ turn effects.eval-form - |= card=card-type - ^- trad-move - [bone card] + effects.eval-form :: case-wise handle next steps :: ?- -.next.output diff --git a/sur/tapp.hoon b/sur/tapp.hoon index 3e2cce9da..a53cb0414 100644 --- a/sur/tapp.hoon +++ b/sur/tapp.hoon @@ -1,4 +1,4 @@ -|* poke-data=mold +|* [poke-data=mold out-peer-data=mold] |% :: :: Possible async calls @@ -9,6 +9,9 @@ [%wait wire @da] [%rest wire @da] [%poke wire dock poke-data] + [%peer wire dock path] + [%pull wire dock ~] + [%diff out-peer-data] == :: :: Possible async responses From 4c93a6f6e952e1ea79eebe616b30ab97c0469c73 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 16:06:53 -0700 Subject: [PATCH 08/12] generalize poke in lib/tapp --- app/baby.hoon | 6 +++--- app/sitter.hoon | 4 ++-- lib/tapp.hoon | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index 11081b3b5..a6d99c5a1 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -12,7 +12,7 @@ +$ state $: top-comments=(list tape) == - +$ command cord + +$ command [%noun =cord] +$ poke-data $% [%noun cord] == @@ -63,7 +63,7 @@ :: :: If requested to print, just print what we have in our state :: - ?: =(command 'print') + ?: =(cord.command 'print') ~& 'drumroll please...' ;< now=@da bind:m get-time ;< ~ bind:m (wait (add now ~s3)) @@ -92,7 +92,7 @@ :: ?~ top-stories ;< ~ bind:m (give-result /comments %comments top-comments) - (handle-command 'print') + (handle-command %noun 'print') :: :: Else, fetch the story info :: diff --git a/app/sitter.hoon b/app/sitter.hoon index 0f80cac79..625d16a20 100644 --- a/app/sitter.hoon +++ b/app/sitter.hoon @@ -8,7 +8,7 @@ +$ state $: subscription=(unit subscription-state) == - +$ command cord + +$ command [%noun =cord] +$ poke-data $% [%noun cord] == @@ -29,7 +29,7 @@ |= =command =/ m tapp-trad ^- form:m - ?: =(command 'pull') + ?: =(cord.command 'pull') ?~ subscription (trad-fail %no-subscription ~) ;< ~ bind:m (pull-app [target path]:u.subscription) diff --git a/lib/tapp.hoon b/lib/tapp.hoon index a5716f005..43a60b4d1 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -125,7 +125,7 @@ :: :: Start a command :: - ++ poke-noun + ++ poke |= command=command-type ^- (quip move _this-tapp) =. waiting (~(put to waiting) %poke command) From c48f9422641bdae715b9fb5e0b1484be73176d28 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 17:01:18 -0700 Subject: [PATCH 09/12] add effectful timers --- app/baby.hoon | 16 +++++++++++-- lib/stdio.hoon | 10 +++++++- lib/tapp.hoon | 65 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index a6d99c5a1..02111e375 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -50,8 +50,8 @@ :: :: The app :: -%- create-tapp-poke-peer:tapp -^- tapp-core-poke-peer:tapp +%- create-tapp-poke-peer-take:tapp +^- tapp-core-poke-peer-take:tapp |_ [=bowl:gall state] :: :: Main function @@ -70,6 +70,9 @@ ~& 'Top comments:' %- (slog (zing (turn top-comments comment-to-tang))) (pure:m top-comments) + ?: =(cord.command 'poll') + ;< ~ bind:m (wait-effect (add now.bowl ~s15)) + (pure:m top-comments) :: :: Otherwise, fetch the top HN stories :: @@ -130,4 +133,13 @@ ^- form:m ~& [%baby-take-peer path] (pure:m top-comments) +:: +++ handle-take + |= sign:tapp + =/ m tapp-trad + ^- form:m + ;< =state bind:m (handle-command %noun 'fetch') + =. top-comments state + (pure:m top-comments) + :: (handle-command %noun 'poll') -- diff --git a/lib/stdio.hoon b/lib/stdio.hoon index ea30c1192..459dd2912 100644 --- a/lib/stdio.hoon +++ b/lib/stdio.hoon @@ -147,7 +147,7 @@ |= at=@da =/ m (trad ,~) ^- form:m - ;< ~ bind:m (send-raw-card %wait /(scot %da at) at) + ;< ~ bind:m (send-raw-card %wait /note/(scot %da at) at) (set-raw-contract & %wait at) :: :: Wait until we get a wake event @@ -185,6 +185,14 @@ ;< ~ bind:m (send-wait until) take-wake :: +:: Wait until time then start new computation +:: +++ wait-effect + |= until=@da + =/ m (trad ,~) + ^- form:m + (send-effect %wait /effect/(scot %da until) until) +:: :: Cancel computation if not done by time :: ++ set-timeout diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 43a60b4d1..553e490c8 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -15,6 +15,7 @@ $% [%poke command=command-type] [%peer =path] [%diff =dock =path =in-peer-data] + [%take =sign] == :: ++ trad-lib (^trad sign card contract) @@ -67,6 +68,7 @@ ++ handle-command ~(handle-command handler bowl state) ++ handle-peer ~(handle-peer handler bowl state) ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) + ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) -- :: :: The form of a tapp that only handles pokes and diffs @@ -88,8 +90,37 @@ %- create-tapp-all |_ [=bowl:gall state=state-type] ++ handle-command ~(handle-command handler bowl state) - ++ handle-peer |=(=path (trad-fail:trad-lib %no-peer-handler >path< ~)) + ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) ++ handle-diff ~(handle-diff handler bowl state) + ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) + -- +:: +:: The form of a tapp that only handles pokes, peers, and takes +:: +++ tapp-core-poke-peer-take + $_ ^| + |_ [bowl:gall state-type] + ++ handle-command + |~ command-type + *form:tapp-trad + :: + ++ handle-peer + |~ path + *form:tapp-trad + :: + ++ handle-take + |~ sign + *form:tapp-trad + -- +:: +++ create-tapp-poke-peer-take + |= handler=tapp-core-poke-peer-take + %- create-tapp-all + |_ [=bowl:gall state=state-type] + ++ handle-command ~(handle-command handler bowl state) + ++ handle-peer ~(handle-peer handler bowl state) + ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) + ++ handle-take ~(handle-take handler bowl state) -- :: :: The form of a tapp @@ -97,17 +128,30 @@ ++ tapp-core-all $_ ^| |_ [bowl:gall state-type] + :: + :: Input + :: ++ handle-command |~ command-type *form:tapp-trad :: + :: Subscription request + :: ++ handle-peer |~ path *form:tapp-trad :: + :: Receive subscription result + :: ++ handle-diff |~ [dock path in-peer-data] *form:tapp-trad + :: + :: Receive syscall result + :: + ++ handle-take + |~ sign + *form:tapp-trad -- :: ++ create-tapp-all @@ -172,13 +216,21 @@ ^- (quip move _this-tapp) (oob-fail-trad %failed-sigh tang) :: - ++ wake + ++ wake-note |= [=wire error=(unit tang)] ^- (quip move _this-tapp) ?^ error (oob-fail-trad %timer-fire-failed u.error) (take-trad bowl `[wire %wake ~]) :: + ++ wake-effect + |= [=wire error=(unit tang)] + ^- (quip move _this-tapp) + =. waiting (~(put to waiting) %take %wake error) + ?^ active + `this-tapp + start-trad + :: :: Continue computing trad :: ++ take-trad @@ -191,7 +243,11 @@ :: ?: ?=([~ @ %sigh *] in.trad-input) `this-tapp - ~| %no-active-trad !! + ~| %no-active-trad + ~| ?~ in.trad-input + ~ + wire.u.in.trad-input + !! =^ r=[moves=(list move) =eval-result:eval:m] u.active (take:eval:m u.active ost.bowl trad-input) => .(active `(unit eval-form:eval:tapp-trad)`active) :: TMI @@ -258,6 +314,7 @@ %poke (~(handle-command handler bowl app-state) command.u.next) %peer (~(handle-peer handler bowl app-state) path.u.next) %diff (~(handle-diff handler bowl app-state) +.u.next) + %take (~(handle-take handler bowl app-state) +.u.next) == (take-trad bowl ~) :: @@ -274,7 +331,7 @@ |= =contract ^- (list move) ?- -.contract - %wait [ost.bowl %rest /(scot %da at.contract) at.contract]~ + %wait [ost.bowl %rest /note/(scot %da at.contract) at.contract]~ %hiss ~ :: can't cancel; will ignore response == -- From 87e50458fc99e2f1af446b9a6197b7a912a76df3 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 28 May 2019 17:11:21 -0700 Subject: [PATCH 10/12] rename command -> poke --- app/baby.hoon | 26 +++++++++---------- app/sitter.hoon | 16 ++++++------ lib/tapp.hoon | 67 ++++++++++++++++++++++++------------------------- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/app/baby.hoon b/app/baby.hoon index 02111e375..c01cc4b58 100644 --- a/app/baby.hoon +++ b/app/baby.hoon @@ -12,16 +12,14 @@ +$ state $: top-comments=(list tape) == - +$ command [%noun =cord] - +$ poke-data - $% [%noun cord] - == + +$ in-poke-data [%noun =cord] + +$ out-poke-data ~ + +$ in-peer-data ~ +$ out-peer-data $% [%comments (list tape)] == - +$ in-peer-data ~ - ++ tapp (^tapp state command poke-data out-peer-data in-peer-data) - ++ stdio (^stdio poke-data out-peer-data) + ++ tapp (^tapp state in-poke-data out-poke-data in-peer-data out-peer-data) + ++ stdio (^stdio out-poke-data out-peer-data) -- => |% @@ -56,21 +54,21 @@ :: :: Main function :: -++ handle-command - |= =command +++ handle-poke + |= =in-poke-data =/ m tapp-trad ^- form:m :: :: If requested to print, just print what we have in our state :: - ?: =(cord.command 'print') + ?: =(cord.in-poke-data 'print') ~& 'drumroll please...' ;< now=@da bind:m get-time ;< ~ bind:m (wait (add now ~s3)) ~& 'Top comments:' %- (slog (zing (turn top-comments comment-to-tang))) (pure:m top-comments) - ?: =(cord.command 'poll') + ?: =(cord.in-poke-data 'poll') ;< ~ bind:m (wait-effect (add now.bowl ~s15)) (pure:m top-comments) :: @@ -95,7 +93,7 @@ :: ?~ top-stories ;< ~ bind:m (give-result /comments %comments top-comments) - (handle-command %noun 'print') + (handle-poke %noun 'print') :: :: Else, fetch the story info :: @@ -138,8 +136,8 @@ |= sign:tapp =/ m tapp-trad ^- form:m - ;< =state bind:m (handle-command %noun 'fetch') + ;< =state bind:m (handle-poke %noun 'fetch') =. top-comments state (pure:m top-comments) - :: (handle-command %noun 'poll') + :: (handle-poke %noun 'poll') -- diff --git a/app/sitter.hoon b/app/sitter.hoon index 625d16a20..242899bd3 100644 --- a/app/sitter.hoon +++ b/app/sitter.hoon @@ -8,16 +8,14 @@ +$ state $: subscription=(unit subscription-state) == - +$ command [%noun =cord] - +$ poke-data - $% [%noun cord] - == + +$ in-poke-data [%noun =cord] + +$ out-poke-data [%noun =cord] +$ out-peer-data ~ +$ in-peer-data $% [%comments comments=(list tape)] == - ++ tapp (^tapp state command poke-data out-peer-data in-peer-data) - ++ stdio (^stdio poke-data out-peer-data) + ++ tapp (^tapp state in-poke-data out-poke-data in-peer-data out-peer-data) + ++ stdio (^stdio out-poke-data out-peer-data) -- =, trad=trad:tapp =, tapp-trad=tapp-trad:tapp @@ -25,11 +23,11 @@ %- create-tapp-poke-diff:tapp ^- tapp-core-poke-diff:tapp |_ [=bowl:gall state] -++ handle-command - |= =command +++ handle-poke + |= =in-poke-data =/ m tapp-trad ^- form:m - ?: =(cord.command 'pull') + ?: =(cord.in-poke-data 'pull') ?~ subscription (trad-fail %no-subscription ~) ;< ~ bind:m (pull-app [target path]:u.subscription) diff --git a/lib/tapp.hoon b/lib/tapp.hoon index 553e490c8..b97fa4295 100644 --- a/lib/tapp.hoon +++ b/lib/tapp.hoon @@ -1,18 +1,18 @@ /- tapp-sur=tapp /+ trad |* $: state-type=mold - command-type=mold - poke-data=mold - out-peer-data=mold + in-poke-data=mold + out-poke-data=mold in-peer-data=mold + out-peer-data=mold == |% -++ tapp-sur (^tapp-sur poke-data out-peer-data) +++ tapp-sur (^tapp-sur out-poke-data out-peer-data) ++ card card:tapp-sur ++ sign sign:tapp-sur ++ contract contract:tapp-sur ++ command - $% [%poke command=command-type] + $% [%poke =in-poke-data] [%peer =path] [%diff =dock =path =in-peer-data] [%take =sign] @@ -34,8 +34,8 @@ ++ tapp-core-poke $_ ^| |_ [bowl:gall state-type] - ++ handle-command - |~ command-type + ++ handle-poke + |~ in-poke-data *form:tapp-trad -- :: @@ -43,8 +43,8 @@ |= handler=tapp-core-poke %- create-tapp-poke-peer |_ [=bowl:gall state=state-type] - ++ handle-command ~(handle-command handler bowl state) - ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) + ++ handle-poke ~(handle-poke handler bowl state) + ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) -- :: :: The form of a tapp that only handles pokes and peers @@ -52,8 +52,8 @@ ++ tapp-core-poke-peer $_ ^| |_ [bowl:gall state-type] - ++ handle-command - |~ command-type + ++ handle-poke + |~ in-poke-data *form:tapp-trad :: ++ handle-peer @@ -65,10 +65,10 @@ |= handler=tapp-core-poke-peer %- create-tapp-all |_ [=bowl:gall state=state-type] - ++ handle-command ~(handle-command handler bowl state) - ++ handle-peer ~(handle-peer handler bowl state) - ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) - ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) + ++ handle-poke ~(handle-poke handler bowl state) + ++ handle-peer ~(handle-peer handler bowl state) + ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) + ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) -- :: :: The form of a tapp that only handles pokes and diffs @@ -76,8 +76,8 @@ ++ tapp-core-poke-diff $_ ^| |_ [bowl:gall state-type] - ++ handle-command - |~ command-type + ++ handle-poke + |~ in-poke-data *form:tapp-trad :: ++ handle-diff @@ -89,10 +89,10 @@ |= handler=tapp-core-poke-diff %- create-tapp-all |_ [=bowl:gall state=state-type] - ++ handle-command ~(handle-command handler bowl state) - ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) - ++ handle-diff ~(handle-diff handler bowl state) - ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) + ++ handle-poke ~(handle-poke handler bowl state) + ++ handle-peer |=(* (trad-fail:trad-lib %no-peer-handler >path< ~)) + ++ handle-diff ~(handle-diff handler bowl state) + ++ handle-take |=(* (trad-fail:trad-lib %no-take-handler >path< ~)) -- :: :: The form of a tapp that only handles pokes, peers, and takes @@ -100,8 +100,8 @@ ++ tapp-core-poke-peer-take $_ ^| |_ [bowl:gall state-type] - ++ handle-command - |~ command-type + ++ handle-poke + |~ in-poke-data *form:tapp-trad :: ++ handle-peer @@ -117,10 +117,10 @@ |= handler=tapp-core-poke-peer-take %- create-tapp-all |_ [=bowl:gall state=state-type] - ++ handle-command ~(handle-command handler bowl state) - ++ handle-peer ~(handle-peer handler bowl state) - ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) - ++ handle-take ~(handle-take handler bowl state) + ++ handle-poke ~(handle-poke handler bowl state) + ++ handle-peer ~(handle-peer handler bowl state) + ++ handle-diff |=(* (trad-fail:trad-lib %no-diff-handler >path< ~)) + ++ handle-take ~(handle-take handler bowl state) -- :: :: The form of a tapp @@ -131,8 +131,8 @@ :: :: Input :: - ++ handle-command - |~ command-type + ++ handle-poke + |~ in-poke-data *form:tapp-trad :: :: Subscription request @@ -170,9 +170,9 @@ :: Start a command :: ++ poke - |= command=command-type + |= =in-poke-data ^- (quip move _this-tapp) - =. waiting (~(put to waiting) %poke command) + =. waiting (~(put to waiting) %poke in-poke-data) ?^ active ~& [%waiting-until-current-trad-finishes waiting] `this-tapp @@ -296,7 +296,6 @@ =^ moves-2 this-tapp start-trad [(weld moves-1 moves-2) this-tapp] :: - :: :: Try to start next command :: ++ start-trad @@ -311,8 +310,8 @@ %- from-form:eval:tapp-trad ^- form:tapp-trad ?- -.u.next - %poke (~(handle-command handler bowl app-state) command.u.next) - %peer (~(handle-peer handler bowl app-state) path.u.next) + %poke (~(handle-poke handler bowl app-state) +.u.next) + %peer (~(handle-peer handler bowl app-state) +.u.next) %diff (~(handle-diff handler bowl app-state) +.u.next) %take (~(handle-take handler bowl app-state) +.u.next) == From b7d5d52315de2d8a4f2b7b380af9bd8a01861ef5 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Thu, 30 May 2019 10:24:52 -0700 Subject: [PATCH 11/12] rename apps --- app/{baby.hoon => example-tapp-fetch.hoon} | 2 +- app/{sitter.hoon => example-tapp-subscribe.hoon} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename app/{baby.hoon => example-tapp-fetch.hoon} (99%) rename app/{sitter.hoon => example-tapp-subscribe.hoon} (80%) diff --git a/app/baby.hoon b/app/example-tapp-fetch.hoon similarity index 99% rename from app/baby.hoon rename to app/example-tapp-fetch.hoon index c01cc4b58..80dd837c2 100644 --- a/app/baby.hoon +++ b/app/example-tapp-fetch.hoon @@ -129,7 +129,7 @@ |= =path =/ m tapp-trad ^- form:m - ~& [%baby-take-peer path] + ~& [%tapp-fetch-take-peer path] (pure:m top-comments) :: ++ handle-take diff --git a/app/sitter.hoon b/app/example-tapp-subscribe.hoon similarity index 80% rename from app/sitter.hoon rename to app/example-tapp-subscribe.hoon index 242899bd3..b6510dd1c 100644 --- a/app/sitter.hoon +++ b/app/example-tapp-subscribe.hoon @@ -32,9 +32,9 @@ (trad-fail %no-subscription ~) ;< ~ bind:m (pull-app [target path]:u.subscription) (pure:m ~) - ;< ~ bind:m (poke-app [our.bowl %baby] %noun 'print') - ;< ~ bind:m (peer-app [our.bowl %baby] /comments) - =. subscription `[[our.bowl %baby] /comments] + ;< ~ bind:m (poke-app [our.bowl %example-tapp-fetch] %noun 'print') + ;< ~ bind:m (peer-app [our.bowl %example-tapp-fetch] /comments) + =. subscription `[[our.bowl %example-tapp-fetch] /comments] ;< ~ bind:m (wait (add now.bowl ~s3)) (pure:m subscription) :: @@ -43,6 +43,6 @@ =/ m tapp-trad ^- form:m ?> ?=(%comments -.data) - ~& sitter-got-data=(lent comments.data) + ~& subscriber-got-data=(lent comments.data) (pure:m subscription) -- From 852e74cb51c55ca9ff98c97f810aee4641a0c194 Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Thu, 30 May 2019 14:43:27 -0700 Subject: [PATCH 12/12] fix fang's suggestions --- app/example-tapp-fetch.hoon | 5 ++-- app/example-tapp-subscribe.hoon | 7 ++--- lib/stdio.hoon | 2 +- lib/trad.hoon | 48 +++++++++++++++++++++++---------- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/app/example-tapp-fetch.hoon b/app/example-tapp-fetch.hoon index 80dd837c2..f44abdae6 100644 --- a/app/example-tapp-fetch.hoon +++ b/app/example-tapp-fetch.hoon @@ -41,7 +41,7 @@ :* top-stories=(weld base "topstories.json") item=|=(item=@ud `tape`:(welp base "item/" +>:(scow %ui item) ".json")) == --- + -- =, trad=trad:tapp =, tapp-trad=tapp-trad:tapp =, stdio @@ -89,7 +89,7 @@ |- ^- form:m =* loop $ :: - :: If done, tell subscriers and print the results + :: If done, tell subscribers and print the results :: ?~ top-stories ;< ~ bind:m (give-result /comments %comments top-comments) @@ -139,5 +139,4 @@ ;< =state bind:m (handle-poke %noun 'fetch') =. top-comments state (pure:m top-comments) - :: (handle-poke %noun 'poll') -- diff --git a/app/example-tapp-subscribe.hoon b/app/example-tapp-subscribe.hoon index b6510dd1c..68901f95b 100644 --- a/app/example-tapp-subscribe.hoon +++ b/app/example-tapp-subscribe.hoon @@ -32,9 +32,10 @@ (trad-fail %no-subscription ~) ;< ~ bind:m (pull-app [target path]:u.subscription) (pure:m ~) - ;< ~ bind:m (poke-app [our.bowl %example-tapp-fetch] %noun 'print') - ;< ~ bind:m (peer-app [our.bowl %example-tapp-fetch] /comments) - =. subscription `[[our.bowl %example-tapp-fetch] /comments] + =/ target [our.bowl %example-tapp-fetch] + ;< ~ bind:m (poke-app target %noun 'print') + ;< ~ bind:m (peer-app target /comments) + =. subscription `[target /comments] ;< ~ bind:m (wait (add now.bowl ~s3)) (pure:m subscription) :: diff --git a/lib/stdio.hoon b/lib/stdio.hoon index 459dd2912..6a631979a 100644 --- a/lib/stdio.hoon +++ b/lib/stdio.hoon @@ -27,7 +27,7 @@ =/ m (trad ,~) ^- form:m |= =trad-input - [[/ card]~ ~ ~ %done ~] + [[card]~ ~ ~ %done ~] :: :: Add or remove a contract :: diff --git a/lib/trad.hoon b/lib/trad.hoon index f032896a7..f058e6043 100644 --- a/lib/trad.hoon +++ b/lib/trad.hoon @@ -3,22 +3,24 @@ +$ trad-input [=bowl:gall in=(unit [=wire sign=input-type])] +$ trad-move (pair bone card-type) :: -:: notes: notes to send immediately. These will go out even if a -:: later stage of the process fails, so they shouldn't have -:: any semantic effect on the rest of the system. Path is -:: included exclusively for documentation and |verb. -:: effects: moves to send after the process ends. -:: contracts: stuff to cancel at end of transaction. +:: cards: cards to send immediately. These will go out even if a +:: later stage of the computation fails, so they shouldn't have +:: any semantic effect on the rest of the system. +:: Alternately, they may record an entry in contracts with +:: enough information to undo the effect if the computation +:: fails. +:: effects: moves to send after the computation ends. +:: contracts: stuff to cancel at end of computation. :: wait: don't move on, stay here. The next sign should come back :: to this same callback. -:: cont: continue process with new callback. -:: fail: abort process; don't send effects -:: done: finish process; send effects +:: cont: continue computation with new callback. +:: fail: abort computation; don't send effects +:: done: finish computation; send effects :: ++ trad-output-raw |* a=mold $~ [~ ~ ~ %done *a] - $: notes=(list [path card-type]) + $: cards=(list card-type) effects=(list trad-move) contracts=(set [add=? contract=contract-type]) $= next @@ -33,22 +35,40 @@ |* a=mold $-(trad-input (trad-output-raw a)) :: +:: Abort asynchronous computation with error message +:: ++ trad-fail |= err=(pair term tang) |= trad-input [~ ~ ~ %fail err] :: +:: Asynchronous transcaction monad. +:: +:: Combo of four monads: +:: - Reader on input-type +:: - Writer on card-type +:: - Continuation +:: - Exception +:: ++ trad |* a=mold |% ++ output (trad-output-raw a) + :: + :: Type of an asynchronous computation. + :: ++ form (trad-form-raw a) + :: + :: Monadic pure. Identity computation for bind. + :: ++ pure |= arg=a ^- form |= trad-input [~ ~ ~ %done arg] :: + :: Monadic bind. Combines two computations, associatively. + :: ++ bind |* b=mold |= [m-b=(trad-form-raw b) fun=$-(b form)] @@ -57,7 +77,7 @@ =/ b-res=(trad-output-raw b) (m-b input) ^- output - :^ notes.b-res effects.b-res contracts.b-res + :^ cards.b-res effects.b-res contracts.b-res ?- -.next.b-res %wait [%wait ~] %cont [%cont ..$(m-b self.next.b-res)] @@ -105,13 +125,13 @@ :: run the trad callback :: =/ =output (form.eval-form trad-input) - :: add notes to moves + :: add cards to moves :: =. moves %+ welp moves - %+ turn notes.output - |= [=path card=card-type] + %+ turn cards.output + |= card=card-type ^- trad-move [bone card] :: add effects to list to be produced when done