on 7fa97bd help sign in
urbit.org/docs/tutorials/internals.umd
148 lines 6.5 kB history raw
1:- :~ navhome/'/docs/'
2 next/'true'
3 sort/'8'
4 title/'Arvo Internals'
5 ==
6;>
8# Arvo internals
10Note: The following documentation was written in 2016. It needs to be rewritten: it's outdated in some respects, and it's also not always as clear as it could be. A rewrite is planned at some point. There is still good information to be found here, but don't bet the farm on anything you read in this section.
13Arvo is composed of modules called vanes:
15;list;
17At a high level `%arvo` takes a mess of Unix I/O events and turns them
18into something clean and structured for the programmer.
20`%arvo` is designed to avoid the usual state of complex event networks:
21event spaghetti. We keep track of every event's cause so that we have a
22clear causal chain for every computation. At the bottom of every chain
23is a Unix I/O event, such as a network request, terminal input, file
24sync, or timer event. We push every step in the path the request takes
25onto the chain until we get to the terminal cause of the computation.
26Then we use this causal stack to route results back to the caller.
28## Ducts
30The `%arvo` causal stack is called a `++duct`. This is represented
31simply as a list of paths, where each path represents a step in the
32causal chain. The first element in the path is the first letter of
33whichever vane handled that step in the computation, or the empty span
34for Unix.
36Here's a duct that was recently observed in the wild:
38````
39~[
40 /g/a/~zod/4_shell_terminal/u/time
41 /g/a/~zod/shell_terminal/u/child/4/main
42 /g/a/~zod/terminal/u/txt
43 /d/term-mess
44 //term/1
46````
48This is the duct the timer vane receives when "timer" sample app asks
49the timer vane to set a timer. This is also the duct over which the
50response is produced at the specified time. Unix sent a terminal
51keystroke event (enter), and Arvo routed it to `%dill` (our terminal),
52which passed it on to the `%gall` app terminal, which sent it to shell,
53its child, which created a new child (with process id 4), which on
54startup asked the timer vane to set a timer.
56The timer vane saves this duct, so that when the specified time arrives
57and Unix sends a wakeup event to the timer vane, it can produce the
58response on the same duct. This response is routed to the place we
59popped off the top of the duct, i.e. the time app. This app produces the
60text "ding", which falls down to the shell, which drops it through to
61the terminal. Terminal drops this down to dill, which converts it into
62an effect that Unix will recognize as a request to print "ding" to the
63screen. When dill produces this, the last path in the duct has an
64initial element of the empty span, so this is routed to Unix, which
65applies the effects.
67This is a call stack, with a crucial feature: the stack is a first-class
68citizen. You can respond over a duct zero, one, or many times. You can
69save ducts for later use. There are definitely parallels to Scheme-style
70continuations, but simpler and with more structure.
72## Making Moves
74If ducts are a call stack, then how do we make calls and produce
75results? Arvo processes "moves" which are a combination of message data
76and metadata. There are two types of moves. A `%pass` move is analogous
77to a call:
79```
80[duct %pass return-path=path vane-name=@tD data=card]
81```
83Arvo pushes the return path (preceded by the first letter of the vane
84name) onto the duct and sends the given data, a card, to the vane we
85specified. Any response will come along the same duct with the path
86`return-path`.
88A `%give` move is analogous to a return:
90```
91[duct %give data=card]
92```
94Arvo pops the top path off the duct and sends the given card back to the
95caller.
97## Vanes
99As shown above, we use Arvo proper to route and control the flow of
100moves. However, Arvo proper is rarely directly responsible for
101processing the event data that directly causes the desired outcome of a
102move. This event data is contained within a card, which is simply a
103`(pair term noun)`. Instead, Arvo proper passes the card off to one of
104its vanes, which each present an interface to clients for a particular
105well-defined, stable, and general-purpose piece of functionality.
107As of this writing, we have seven vanes, which each provide the
108following services:
110- `%ames`: the name of both our network and the vane that communicates over it.
111- `%behn`: a simple timer.
112- `%clay`: our version-controlled, referentially- transparent, and global filesystem.
113- `%dill`: a terminal driver. Unix sends keyboard events to `%dill` from either the console or telnet, and `%dill` produces terminal output.
114- `%eyre`: an http server. Unix sends http messages to `%eyre`, and `%eyre` produces http messages in response.
115- `%ford`: handles resources and publishing.
116- `%gall`: manages our userspace applications. `%gall` keeps state and manages subscribers.
118## Cards
120Cards are the vane-specific portion of a move. Each vane defines a
121protocol for interacting with other vanes (via Arvo) by defining four
122types of cards: kisses, gifts, notes, and signs.
124When one vane is `%pass`ed a card in its `++kiss`, Arvo activates the
125`++call` gate with the card as its argument. To produce a result, the
126vane `%give`s one of the cards defined in its `++gift`. If the vane
127needs to request something of another vane, it `%pass`es it a `++note`
128card. When that other vane returns a result, Arvo activates the `++take`
129gate of the initial vane with one of the cards defined in its `++sign`.
131In other words, there are only four ways of seeing a move: (1) as a
132request seen by the caller, which is a ++note. (2) that same request as
133seen by the callee, a `++kiss`. (3) the response to that first request
134as seen by the callee, a `++gift`. (4) the response to the first request
135as seen by the caller, a `++sign`.
137When a `++kiss` card is passed to a vane, Arvo calls its `++call` gate,
138passing it both the card and its duct. This gate must be defined in
139every vane. It produces two things in the following order: a list of
140moves and a possibly modified copy of its context. The moves are used to
141interact with other vanes, while the new context allows the vane to save
142its state. The next time Arvo activates the vane it will have this
143context as its subject.
145This overview has detailed how to pass a card to a particular vane. To
146see the cards each vane can be `%pass`ed as a `++kiss` or return as a
147`++gift` (as well as the semantics tied to them), each vane's public
148interface is explained in detail in its respective overview.