From 80d973dae03f6162f79e43c440f89eb818dddbfe Mon Sep 17 00:00:00 2001 From: Tinnus Napbus Date: Wed, 12 Jul 2023 03:41:53 +1200 Subject: [PATCH] bring gall documentation up-to-date --- content/reference/arvo/gall/_index.md | 17 + content/reference/arvo/gall/data-types.md | 340 +++-- content/reference/arvo/gall/gall-api.md | 1455 ++++++++------------- content/reference/arvo/gall/gall.md | 23 +- content/reference/arvo/gall/scry.md | 22 + content/reference/arvo/gall/threads.md | 86 -- 6 files changed, 805 insertions(+), 1138 deletions(-) delete mode 100644 content/reference/arvo/gall/threads.md diff --git a/content/reference/arvo/gall/_index.md b/content/reference/arvo/gall/_index.md index 9177d01..d3152c9 100644 --- a/content/reference/arvo/gall/_index.md +++ b/content/reference/arvo/gall/_index.md @@ -4,3 +4,20 @@ weight = 70 sort_by = "weight" insert_anchor_links = "right" +++ + +## [Overview](/reference/arvo/gall/gall) + +An overview of Eyre and its capabilities. + +## [API Reference](/reference/arvo/gall/gall-api) + +Reference documentation of both Gall's vane API and the API available to +agents. + +## [Scry Reference](/reference/arvo/gall/scry) + +Reference documentation of Gall scry endpoints. + +## [Data Types](/reference/arvo/gall/data-types) + +Reference documentation of Gall's types as defined in `lull.hoon`. diff --git a/content/reference/arvo/gall/data-types.md b/content/reference/arvo/gall/data-types.md index 5779d97..8f0a5fe 100644 --- a/content/reference/arvo/gall/data-types.md +++ b/content/reference/arvo/gall/data-types.md @@ -5,41 +5,60 @@ weight = 5 This document describes the data types for Gall defined in `lull.hoon`. + ## `bitt` +Incoming subscriptions. + ```hoon +$ bitt (map duct (pair ship path)) ``` -Incoming subscriptions. +This is the structure Gall uses to keep track of incoming subscriptions +for a Gall agent. The `sup` field of a [`bowl`](#bowl) contains the +`bitt` for our agent. -This is the structure Gall uses to keep track of subscribers to our Gall agent. -The `sup` field of a [`bowl`](#bowl) contains the `bitt` for our agent. +--- ## `boat` -```hoon -+$ boat - %+ map [=wire =ship =term] - [acked=? =path] -``` - Outgoing subscriptions. -This is the structure Gall uses to keep track of subscriptions our agent has -initiated. The `wex` field of a [`bowl`](#bowl) contails the `boat` for that -agent. +```hoon ++$ boat (map [=wire =ship =term] [acked=? =path]) +``` -The `wire` field is the `wire` which [`sign:agent`](#signagent)s will come in on. -The `ship` and `term` fields are the ship and the name of the agent to which our -agent has subscribed. +This is the structure Gall uses to keep track of subscriptions our agent +has initiated. The `wex` field of a [`bowl`](#bowl) contails the `boat` +for that agent. -The `acked` field is `%.y` if they have acknowledged our subscription request, -and `%.n` if they have not. The `path` field is the `path` on the other agent to -which our agent has subscribed. +The `wire` field is the `wire` which [`sign:agent`](#signagent)s will +come in on. The `ship` and `term` fields are the ship and the name of +the agent to which our agent has subscribed. + +The `acked` field is `%.y` if they have acknowledged our subscription +request with a `%watch-ack`, and `%.n` if they have not. The `path` +field is the `path` on the other agent to which our agent has +subscribed. + +--- + +## `boar` + +Subscription nonces. + +```hoon ++$ boar (map [=wire =ship =term] nonce=@) +``` + +Gall uses this to keep track of nonces for subscriptions. + +--- ## `bowl` +Additional agent state. + ```hoon +$ bowl :: standard app state $: $: our=ship :: host @@ -56,11 +75,9 @@ which our agent has subscribed. eny=@uvJ :: entropy now=@da :: current time byk=beak :: load source - == == :: :: + == == :: ``` -Additional agent state. - A `bowl` is given to the agent core each time an event comes in. The fields are as follows: @@ -82,24 +99,49 @@ as follows: `case` will be `[%da @da]` where the `@da` is the when the agent was loaded. A `beak` is a triple of `[ship desk case]`. +--- + ## `dude` +Agent name. + ```hoon +$ dude term ``` -Agent name. +--- ## `gill` +A general contact. + ```hoon +$ gill (pair ship term) ``` -A general contact: A pair of the ship and agent name. +A pair of the ship and agent name. + +--- + +## `load` + +Loadout. + +```hoon ++$ load (list [=dude =beak =agent]) +``` + +The [`dude`](#dude) is the agent name, the `beak` is the ship/desk/case +in which it resides, and the [`agent`](#agent) is the built agent +itself. Clay passes this to Gall when it builds or modifies the state of +running agents. + +--- ## `scar` +Opaque duct - used internally. + ```hoon +$ scar $: p=@ud @@ -108,40 +150,30 @@ A general contact: A pair of the ship and agent name. == ``` -Opaque duct - used internally. +--- ## `suss` +Configuration report. + ```hoon +$ suss (trel dude @tas @da) ``` -Configuration report. +--- ## `well` +Desk and agent. + ```hoon +$ well (pair desk term) ``` -Desk and agent. - -## `neat` - -```hoon -+$ neat - $% [%arvo =note-arvo] - [%agent [=ship name=term] =deal] - [%pyre =tang] - == -``` - -Like a [`note:agent`](#noteagent), except the `%agent` case has a [`deal`](#deal) instead -of just a [`task:agent`](#taskagent). This is used for messages that come in over the -network and would not be used manually. - ## `deal` +An agent task or raw poke. + ```hoon +$ deal $% [%raw-poke =mark =noun] @@ -149,12 +181,17 @@ network and would not be used manually. == ``` -Like a [`task:agent`](#taskagent) but with the additional case of a raw poke. -This is used for messages that come in over the network and would not be used -manually. +The additional `%raw-poke` is for pokes which haven't yet been converted +to an ordinary `%poke` by molding the `noun` with the specified `mark` +core. This structure is passed around on the kernel level, it would not +be used in userspace. + +--- ## `unto` +An agent gift or a raw fact. + ```hoon +$ unto $% [%raw-fact =mark =noun] @@ -162,9 +199,24 @@ manually. == ``` -Like a [`sign:agent`](#signagent) but with the additional case of a raw fact. -This is used for messages that come in over the network and would not be used -manually. +The additional `%raw-fact` is for facts which haven't yet been converted +to an ordinary `%fact` by molding the `noun` it with the specified +`mark` core. This structure is passed around on the kernel level, it +would not be used in userspace. + +--- + +## `verb` + +Verbosity flags. + +```hoon ++$ verb ?(%odd) +``` + +Flags to set Gall verbosity. Currently only `%odd` for unusual errors. + +--- ## `agent` @@ -175,10 +227,10 @@ manually. ``` Container for Gall agent types. The most significant arm is -[`form:agent`](#formagent), which specifies the structure of the agent itself. -There are also some additional structures defined here, mostly defining the -kinds of messages agents can send. The different arms of the core in `agent` -are considered separately below. +[`form:agent`](#formagent), which specifies the structure of the agent +itself. There are also some additional structures defined here, mostly +defining the kinds of messages agents can send. The different arms of +the core in `agent` are considered separately below. ### `step:agent` @@ -186,8 +238,12 @@ are considered separately below. +$ step (quip card form) ``` -A cell of [`card:agent`](#cardagent)s to be sent and a new agent state. This is the -type returned by most arms of an agent. A `(quip a b)` is the same as `[(list a) b]`, it's just a more convenient way to specify it. +A cell of [`card:agent`](#cardagent)s to be sent and a new agent state. +This is the type returned by most arms of an agent. A `(quip a b)` is +the same as `[(list a) b]`, it's just a more convenient way to specify +it. + +--- ### `card:agent` @@ -195,9 +251,9 @@ type returned by most arms of an agent. A `(quip a b)` is the same as `[(list a) +$ card (wind note gift) ``` -An effect - typically a message to be sent to another agent or vane. A list of -these are returned by most agent arms along with a new state in a -[`step:agent`](#stepagent). A `wind` is the following: +An effect - typically a message to be sent to another agent or vane. A +list of these are returned by most agent arms along with a new state in +a [`step:agent`](#stepagent). A `wind` is the following: ```hoon ++ wind @@ -213,9 +269,11 @@ Gall will not allow a `%slip`, so in practice a `card` will be one of: - `[%pass path note]` - `[%give gift]` -For `%pass`, `p` specifies the `wire` on which a response should be returned. -See [`note:agent`](#noteagent) and [`gift:agent`](#giftagent) below for details of their -types. +For `%pass`, `p` specifies the `wire` on which a response should be +returned. See [`note:agent`](#noteagent) and [`gift:agent`](#giftagent) +below for details of their types. + +--- ### `note:agent` @@ -232,13 +290,15 @@ types. ``` The type for messages initiated by our agent. This is opposed to -[`gift:agent`](#giftagent), which is the type for responding to other agents or -vanes, or for sending out updates to subscribers. The three cases are: +[`gift:agent`](#giftagent), which is the type for responding to other +agents or vanes, or for sending out updates to subscribers. The three +cases are: - `%agent`: Poke another agent, subscribe to another agent, or cancel a - subscription to another agent. The `ship` and `name` fields are the ship and - agent to which the `task` should be sent. The `task` is the request itself, - see [`task:agent`](#taskagent) below for its possible types. + subscription to another agent. The `ship` and `name` fields are the + ship and agent to which the `task` should be sent. The `task` is the + request itself, see [`task:agent`](#taskagent) below for its possible + types. - `%arvo`: Pass a `task` to a vane. The type of a `note-arvo` is: ```hoon +$ note-arvo @@ -256,19 +316,23 @@ vanes, or for sending out updates to subscribers. The three cases are: [@tas %meta vase] == ``` - You can refer to the `/sys/lull.hoon` source code for all the possible vane - tasks, or see each vane's API Reference section in the [Arvo + You can refer to the `/sys/lull.hoon` source code for all the possible + vane tasks, or see each vane's API Reference section in the [Arvo documentation](/reference/arvo/overview) - `%pyre`: This is for aborting side-effects initiated during agent installation. The `tang` is an error message. -- `%grow`/`%tomb`/`%cull`: These are used for publishing and managing data - available for remote scries. For more information, see the [remote scries - guide](/guides/additional/remote-scry). +- `%grow`/`%tomb`/`%cull`: These are used for publishing and managing + data available for remote scries. For more information, see the + [remote scries guide](/guides/additional/remote-scry). A `note:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent). +--- + ### `task:agent` +The types of messages initiated by our agent and sent to another agent. + ```hoon +$ task $% [%watch =path] @@ -279,10 +343,9 @@ A `note:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent). == ``` -The types of messages initiated by our agent and sent to another agent. This is -in contrast to [`gift:agent`](#giftagent)s, which are responses to incoming -messages from agents or updates to agents already subscribed. The five kinds -are: +This is in contrast to [`gift:agent`](#giftagent)s, which are responses +to incoming messages from agents or updates to agents already +subscribed. The five kinds of `task:agent` are: - `%watch`: Subscribe to `path` on the target ship and agent. - `%watch-as`: Same as `%watch`, except you ask the target's Gall to convert @@ -298,8 +361,13 @@ are: A `task:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent). +--- + ### `gift:agent` +The types of messages our agent can either send in response to messages +from other agents, or send to subscribed agents. + ```hoon +$ gift $% [%fact paths=(list path) =cage] @@ -309,37 +377,46 @@ A `task:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent). == ``` -The types of messages our agent can either send in response to messages from -other agents, or send to subscribed agents. This is in contrast to -[`task:agent`](#taskagent)s, which are messages to other agents our agent -initiates rather than sends in response. The four kinds are: +This is in contrast to [`task:agent`](#taskagent)s, which are messages +to other agents our agent initiates rather than sends in response. The +four kinds of `gift:agent` are: -- `%fact`: An update to existing subscribers. The `paths` field specifies which - subscription paths the update should go out to. The `cage` is the data, and is - a `[mark vase]`. +- `%fact`: An update to existing subscribers. The `paths` field + specifies which subscription paths the update should go out to. The + `cage` is the data, and is a `[mark vase]`. - `%kick`: Kick subscriber, ending their subscription. The `paths` field - specifies which paths the subscriber should be kicked from, and the `ship` - field specifies the ship to kick. If the `ship` field is null, all subscribers - on the specified paths are kicked. Gall will automatically remove the - subscription from our agent's [`bitt`](#bitt) (inbound subscription `map`), - and subscriber will no longer receive updates on the `path`s in question. -- `%watch-ack`: Acknowledge a subscription request. If `p` is null, it's an ack - (positive acknowledgement), and if `p` is non-null, it's a nack (negative - acknowledgement). Simply crashing will caused Gall to nack a subscription - request, and not crashing but not explicitly producing a `%watch-ack` `gift` - will cause Gall to ack a subscription request. Therefore, you'd typically only - explicitly produce a `%watch-ack` `gift` if you wanted to nack a subscription - request with a custom error in the `tang`. -- `%poke-ack`: Acknowledge a poke. If `p` is null, it's an ack, and if `p` is - non-null, it's a nack. Simply crashing will cause Gall to nack a poke, and not - crashing but not explicitly producing a `%poke-ack` `gift` will cause Gall to - ack a poke. Therefore, you'd typically only explicitly produce a `%poke-ack` - `gift` if you wanted to nack a poke with a custom error in the `tang`. + specifies which paths the subscriber should be kicked from, and the + `ship` field specifies the ship to kick. If the `ship` field is null, + all subscribers on the specified paths are kicked. Gall will + automatically remove the subscription from our agent's [`bitt`](#bitt) + (inbound subscription `map`), and subscriber will no longer receive + updates on the `path`s in question. +- `%watch-ack`: Acknowledge a subscription request. If `p` is null, it's + an ack (positive acknowledgement), and if `p` is non-null, it's a nack + (negative acknowledgement). Simply crashing will caused Gall to nack a + subscription request, and not crashing but not explicitly producing a + `%watch-ack` `gift` will cause Gall to ack a subscription request. + Therefore, you'd typically only explicitly produce a `%watch-ack` + `gift` if you wanted to nack a subscription request with a custom + error in the `tang`. +- `%poke-ack`: Acknowledge a poke. If `p` is null, it's an ack, and if + `p` is non-null, it's a nack. Simply crashing will cause Gall to nack + a poke, and not crashing but not explicitly producing a `%poke-ack` + `gift` will cause Gall to ack a poke. Therefore, you'd typically only + explicitly produce a `%poke-ack` `gift` if you wanted to nack a poke + with a custom error in the `tang`. -A `gift:agent` is always wrapped in a `%give` [`card:agent`](#cardagent). +A `gift:agent` is always wrapped in a `%give` +[`card:agent`](#cardagent). + +--- ### `sign:agent` +A `sign` is like a [`gift:agent`](#giftagent) but it's something that +comes _in_ to our agent from another agent rather than something we send +out. + ```hoon +$ sign $% [%poke-ack p=(unit tang)] @@ -349,31 +426,34 @@ A `gift:agent` is always wrapped in a `%give` [`card:agent`](#cardagent). == ``` -A `sign` is like a [`gift:agent`](#giftagent) but it's something that comes -_in_ to our agent from another agent rather than something we send out. The -possible types are: +The possible types are: -- `%poke-ack`: Another agent has acked (positively acknowledged) or nacked - (negatively acknowledged) a `%poke` [`task:agent`](#taskagent) we previously - sent. It's an ack if `p` is null and a nack if `p` is non-null. The `tang` - contains an error or traceback if it's a nack. +- `%poke-ack`: Another agent has acked (positively acknowledged) or + nacked (negatively acknowledged) a `%poke` [`task:agent`](#taskagent) + we previously sent. It's an ack if `p` is null and a nack if `p` is + non-null. The `tang` contains an error or traceback if it's a nack. - `%watch-ack`: Another agent has acked or nacked a `%watch` - [`task:agent`](#taskagent) (subscription request) we previously sent. It's an - ack if `p` is null and a nack if `p` is non-null. The `tang` contains an error - or traceback if it's a nack. If it's a nack, Gall will automatically remove - the subscription from our agent's [`boat`](#boat) (outbound subscription - map). -- `%fact`: An update from another agent to which we've previously subscribed - with a `%watch` [`task:agent`](#taskagent) (subscription request). The `cage` - contains the data, and is a `[mark vase]`. -- `%kick`: Our subscription to another agent has been ended, and we'll no longer - receive updates. A `%kick` may be intentional, but it may also happen due to - certain network conditions or other factors. As a result, it's best to try and - resubscribe with another `%watch` [`task:agent`](#taskagent), and if they - nack the `%watch`, we can conclude it was intentional and give up. + [`task:agent`](#taskagent) (subscription request) we previously sent. + It's an ack if `p` is null and a nack if `p` is non-null. The `tang` + contains an error or traceback if it's a nack. If it's a nack, Gall + will automatically remove the subscription from our agent's + [`boat`](#boat) (outbound subscription map). +- `%fact`: An update from another agent to which we've previously + subscribed with a `%watch` [`task:agent`](#taskagent) (subscription + request). The `cage` contains the data, and is a `[mark vase]`. +- `%kick`: Our subscription to another agent has been ended, and we'll + no longer receive updates. A `%kick` may be intentional, but it may + also happen due to certain network conditions or other factors. As a + result, it's best to try and resubscribe with another `%watch` + [`task:agent`](#taskagent), and if they nack the `%watch`, we can + conclude it was intentional and give up. + +--- ### `form:agent` +This defines the structure of the agent itself. + ```hoon ++ form $_ ^| @@ -419,7 +499,8 @@ possible types are: -- ``` -This defines the structure of the agent itself. The agent is a door with a [`bowl`](#bowl) as its sample and exactly ten arms. Below we'll describe each arm briefly. +The agent is a door with a [`bowl`](#bowl) as its sample and exactly ten +arms. Below we'll describe each arm briefly. #### `on-init` @@ -447,16 +528,16 @@ This arm is called when another agent subscribes to our agent. - Accepts: `path` - Produces: [`step:agent`](#stepagent) -This arm is called when another agent unsubscribes from a subscription path on -our agent. +This arm is called when another agent unsubscribes from a +subscription path on our agent. #### `on-peek` - Accepts: `path` - Produces: `(unit (unit cage))` -This arm is called when a [scry](/reference/arvo/concepts/scry) is performed on our -agent. +This arm is called when a [scry](/reference/arvo/concepts/scry) is +performed on our agent. #### `on-agent` @@ -471,7 +552,8 @@ This arm is called when another agent give our agent a - Accepts: `[wire sign-arvo]` - Produces: [`step:agent`](#stepagent) -This arm is called when a vane gives our agent a `gift`. A `sign-arvo` is: +This arm is called when a vane gives our agent a `gift`. A `sign-arvo` +is: ```hoon +$ sign-arvo @@ -494,13 +576,15 @@ This arm is called when a vane gives our agent a `gift`. A `sign-arvo` is: == ``` -You can refer to the `/sys/lull.hoon` source code, or the API Reference of each -vane in the [Arvo documentation](/reference/arvo/overview). +You can refer to the `/sys/lull.hoon` source code, or the API Reference +of each vane in the [Arvo documentation](/reference/arvo/overview). #### `on-fail` - Accepts: `[term tang]` - Produces: [`step:agent`](#stepagent) -This arm is called if certain errors occur in Gall, such as if our agent tries -to create a duplicate subscription. +This arm is called if certain errors occur in Gall, such as if our agent +tries to create a duplicate subscription. + +--- diff --git a/content/reference/arvo/gall/gall-api.md b/content/reference/arvo/gall/gall-api.md index e32768d..44e95e1 100644 --- a/content/reference/arvo/gall/gall-api.md +++ b/content/reference/arvo/gall/gall-api.md @@ -3,956 +3,579 @@ title = "API Reference" weight = 3 +++ -## Reference Agent - -This app stores a number for each user. You can increment your number, increment -someone else's number, start tracking someone else's number by poking. It -exposes a scry namespace to inspect everyone's number. - -### `app/example-gall.hoon` - -```hoon -:: Import sur/example-gall -/- *example-gall -:: Import lib/default-agent -/+ default-agent -|% -+$ card card:agent:gall -+$ note - $% - [%arvo =note-arvo] - [%agent [=ship name=term] =task:agent:gall] - == -+$ state-zero [%0 local=@ud] -+$ state-one [%1 local=@ud remote=(map @p @ud)] -+$ versioned-state - $% - state-zero - state-one - == --- -=| state-one -=* state - -^- agent:gall -|_ =bowl:gall -+* this . - def ~(. (default-agent this %|) bowl) -:: -:: Set local counter to 1 by default -++ on-init - ^- (quip card _this) - `this(local 1) -:: Expose state for saving -++ on-save - !>(state) -:: -:: Load old state and upgrade if neccessary -++ on-load - |= old=vase - ^- (quip card _this) - =/ loaded=versioned-state - !<(versioned-state old) - ?- -.loaded - %0 - `this(local local.loaded) :: Upgrade old state - %1 - `this(state loaded) - == -:: -:: Respond to poke -:: App can be poked in the dojo by running the following commands -:: Increment local counter -:: :example-gall &example-gall-action [%increment ~] -:: Increment ~zod's counter -:: :example-gall &example-gall-action [%increment-remote ~zod] -:: Subscribe to ~zod's counter -:: :example-gall &example-gall-action [%view ~zod] -:: Unsubscribe from ~zod's counter -:: :example-gall &example-gall-action [%stop-view ~zod] -:: -++ on-poke - |= [=mark =vase] - ^- (quip card _this) - :: Ensure poke is of mark %example-gall-action - ?> =(mark %example-gall-action) - =/ act=example-gall-action !<(example-gall-action vase) - ?- act - :: - :: Increment local counter and send new counter to subscribers - :: - [%increment ~] - :- [%give %fact ~[/local] %atom !>(+(local))]~ - this(local +(local)) - :: - :: Send remote %increment poke - :: - [%increment-remote who=@p] - :_ this - :~ :* - %pass - /inc/(scot %p who.act) - %agent - [who.act %example-gall] - %poke %example-gall-action !>([%increment ~]) - == == - :: - :: Subscribe to a remote counter - :: - [%view who=@p] - :_ this - [%pass /view/(scot %p who.act) %agent [who.act %example-gall] %watch /local]~ - :: - :: Unsubscribe from remote counter and remove from state - :: - [%stop-view who=@p] - :_ this(remote (~(del by remote) who.act)) - [%pass /view/(scot %p who.act) %agent [who.act %example-gall] %leave ~]~ - :: - == -:: -:: Print on unsubscribe -:: -++ on-leave - |= =path - ^- (quip card _this) - ~& "Unsubscribed by: {} on: {}" - `this -:: -:: Handle new subscription -:: -:: When another ship subscribes to our counter, give them the current state of -:: the counter immediately -:: -++ on-watch - |= =path - ^- (quip card _this) - :_ this - :: Crash if we see a subscription we don't recognise - ?+ path ~|("unexpected subscription" !!) - :: - [%local ~] - [%give %fact ~ %atom !>(local)]~ - == -:: -:: Expose scry namespace -:: -:: .^(@ %gx /=example-gall=/local/atom) will produce the current local counter -:: .^(@ %gx /=example-gall=/remote/~zod/atom) will produce the counter for ~zod -:: .^(arch %gy /=example-gall=/remote) will produce a listing of the current -:: remote counters -++ on-peek - |= =path - ^- (unit (unit cage)) - ?+ path [~ ~] - :: - :: Produce local counter - :: - [%x %local ~] - ``[%atom !>(local)] - :: - :: Produce remote counter - :: - [%x %remote who=@ta ~] - =* location i.t.t.path :: Ship name is third in the list - =/ res - (~(got by remote) (slav %p location)) - ``[%atom !>(res)] - :: - :: Produce listing of remote counters - :: - [%y %remote ~] - =/ dir=(map @ta ~) - %- molt :: Map from list of k-v pairs - %+ turn :: iterate over list of k-v pairs - ~(tap by remote) :: list of k-v pairs from map - |= [who=@p *] - [(scot %p who) ~] - ``[%arch !>(`arch`[~ dir])] - == -:: -:: Handle sign from agent -:: -++ on-agent - |= [=wire =sign:agent:gall] - ^- (quip card _this) - ?- -.sign - :: - :: Print error if poke failed - :: - %poke-ack - ?~ p.sign - `this - %- (slog u.p.sign) - `this - :: - :: Print error if subscription failed - :: - %watch-ack - ?~ p.sign - `this - =/ =tank leaf+"subscribe failed from {} on wire {}" - %- (slog tank u.p.sign) - `this - :: - :: Do nothing if unsubscribed - :: - %kick `this - :: - :: Update remote counter when we get a subscription update - :: - %fact - :- ~ - ?. ?=(%atom p.cage.sign) - this - this(remote (~(put by remote) src.bowl !<(@ q.cage.sign))) - == -:: -:: Handle arvo signs -:: -:: We never give any cards to arvo. Therefore we never need to handle any signs -:: from arvo. We use the default-agent library to avoid implementing this arm, -:: as gall apps must have all the arms. -:: -++ on-arvo on-arvo:def -:: -:: Handle error -:: -:: Print errors when they happen -:: -++ on-fail - |= [=term =tang] - ^- (quip card _this) - %- (slog leaf+"error in {}" >term< tang) - `this --- - -``` - -### `sur/example-gall.hoon` - -```hoon -|% -+$ example-gall-action - $% - [%view who=@p] - [%stop-view who=@p] - [%increment-remote who=@p] - [%increment ~] - == --- -``` - -### `mar/example-gall/action.hoon` - -```hoon -/- *example-gall -|_ act=example-gall-action -++ grab - |% - ++ noun example-gall-action - -- --- -``` - -## Arms - -### `++on-init` - -Application initialisation - -`++on-init` is called when an application is first started. It is not a gate and -has no input. - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent - -#### Example - -```hoon -:: From reference agent. -:: Set local counter to 1 by default -:: -++ on-init - ^- (quip card _this) - `this(local.sta 1) -:: From app/weather.hoon. This setup is typical of a landscape tile. -:: -++ on-init - :_ this - :~ [%pass /bind/weather %arvo %e %connect [~ /'~weather'] %weather] - :* %pass /launch/weather %agent [our.bol %launch] %poke - %launch-action !>([%weather /weathertile '/~weather/js/tile.js']) - == - == -``` - -### `++on-save` - -Expose state for saving. - -This arm is called immediately before the agent is upgraded. It packages the -permament state of the agent in a vase for the next version of the agent. -Unlike most handlers, this cannot produce effects. It is not a gate and has no input. - -#### Returns - -`vase` of permanent state. - -#### Example - -```hoon -:: From reference agent -:: -:: Expose state for saving -:: -++ on-save - !>(state) -``` - -### `++on-load` - -Application upgrade. - -This arm is called immediately after the agent is upgraded. It receives -a vase of the state of the previously-running version of the agent, obtained -from `+on-save`, which allows it to cleanly upgrade from the old agent. - -#### Accepts - -```hoon -=vase -``` - -`vase` of previous state, from `++on-save` - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent - -#### Examples - -```hoon -:: From reference agent -:: -:: Load old state and upgrade if neccessary -++ on-load - |= old=vase - ^- (quip card _this) - =/ loaded=versioned-state - !<(versioned-state old) - ?- -.loaded - %0 - `this(local local.loaded) :: Upgrade old state - %1 - `this(state loaded) - == -``` - -### `++on-poke` - -Handle application poke. - -This arm is called when the agent is "poked". The input is a cage, so -it's a pair of a mark and a dynamic vase. - -#### Accepts - -```hoon -[=mark =vase] -``` - -`mark` is the mark of the poked data. - -`vase` is a vase with the poked data inside. - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent. - -#### Example - -```hoon -:: From reference agent. -:: -:: Respond to poke -:: App can be poked in the dojo by running the following commands -:: Increment local counter -:: :example-gall &example-gall-action [%increment ~] -:: Increment ~zod's counter -:: :example-gall &example-gall-action [%increment-remote ~zod] -:: Subscribe to ~zod's counter -:: :example-gall &example-gall-action [%view ~zod] -:: Unsubscribe from ~zod's counter -:: :example-gall &example-gall-action [%stop-view ~zod] -:: -++ on-poke - |= [=mark =vase] - ^- (quip card _this) - :: Ensure poke is of mark %example-gall-action - ?> =(mark %example-gall-action) - =/ act=example-gall-action !<(example-gall-action vase) - ?- act - :: - :: Increment local counter and send new counter to subscribers - :: - [%increment ~] - :- [%give %fact ~[/local] %atom !>(+(local))]~ - this(local +(local)) - :: - :: Send remote %increment poke - :: - [%increment-remote who=@p] - :_ this - :~ :* - %pass - /inc/(scot %p who.act) - %agent - [who.act %example-gall] - %poke %example-gall-action !>([%increment ~]) - == == - :: - :: Subscribe to a remote counter - :: - [%view who=@p] - :_ this - [%pass /view/(scot %p who.act) %agent [who.act %example-gall] %watch /local]~ - :: - :: Unsubscribe from remote counter and remove from state - :: - [%stop-view who=@p] - :_ this(remote (~(del by remote) who.act)) - [%pass /view/(scot %p who.act) %agent [who.act %example-gall] %leave ~]~ - :: - == -``` - -### `++on-watch` - -Handle new subscriber. - -This arm is called when a program wants to subscribe to the agent on a -particular path. The agent may or may not need to perform setup steps -to intialize the subscription. It may produce a `%give` -`%subscription-result` to the subscriber to get it up to date, but after -this event is complete, it cannot give further updates to a specific -subscriber. It must give all further updates to all subscribers on a -specific path. - -If this arm crashes, then the subscription is immediately terminated. -More specifcally, it never started -- the subscriber will receive a -negative `%watch-ack`. You may also produce an explicit `%kick` to -close the subscription without crashing -- for example, you could -produce a single update followed by a `%kick`. - -#### Accepts - -```hoon -=path -``` - -Path of new subscription. - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent. - -#### Example - -```hoon -:: From reference agent -:: -:: Handle new subscription -:: -:: When another ship subscribes to our counter, give them the current state of -:: the counter immediately -:: -++ on-watch - |= =path - ^- (quip card _this) - :_ this - ?+ path on-watch:def - :: - [%local ~] - [%give %fact ~ %atom !>(local)]~ - == -``` - -### `++on-leave` - -Handle unsubscribe. - -This arm is called when a program becomes unsubscribed to you. -Subscriptions may close because the subscriber intentionally -unsubscribed, but they also could be closed by an intermediary. For -example, if a subscription is from another ship which is currently -unreachable, Ames may choose to close the subscription to avoid queueing -updates indefinitely. If the program crashes while processing an -update, this may also generate an unsubscription. You should consider -subscriptions to be closable at any time. - -#### Accepts - -```hoon -=path -``` - -Path of the closed subscription. - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent. - -#### Example - -```hoon -:: From reference agent. Prints a message when programs become unsubscribed. -++ on-leave - |= =path - ^- (quip card _this) - ~& "Unsubscribe by: {} on: {}" - `this -``` - -### `++on-peek` - -Handle scry request. - -This arm is called when a program reads from the agent's "scry" -namespace, which should be referentially transparent. Unlike most -handlers, this cannot perform IO, and it cannot change the state. All -it can do is produce a piece of data to the caller, or not. - -#### Accepts - -```hoon -=path -``` - -The path being scryed for. - -```hoon -:: Example scry to path mappings -:: -.^(arch %gy /=example-gall=/remote) -:: Path will be /y/remote -.^(@ %gx /=example-gall=/local/atom) -:: Path will be /x/local -``` - -#### Returns - -```hoon -(unit (unit cage)) -``` - -If this arm produces `[~ ~ data]`, then `data` is the value at the the -given path. If it produces `[~ ~]`, then there is no data at the given -path and never will be. If it produces `~`, then we don't know yet whether -there is or will be data at the given path. The head of the path is known as the -`care`. Requests with a care of `%x` should return a vase that matches or is -convertible to the mark at the end of the scry request. This mark is not -included in the path passed to `++on-peek`. Requests with a care of `%y` should -return a cage with a mark of `%arch` and a vase of `arch`. - -#### Example - -```hoon -:: From reference agent -:: -:: Expose scry namespace -:: -:: .^(@ %gx /=example-gall=/local/atom) will produce the current local counter -:: .^(@ %gx /=example-gall=/remote/~zod/atom) will produce the counter for ~zod -:: .^(arch %gy /=example-gall=/remote) will produce a listing of the current -:: remote counters -++ on-peek - |= =path - ^- (unit (unit cage)) - ?+ path [~ ~] - :: - :: Produce local counter - :: - [%x %local ~] - ``[%atom !>(local)] - :: - :: Produce remote counter - :: - [%x %remote who=@ta ~] - =* location i.t.t.path :: Ship name is third in the list - =/ res - (~(got by remote) (slav %p location)) - ``[%atom !>(res)] - :: - :: Produce listing of remote counters - :: - [%y %remote ~] - =/ dir=(map @ta ~) - %- molt :: Map from list of k-v pairs - %+ turn :: iterate over list of k-v pairs - ~(tap by remote) :: list of k-v pairs from map - |= [who=@p *] - [(scot %p who) ~] - ``[%arch !>(`arch`[~ dir])] - == -``` - -### `++on-agent` - -Handle `%pass` card - -This arm is called to handle responses to `%pass` cards to other agents. -It will be one of the following types of response: - -- `%poke-ack`: acknowledgment (positive or negative) of a poke. If the - value is `~`, then the poke succeeded. If the value is `[~ tang]`, - then the poke failed, and a printable explanation (eg a stack trace) - is given in the `tang`. - -- `%watch-ack`: acknowledgment (positive or negative) of a subscription. - If negative, the subscription is already ended (technically, it never - started). - -- `%fact`: update from the publisher. - -- `%kick`: notification that the subscription has ended. This happens because - either the target app passed a `%leave` note, or ames killed the subscription - due to backpressure. Most of the time you will want to resubscribe. If you can - no longer access the subscription you will get a negative `%watch-ack` and end - your flow there. - -#### Accepts - -```hoon -[=wire =sign:agent:gall] -``` - -`wire` is the wire from the `+gift` that triggered `++on-agent` - -`sign` is response for the gift. - -#### Returns - -```hoon -(quip card _this) -``` - -#### Example - -```hoon -:: From reference agent -:: -:: Handle sign from agent -:: -++ on-agent - |= [=wire =sign:agent:gall] - ^- (quip card _this) - ?- -.sign - :: - :: Print error if poke failed - :: - %poke-ack - ?~ p.sign - `this - %- (slog u.p.sign) - `this - :: - :: Print error if subscription failed - :: - %watch-ack - ?~ p.sign - `this - =/ =tank leaf+"subscribe failed from {} on wire {}" - %- (slog tank u.p.sign) - `this - :: - :: Do nothing if unsubscribed - :: - %kick `this - :: - :: Update remote counter when we get a subscription update - :: - %fact - :- ~ - ?. ?=(%atom p.cage.sign) - this - this(remote (~(put by remote) src.bowl !<(@ q.cage.sign))) - == -``` - -### `++on-arvo` - -Handle vane response - -This arm is called to handle responses for `%pass` cards to vanes. - -#### Accepts - -```hoon - [=wire =sign:agent:gall] -``` - -`wire` is the wire from the `++gift` that triggered `++on-arvo`. - -`sign` is the response from the vane. The list of possible responses from the -vanes is statically defined in sys/zuse.hoon (grep for `++ sign-arvo`). - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent. - -#### Example - -```hoon -:: From app/weather.hoon. Handles %bound, %wake and %http-response signs -++ on-arvo - |= [=wire =sign-arvo] - ^- (quip card:agent:gall _this) - ?: ?=(%bound +<.sign-arvo) - [~ this] - ?: ?=(%wake +<.sign-arvo) - =^ cards state - (wake:wc wire error.sign-arvo) - [cards this] - ?: ?=(%http-response +<.sign-arvo) - =^ cards state - (http-response:wc wire client-response.sign-arvo) - [cards this] - (on-arvo:def wire sign-arvo) -:: -:: From reference agent -:: -:: Handle arvo signs -:: -:: We never give any cards to arvo. Therefore we never need to handle any signs -:: from arvo. We use the default-agent library to avoid implementing this arm, -:: as gall apps must have all the arms specified in the agent:gall definition. -:: -++ on-arvo on-arvo:def -``` - -### `++on-fail` - -Handle error. - -If an error happens in `+on-poke`, the crash report goes into the -`%poke-ack` response. Similarly, if an error happens in -`+on-subscription`, the crash report goes into the `%watch-ack` -response. If a crash happens in any of the other handlers, the report -is passed into this arm. - -#### Accepts - -```hoon -[=term =tang] -``` - -`term` is a cord describing the error. - -`tang` is a stack trace for the error. - -#### Returns - -```hoon -(quip card _this) -``` - -List of cards and new agent - -#### Example - -```hoon -:: -:: Handle error -:: -:: Print errors when they happen -:: -++ on-fail - |= [=term =tang] - ^- (quip card _this) - %- (slog leaf+"error in {}" >term< tang) - `this -``` - -## Agent Gifts - -Giving a gift takes the general form of - -```hoon -[%give =gift] -``` - -### `%fact` - -Produce a subscription update. - -Produces a subscription update. A subscription update is a new piece of -subscription content for all subscribers on a given path. - -#### Structure - -```hoon -[%fact paths=(list path) =cage] -``` - -`paths` is a list of the subscription paths to send the update on. In -`+on-watch` alone, if no path is given, then the update is given -exclusively to the source of the `%watch` request. This is useful for -giving initial state to new subscribers. In other contexts, one or more -subscription paths should be provided. - -`cage` is a cage of the subscription update. - -#### Example - -```hoon -:: From ++on-watch in reference agent. -:: -:: Gives current local state to new subscribers. -[%give %fact ~ %atom !>(local.sta)] - - -:: From ++on-poke in reference agent -:: -:: Gives incremented local state to any subscribers on /local -[%give %fact ~[/local] %atom !>(+(local))] -``` - -### `%kick` - -Close subscription. - -Closes a subscription. A subscription close closes the subscription for all or -one subscribers on a given path. - -#### Structure - -```hoon -[%kick (unit path) (unit ship)] -``` - -`(unit path)` is the path of the subscription being updated. If no path is -given, then the update is only given to the program that instigated the request. -Typical use of this mode would be in `+on-watch` to produce a single update to a -subscription then close the subscription. - -`(unit ship)` is the ship to close the subscription for. If no path is given, -then the subscription is closed for all subscribers. - ## Agent Notes -Passing a agent note (a 'task') along a wire looks like so. +A `note` is a request to a vane or agent which you initiate. A `note` is +one of: ```hoon -[%pass =wire %agent [=ship name=term] =task] ++$ note + $% [%agent [=ship name=term] =task] + [%arvo note-arvo] + [%pyre =tang] + :: + [%grow =spur =page] + [%tomb =case =spur] + [%cull =case =spur] + == ``` -`wire` is used to identify the response to the note. - -`ship` is the ship to pass the note to. - -`name` is the name of the agent that should receive the note. - -`task` is the task itself, described below. - -### `%poke` - -Poke an application. - -This note is passed to poke an application with a cage, a marked vase. - -#### Structure +A `note` is always wrapped in a `%pass` `card`, like so: ```hoon -[%poke =cage] +[%pass p=wire q=note] ``` -`cage` is the marked data to poke the application with. It is a pair of a mark -and vase. +The `wire` is just a `path` like `/foo/bar/baz`. You use it as a tag to +identify responses. -#### Example +The possible cases of an `%agent` `note` are documented [separately +below](#agent-tasks). + +We'll look at the remaining cases here. + +### `%arvo` + +Pass a vane `task` to a vane (kernel module). ```hoon -:: From ++on-poke in reference agent. -:: -:: Sends an increment poke to the example-gall agent -:: on who.act. -:* - %pass - /inc/(scot %p who.act) - %agent - [who.act %example-gall] - %poke %example-gall-action !>([%increment ~]) -== +[%arvo note-arvo] ``` +A `note-arvo` is defined as the following: + +```hoon ++$ note-arvo + $~ [%b %wake ~] + $% [%a task:ames] + [%b task:behn] + [%c task:clay] + [%d task:dill] + [%e task:eyre] + [%g task:gall] + [%i task:iris] + [%j task:jael] + [%k task:khan] + [%$ %whiz ~] + [@tas %meta vase] + == +``` + +The first part is vane letter (`%g` for Gall, `%i` for Iris, etc). The +second part is a `task` belonging to that vane. + +--- + +### `%pyre` + +Abort event. + +```hoon +[%pyre =tang] +``` + +This `note` tells Gall to crash with the given `tang` in the stack +trace. You'd use it in `++on-load` or `++on-init` when you wanted the +upgrade/installation to fail under some condition. + +--- + +### `%grow` + +Publish remote scry file. + +```hoon +[%grow =spur =page] +``` + +The `spur` is the `path` the file should be published at. The revision +number will be determined implicitly. As an example, if the `spur` was +`/foo`, the agent `%bar`, and it was the first revision, the resulting +remote scry path would be `/g/x/0/bar//foo` + +The `page` is the file, a pair of `[p=mark q=noun]`. + +--- + +### `%tomb` + +Delete remote scry file. + +```hoon +[%tomb =case =spur] +``` + +The `case` is the file revision, for example `[%ud 3]`. The spur is the +`path` it's bound to, for example `/foo`. + +The file at the specified `spur` and specific `case` will be deleted and +replaced by a simple hash. + +--- + +### `%cull` + +Delete remote scry file up to the given revision. + +```hoon +[%cull =case =spur] +``` + +All revisions of the remote scry file published at the `path` in `spur` +up to and including the revision specified in `case` will be deleted. +For example, if the `case` is `[%ud 2]`, then revisions `0`, `1`, and +`2` will all be deleted. + +--- + +## Agent Tasks + +A `task` is a request to an agent you initiate, as opposed to a +[`gift`](#agent-gifts), which is a response. + +Passing an agent `task` looks like so: + +```hoon +[%pass p=wire q=[%agent [=ship name=term] =task]] +``` + +- `wire`: this is just a `path` like `/foo/bar/baz`. You use it as a tag + to identify any [`gift`](#agent-gifts) that come back in response. +- `ship`: is the ship to pass the `task` to. +- `name`: is the name of the agent on the specified ship that should + receive the `task`. +- `task`: the `task` itself, as described below. + ### `%watch` -Subscribe to an application. - -This note is given to subscribe to an application at a path - -#### Structure +Subscribe to a path on an agent for updates. ```hoon [%watch =path] ``` -`path` is the path to be subscribed to. +The `path` is a subscription `path` like `/foo/bar/baz` which the +receiving agent publishes updates on. The publisher's Gall will +automatically respond with a [`%watch-ack`](#watch-ack). The +`%watch-ack` will be positive (an "ack") if the agent did not crash +processing the `%watch`, and will be negative (a "nack") if it crashed. -#### Example +Assuming the subscription request was successful (and therefore the +`%watch-ack` was positive), the publisher will begin sending updates as +[`%fact`](#fact) `gift`s to the subscriber. The publisher will continue +sending updates until the subscriber [`%leave`](#leave)s or the +publisher [`%kick`](#kick)s them. + +--- + +### `%watch-as` + +Subscribe to a path on an agent for updates, asking for the updates to +have a specified `mark`. ```hoon -:: From ++on-poke in reference agent. -:: -:: Subscribes to the example-gall agent on who.act on the path /local -:: -[%pass /view/(scot %p who.act) %agent [who.act %example-gall] %watch /local] +[%watch-as =mark =path] ``` +The `path` is a subscription `path` like `/foo/bar/baz` which the +receiving agent publishes updates on. The `mark` is the `mark` you want +the publisher to use for the data it gives you in the updates. + +This behaves the same as an ordinary [`%watch`](#watch) request, except +the publisher's Gall will try to convert from the `mark` of the `%fact`s +the agent produced to the `mark` you specified before sending it off. If +the publisher's Gall is unable to perform the mark conversion, you'll +get [`%kick`](#kick)ed from the subscription, and they'll send +themselves a [`%leave`](#leave) on your behalf. + +--- + ### `%leave` -Unsubscribe from an application. - -This note is passed to unsubscribe from an application. It should be passed on -the same wire that the corresponding `%watch` note for the subscription was -passed on. - -#### Structure +Unsubscribe from a subscription path on an agent. ```hoon [%leave ~] ``` -#### Example +The subscription to end is determined by the `wire`, `ship` and agent +`name` in the `%pass` `card` this is wrapped in. That is, if you +originally subscribed to subscription path `/foo/bar/baz` in agent +`%foo` on ship `~zod` using `wire` `/x/y/z`, you'd unsubscribe by +specifying `/x/y/z`, `~zod` and `%foo`. + +Once sent, you'll stop receiving `%fact`s from the publisher for the +subscription in question. + +--- + +### `%poke` + +A one-off request/datagram to an agent. ```hoon -:: From ++on-poke in reference agent. -:: -:: Unsubscribes from the example-gall agent on who.act -[%pass /view/(scot %p who.act) %agent [who.act %example-gall] %leave ~] +[%poke =cage] ``` + +A `%poke` `task` is a one-off, unsolicited delivery of some data. This +is in contrast to a [`%fact`](#fact) `gift`, the other basic method of +passing data between agents, which is ultimately a solicited response to +a past [`%watch`](#watch) request for subscription updates. Unlike a +`%watch` request, the recipient of the `%poke` cannot directly send data +back to the `%poke`-er (though they could conceivably send a new, +separate `%poke` back). The only response you get to a `%poke` is a +[`%poke-ack`](#poke-ack), indicating a simple success/failure result. + +The data of the `%poke` is contained in the `cage`, which is a pair of +`[p=mark q=vase]`. It's the basic way to pass around dynamically typed +data. + +--- + +### `%poke-as` + +A one-off request/datagram to an agent, asking the recipient's Gall to +convert the data to the specified `mark` before delivering it to the +agent. + +```hoon +[%poke-as =mark =cage] +``` + +This behaves the same as an ordinary [`%poke`](#poke) but with +additional `mark` conversion to the `mark` you specify by the +recipient's Gall. + +The `mark` is the `mark` you want the `cage` converted *to* before +delivery to the agent. The `cage` is the data itself, a pair of `[p=mark +q=vase]`. The mark conversion will be performed by the recipient's Gall, +not the sender's. + +If the `mark` conversion fails, the sender will be sent a negative +[`%poke-ack`](#poke-ack) (nack). Otherwise, the recipient will receive a +`%poke` with the target `mark` specified. + +--- + +## Agent Gifts + +An agent `gift` is ultimately a response to an agent `task`. Sometimes +it's an immediate, direct response, and other times it happens down the +line, or there's an ongoing series of gifts, as in the case of +subscriptions. They do all ultimately arise from an original `task`, +though, be it a a `%watch` subscription request or a `%poke`. A `gift` +cannot be sent out unsolicited to other agents. Where they are routed +to, whether another local agent, an agent on a remote ship, or even to +vanes or a browser-based front-end in some cases, is determined by the +original `task`. + +Giving a gift takes the general form of: + +```hoon +[%give p=gift] +``` + +Each possible `gift` is detailed below. + +### `%fact` + +Produce a subscription update. + +```hoon +[%fact paths=(list path) =cage] +``` + +A `%fact` is a piece of data given to all subscribers on one or more +subscription paths. + +The fields are: + +- `paths`: a list of subscription paths to send the update on. In + `+on-watch` alone, if no path is given, then the update is given + exclusively to the source of the `%watch` request. This is useful for + giving initial state to new subscribers. In other contexts, one or + more subscription paths should be provided. +- `cage`: the data. A `cage` is a pair of `[p=mark q=vase]`. + +--- + +### `%kick` + +Close subscription. + +```hoon +[%kick paths=(list path) ship=(unit ship)] +``` + +If `ship` is null, all subscribers will be kicked from the specified +subscription `paths` and will stop receiving updates. If `ship` is +non-null, only the specified ship will be kicked from the given `paths`. + +It should be noted that `%kick` `gift`s are not *only* emitted +intentionally by the publishing agent. Gall itself will `%kick` remote +subscribers if too many undelivered outbound `%fact`s queue up due to +network connectivity problems. On the subscriber side, their Gall will +`%kick` themselves if they crash while processing an incoming `%fact`. +It should therefore not be assumed the `%kick` was intentional. +Typically agents will be designed to resubscribe on `%kick` with a new +`%watch`, only giving up on negative `%watch-ack`. You should be careful +with automatic resubscribe logic, though, because you can inadvertently +create a network loop of infinite resubscribes and kicks if, for +example, a crash on `%fact` is repeatable. + +--- + +### `%watch-ack` + +Acknowledge a subscription request. + +```hoon +[%watch-ack p=(unit tang)] +``` + +A `%watch-ack` is automatically given by Gall in response to a `%watch` +`task`. A `%watch-ack` is either positive (an "ack") or negative (a +"nack"). It's an ack when `p` is null, and a nack when `p` is non-null, +instead containing a stack trace. + +A `%watch-ack` is given *automatically* and *implicitly* by Gall itself, +it is unnecessary for an agent to emit one explicitly. An ack will be +given as long as `++on-watch` doesn't crash. A nack will be given if it +*does* crash, with a trace of the crash in `p`. Your agent should +therefore be designed to accept or reject a subscription request by +crashing or not crashing, respectively. + +--- + +### `%poke-ack` + +Acknowledge a poke. + +```hoon +[%poke-ack p=(unit tang)] +``` + +A `%poke-ack` is automatically given by Gall in response to a `%poke` +`task`. A `%poke-ack` is either positive (an "ack") or negative (a +"nack"). It's an ack when `p` is null, and a nack when `p` is non-null, +instead containing a stack trace. + +A `%poke-ack` is given *automatically* and *implicitly* by Gall itself, +it is unnecessary for an agent to emit one explicitly. An ack will be +given as long as `++on-poke` doesn't crash. A nack will be given if it +*does* crash, with a trace of the crash in `p`. Your agent should +therefore be designed to accept or reject a poke by crashing or not +crashing, respectively. + +--- + +## Vane Tasks + +These are the Vane `task`s that can be `%pass`ed to Gall itself in an +`%arvo` `note`. Most of these are only used internally by the kernel, +though some app management `task`s might be of use in userspace. + +### `%deal` + +Full transmission. + +```hoon +[%deal p=sock q=term r=deal] +``` + +Gall translates agent +[`task:agent`](/reference/arvo/gall/data-types#taskagent)s emitted by +agents into `%deal` tasks, as well as requests from over the network. +This `task` is kernel-level only, it cannot be used directly from +userspace. + +Its fields are: + +- `p`: A `sock`, a `(pair ship ship)`, the sending and receiving ships. +- `q`: The source agent. +- `r`: A [`deal`](/reference/arvo/gall/data-types#deal) is either a + [`task:agent`](/reference/arvo/gall/data-types#taskagent) or a + `%raw-poke`. This is the request itself. + +#### Returns + +Gall returns no `gift` in response to a `%deal`. + +--- + +### `%sear` + +Clear pending queues. + +```hoon +[%sear =ship] +``` + +This `task` clears blocked inbound `move`s from the given ship. Moves +get blocked and queued when sent to an agent that isn't currently +running. + +#### Returns + +Gall returns no `gift` in response to a `%sear`. + +--- + +### `%jolt` + +Restart agent (deprecated). + +```hoon +[%jolt =desk =dude] +``` + +Restart agent `dude` on desk `desk`. This `task` is deprecated and now a +no-op. + +#### Returns + +Gall returns no `gift` in response to a `%jolt`. + +--- + +### `%idle` + +Suspend agent. + +```hoon +[%idle =dude] +``` + +The agent specified in `dude` will be suspended. Note it is usually +better to suspend agents with a +[`%rein`](/reference/arvo/clay/tasks#rein---force-apps) `task` to Clay +rather than an `%idle` `task` to Gall. + +#### Returns + +Gall returns no `gift` in response to an `%idle`. + +--- + +### `%load` + +Load agents. + +```hoon +[%load =load] +``` + +This `task` is given to Gall by Clay. It contains the compiled agents to +be installed or updated. This `task` would not be used from userspace. + +See the [`load`](/reference/arvo/gall/data-types#load) entry in the +type reference for more details of the datastructure in this `task`. + +#### Returns + +Gall returns no `gift` in response to a `%load`. + +--- + +### `%nuke` + +Delete agent. + +```hoon +[%nuke =dude] +``` + +The agent in `dude` will be stopped and its state discarded. + +{% callout %} + +**WARNING:** This will irreversibly erase all data stored in the state +of the agent. Use with care and caution. + +{% /callout %} + +#### Returns + +Gall returns no `gift` in response to a `%nuke`. + +--- + +### `%doff` + +Kill old-style subscriptions. + +```hoon +[%doff dude=(unit dude) ship=(unit ship)] +``` + +Kills nonceless outgoing subscriptions. If `dude` is non-null, it only +applies to the specified agent. If the `ship` is non-null, it only +applies to subscriptions to the specified ship. Otherwise, it applies to +all subscriptions. + +You're unlikely to use this `task` from userspace. + +#### Returns + +Gall returns no `gift` in response to a `%doff`. + +--- + +### `%rake` + +Reclaim old subscriptions. + +```hoon +[%rake dude=(unit dude) all=?] +``` + +This sends an Ames `%cork` on any old subscription ducts. If `dude` is +null, it applies to all agents, otherwise to the specified one. The +`all` flag should only be set if you want the ship to try and kill an +old subscription at sub-nonce zero. + +You are unlikely to use this `task`. + +#### Returns + +Gall returns no `gift` in response to a `%rake`. + +--- + +### `%spew` + +Set verbosity. + +```hoon +[%spew veb=(list verb)] +``` + +This sets verbosity flags for Gall. Currently there's only one +[`verb`](/reference/arvo/gall/data-types#verb), `%odd`, which prints +messages for unusual error cases. This overwrites the existing verbosity +settings: an empty list will turn all verbosity flags off. + +#### Returns + +Gall returns no `gift` in response to a `%spew`. + +--- + +### `%sift` + +Filter verbose debug printing to certain agents. + +```hoon +[%sift dudes=(list dude)] +``` + +The `dudes` are the agents you want verbose debug printing for. An empty +list enables it for all agents. See [`%spew`](#spew) for setting +verbosity. + +#### Returns + +Gall returns no `gift` in response to a `%sift`. + +--- + diff --git a/content/reference/arvo/gall/gall.md b/content/reference/arvo/gall/gall.md index fc0a0fc..6c07b08 100644 --- a/content/reference/arvo/gall/gall.md +++ b/content/reference/arvo/gall/gall.md @@ -59,10 +59,11 @@ definable in a regular recursive data type). ## Specification -An agent is defined as a [core](/reference/glossary/core/) with a set of [arms](/reference/glossary/arm/) to handle various -events. These handlers usually produce a list of effects and the next -state of the agent. The interface definition can be found in -`sys/lull.hoon`, which at the time of writing is: +An agent is defined as a [core](/reference/glossary/core/) with a set of +[arms](/reference/glossary/arm/) to handle various events. These +handlers usually produce a list of effects and the next state of the +agent. The interface definition can be found in `sys/lull.hoon`, which +at the time of writing is: ```hoon ++ agent @@ -71,8 +72,13 @@ state of the agent. The interface definition can be found in +$ step (quip card form) +$ card (wind note gift) +$ note - $% [%arvo =note-arvo] - [%agent [=ship name=term] =task] + $% [%agent [=ship name=term] =task] + [%arvo note-arvo] + [%pyre =tang] + :: + [%grow =spur =page] + [%tomb =case =spur] + [%cull =case =spur] == +$ task $% [%watch =path] @@ -82,8 +88,8 @@ state of the agent. The interface definition can be found in [%poke-as =mark =cage] == +$ gift - $% [%fact path=(unit path) =cage] - [%kick path=(unit path) ship=(unit ship)] + $% [%fact paths=(list path) =cage] + [%kick paths=(list path) ship=(unit ship)] [%watch-ack p=(unit tang)] [%poke-ack p=(unit tang)] == @@ -134,6 +140,7 @@ state of the agent. The interface definition can be found in |~ [term tang] *(quip card _^|(..on-init)) -- + -- ``` Here's a skeleton example of an implementation: diff --git a/content/reference/arvo/gall/scry.md b/content/reference/arvo/gall/scry.md index 1da8821..a04d89b 100644 --- a/content/reference/arvo/gall/scry.md +++ b/content/reference/arvo/gall/scry.md @@ -215,6 +215,28 @@ A `cass:clay`, specifically the `%ud` kind. --- +### `%x`: remote scry file + +A scry with a `%x` care and an agent in `q.beak` will get the value +bound at the remote scry path given in the `spur`. The revision of the +file must be given in the `beak` portion of the scry path. The general +format is therefore: + +```hoon +[%gx /[ship]/[agent]/[file revision]//[file path] +``` + +See the [remote scry guide](/guides/additional/remote-scry) for more +details. + +#### Produces + +The type returned is an `(each page @uvI)`. If the file has been +tombstoned, it'll be the `@uvI` hash of the file. Otherwise, it will be +the data as a `page` (a pair of `mark` and `noun`). + +--- + ### `%z`: hash of value at path A scry with a `%z` care and an agent in `q.beak` will get the hash identifier diff --git a/content/reference/arvo/gall/threads.md b/content/reference/arvo/gall/threads.md deleted file mode 100644 index 32e870c..0000000 --- a/content/reference/arvo/gall/threads.md +++ /dev/null @@ -1,86 +0,0 @@ -+++ -title = "Threads Reference" -weight = 50 -+++ - -## Start thread - -Poke `spider` with mark `%spider-start` and a vase containing `start-args`: - -```hoon -+$ start-args - [parent=(unit tid) use=(unit tid) =beak file=term =vase] -``` - -Where: - -- `parent` - optional `tid` of parent thread if the thread is a child. If specified, the child thread will be killed with the parent thread ends. -- `use` - `tid` (thread ID) to give the new thread. Can be generated with something like `(scot %ta (cat 3 'my-agent_' (scot %uv (sham eny))))`. However you do it, make sure it's unique. -- `beak` - A `$beak` is a triple of `[p=ship q=desk r=case]`. `p` is always our ship, `q` is the desk which contains the thread we want to run. `r` is a `case`, which specifies a desk revision and is a tagged union of: - ```hoon - +$ case - $% [%da p=@da] :: date - [%tas p=@tas] :: label - [%ud p=@ud] :: number - == - ``` - You'll almost always just want the current revision, so you can specify the `case` as `da+now.bowl`. If the thread is on the same desk as the agent you can also just use `byk.bowl(r da+now)` for the `beak`. -- `file` - name of the thread file in `/ted`. For example, if the thread you want to start is `/ted/foo/hoon` you'd specify `%foo`. -- `vase` - `vase` to be given to the thread when it's started. Can be whatever or just `!>(~)` if it doesn't need any args. - -#### Example - -```hoon -[%pass /some-path %agent [our.bowl %spider] %poke %spider-start !>([~ `tid byk.bowl %foo !>(~)])] -``` - -## Stop thread - -Poke `spider` with mark `%spider-stop` and a vase containing `[tid ?]`, where: - -- `tid` - the `tid` of the thread you want to stop -- `?` - whether thread should end nicely. If `%.y` it'll end with mark `%thread-done` and the bunt value of a vase. If `%.n` it'll end with mark `%thread-fail` and a `[term tang]` where `term` is `%cancelled` and `tang` is `~`. - -#### Example - -```hoon -[%pass /some-path %agent [our.bowl %spider] %poke %spider-stop !>([tid %.y)] -``` - -## Subscribe for result - -Spider will send the result on `/thread-result/[tid]` so you can subscribe there for the result. You should subscribe before starting the thread. - -The result will have a mark of either `%thread-fail` or `%thread-done`. - -- `%thread-fail` - has a vase containing a `[term tang]` where `term` is an error message and `tang` is a traceback. -- `%thread-done` - has a vase of the result of the thread. - -#### Example - -```hoon -[%pass /some-path %agent [our.bowl %spider] %watch /thread-result/[tid]] -``` - -## Subscribe to thread - -You can subscribe to a thread on `/thread/[tid]/path`. Note this is for facts sent off by the thread while it's running, not the final result. The path depends on the particular thread. - -#### Example - -```hoon -[%pass /some-path %agent [our.bowl %spider] %watch /thread/[tid]/thread-path] -``` - -## Poke thread - -To poke a thread you poke spider with a mark of `%spider-input` and a vase of `[tid cage]`. - -- `tid` is the tid of the thread you want to poke -- `cage` is whatever mark and vase you want to poke it with - -#### Example - -```hoon -[%pass /some-path %agent [our.bowl %spider] %poke %spider-input !>([tid %foo !>('foooo')])] -```