shrub/app/example-tapp-fetch.hoon

148 lines
3.6 KiB
Plaintext
Raw Normal View History

2019-05-25 05:42:37 +03:00
:: 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
::
2019-05-26 05:17:18 +03:00
/+ tapp, stdio
2019-05-23 22:26:53 +03:00
::
:: Preamble
::
=>
|%
+$ state
2019-05-25 05:42:37 +03:00
$: top-comments=(list tape)
2019-05-23 22:26:53 +03:00
==
+$ peek-data _!!
2019-05-29 03:11:21 +03:00
+$ in-poke-data [%noun =cord]
+$ out-poke-data ~
+$ in-peer-data ~
2019-05-29 01:38:14 +03:00
+$ out-peer-data
$% [%comments (list tape)]
==
++ tapp (^tapp state peek-data in-poke-data out-poke-data in-peer-data out-peer-data)
2019-05-29 03:11:21 +03:00
++ stdio (^stdio out-poke-data out-peer-data)
2019-05-23 22:26:53 +03:00
--
2019-05-25 05:42:37 +03:00
=>
|%
:: 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"))
==
2019-05-31 00:43:27 +03:00
--
2019-06-01 00:44:47 +03:00
=, async=async:tapp
=, tapp-async=tapp-async:tapp
2019-05-26 05:17:18 +03:00
=, stdio
2019-05-23 22:26:53 +03:00
::
:: The app
::
2019-05-29 03:01:18 +03:00
%- create-tapp-poke-peer-take:tapp
^- tapp-core-poke-peer-take:tapp
2019-05-23 22:26:53 +03:00
|_ [=bowl:gall state]
2019-05-25 05:42:37 +03:00
::
:: Main function
::
2019-05-29 03:11:21 +03:00
++ handle-poke
|= =in-poke-data
2019-06-01 00:44:47 +03:00
=/ m tapp-async
2019-05-23 22:26:53 +03:00
^- form:m
2019-05-25 05:42:37 +03:00
::
:: If requested to print, just print what we have in our state
::
2019-05-29 03:11:21 +03:00
?: =(cord.in-poke-data 'print')
2019-05-26 05:17:18 +03:00
~& 'drumroll please...'
;< now=@da bind:m get-time
;< ~ bind:m (wait (add now ~s3))
2019-05-25 05:42:37 +03:00
~& 'Top comments:'
%- (slog (zing (turn top-comments comment-to-tang)))
(pure:m top-comments)
2019-05-29 03:11:21 +03:00
?: =(cord.in-poke-data 'poll')
2019-05-29 03:01:18 +03:00
;< ~ bind:m (wait-effect (add now.bowl ~s15))
(pure:m top-comments)
2019-05-25 05:42:37 +03:00
::
:: Otherwise, fetch the top HN stories
::
=. top-comments ~
2019-05-26 05:17:18 +03:00
::
:: If this whole thing takes more than 15 seconds, cancel it
2019-05-26 05:17:18 +03:00
::
%+ (set-timeout _top-comments) (add now.bowl ~s15)
2019-05-25 05:42:37 +03:00
;< =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 5 stories
2019-05-25 05:42:37 +03:00
::
=. top-stories (scag 5 top-stories)
2019-05-25 05:42:37 +03:00
|- ^- form:m
=* loop $
::
2019-05-31 00:43:27 +03:00
:: If done, tell subscribers and print the results
2019-05-25 05:42:37 +03:00
::
?~ top-stories
2019-05-29 01:38:14 +03:00
;< ~ bind:m (give-result /comments %comments top-comments)
2019-05-29 03:11:21 +03:00
(handle-poke %noun 'print')
2019-05-25 05:42:37 +03:00
::
:: 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 ["<no top comment>" 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 comment has no text>" 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)
2019-05-29 01:38:14 +03:00
::
++ handle-peer
|= =path
2019-06-01 00:44:47 +03:00
=/ m tapp-async
2019-05-29 01:38:14 +03:00
^- form:m
2019-05-30 20:24:52 +03:00
~& [%tapp-fetch-take-peer path]
2019-05-29 01:38:14 +03:00
(pure:m top-comments)
2019-05-29 03:01:18 +03:00
::
++ handle-take
|= =sign:tapp
2019-06-01 00:44:47 +03:00
=/ m tapp-async
2019-05-29 03:01:18 +03:00
^- form:m
:: ignore %poke/peer acknowledgements
::
?. ?=(%wake -.sign)
(pure:m top-comments)
2019-05-29 03:11:21 +03:00
;< =state bind:m (handle-poke %noun 'fetch')
2019-05-29 03:01:18 +03:00
=. top-comments state
(pure:m top-comments)
2019-05-23 22:26:53 +03:00
--