mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-16 19:22:22 +03:00
Merge branch 'test' of github.com:urbit/urbit-new into test
This commit is contained in:
commit
26f18774f5
@ -439,7 +439,7 @@
|
|||||||
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
|
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
|
||||||
tay=(cut 0 [27 5] mag) :: message type
|
tay=(cut 0 [27 5] mag) :: message type
|
||||||
==
|
==
|
||||||
?> =(7 vez)
|
?> =(1 vez)
|
||||||
?> =(chk (end 0 20 (mug bod)))
|
?> =(chk (end 0 20 (mug bod)))
|
||||||
:+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
|
:+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
|
||||||
(kins tay)
|
(kins tay)
|
||||||
@ -459,7 +459,7 @@
|
|||||||
=+ tay=(ksin q.kec)
|
=+ tay=(ksin q.kec)
|
||||||
%+ mix
|
%+ mix
|
||||||
%+ can 0
|
%+ can 0
|
||||||
:~ [3 7]
|
:~ [3 1]
|
||||||
[20 (mug bod)]
|
[20 (mug bod)]
|
||||||
[2 yax]
|
[2 yax]
|
||||||
[2 qax]
|
[2 qax]
|
||||||
@ -1047,7 +1047,7 @@
|
|||||||
++ gnaw :: gnaw:am
|
++ gnaw :: gnaw:am
|
||||||
|= [kay=cape ryn=lane pac=rock] :: process packet
|
|= [kay=cape ryn=lane pac=rock] :: process packet
|
||||||
^- [p=(list boon) q=fort]
|
^- [p=(list boon) q=fort]
|
||||||
?. =(7 (end 0 3 pac)) [~ fox]
|
?. =(1 (end 0 3 pac)) [~ fox]
|
||||||
=+ kec=(bite pac)
|
=+ kec=(bite pac)
|
||||||
?: (goop p.p.kec) [~ fox]
|
?: (goop p.p.kec) [~ fox]
|
||||||
?. (~(has by urb.ton.fox) q.p.kec)
|
?. (~(has by urb.ton.fox) q.p.kec)
|
||||||
|
@ -338,8 +338,9 @@
|
|||||||
=+ nex=(~(get by haw.u.ref) nez)
|
=+ nex=(~(get by haw.u.ref) nez)
|
||||||
?~ nex +>+.^$
|
?~ nex +>+.^$
|
||||||
?~ u.nex +>+.^$ :: should never happen
|
?~ u.nex +>+.^$ :: should never happen
|
||||||
=. +>+.^$ =+ roo=(edis ((hard nako) u.u.nex))
|
=. +>+.^$
|
||||||
?>(?=(^ ref.roo) roo)
|
=+ roo=(edis ((hard nako) u.u.nex))
|
||||||
|
?>(?=(^ ref.roo) roo)
|
||||||
%= $
|
%= $
|
||||||
haw.u.ref (~(del by haw.u.ref) nez)
|
haw.u.ref (~(del by haw.u.ref) nez)
|
||||||
==
|
==
|
||||||
@ -397,7 +398,7 @@
|
|||||||
..wake =- (blub:- p.i.xiq)
|
..wake =- (blub:- p.i.xiq)
|
||||||
=+ ^= ear
|
=+ ^= ear
|
||||||
(~(lobes-at-path ze lim dom ran) u.huy r.p.q.i.xiq)
|
(~(lobes-at-path ze lim dom ran) u.huy r.p.q.i.xiq)
|
||||||
?: =(s.p.q.i.xiq ear) ..wake
|
?: =(s.p.q.i.xiq ear) (blub p.i.xiq)
|
||||||
=+ fud=(~(make-nako ze lim dom ran) u.nab u.huy)
|
=+ fud=(~(make-nako ze lim dom ran) u.nab u.huy)
|
||||||
(bleb p.i.xiq +(u.nab) fud)
|
(bleb p.i.xiq +(u.nab) fud)
|
||||||
==
|
==
|
||||||
|
@ -438,7 +438,7 @@
|
|||||||
?. ?=([%$ ?(%da %ud %tas) *] a) ~
|
?. ?=([%$ ?(%da %ud %tas) *] a) ~
|
||||||
[~ u=(^case a)]
|
[~ u=(^case a)]
|
||||||
::
|
::
|
||||||
++ hath (cook plex:voz (stag %clsg poor:voz)) :: hood path
|
++ hath (sear plex:voz (stag %clsg poor:voz)) :: hood path
|
||||||
++ have (sear tome ;~(pfix fas hath)) :: hood beam
|
++ have (sear tome ;~(pfix fas hath)) :: hood beam
|
||||||
++ hood
|
++ hood
|
||||||
%+ ifix [gay gay]
|
%+ ifix [gay gay]
|
||||||
|
@ -8467,28 +8467,36 @@
|
|||||||
;~(plug (star low) (star hig))
|
;~(plug (star low) (star hig))
|
||||||
::
|
::
|
||||||
++ plex
|
++ plex
|
||||||
|= gen=twig ~| [%plex gen] ^- path
|
|= gen=twig ^- (unit path)
|
||||||
?: ?=([%zpcb *] gen)
|
?: ?=([%zpcb *] gen)
|
||||||
$(gen q.gen)
|
$(gen q.gen)
|
||||||
?> ?=([%clsg *] gen)
|
?. ?=([%clsg *] gen) ~
|
||||||
(turn p.gen |=(a=twig ?>(?=(%dtzy -.a) q.a)))
|
%+ reel p.gen
|
||||||
|
|= [a=twig b=_`(unit path)`[~ u=/]]
|
||||||
|
?~ b ~
|
||||||
|
?. ?=(%dtzy -.a) ~
|
||||||
|
`[q.a u.b]
|
||||||
::
|
::
|
||||||
++ pray
|
++ pray
|
||||||
|= gen=twig ~| %pray ^- twig
|
|= gen=twig ~| %pray ^- (unit twig)
|
||||||
=+ rev=(plex gen)
|
=+ rev=(plex gen)
|
||||||
?: (~(has in was) rev)
|
?~ rev ~
|
||||||
|
:- ~
|
||||||
|
?: (~(has in was) u.rev)
|
||||||
~|(%pray-loop !!)
|
~|(%pray-loop !!)
|
||||||
=+ ruv=`path`(weld rev `path`[%hoon ~])
|
=+ ruv=`path`(weld u.rev `path`[%hoon ~])
|
||||||
=+ txt=(,@ta .^(%cx ruv))
|
=+ txt=(,@ta .^(%cx ruv))
|
||||||
~| ruv
|
~| ruv
|
||||||
%+ rash txt
|
%+ rash txt
|
||||||
(ifix [gay gay] tall(was (~(put in was) rev), wer rev))
|
(ifix [gay gay] tall(was (~(put in was) u.rev), wer u.rev))
|
||||||
::
|
::
|
||||||
++ prey
|
++ prey
|
||||||
|= gun=(list twig) ^- twig
|
|= gun=(list twig) ^- (unit twig)
|
||||||
?~ gun [~ 1]
|
?~ gun `[~ 1]
|
||||||
?~ t.gun (pray i.gun)
|
=+ gup=(pray i.gun)
|
||||||
[%tsgr (pray i.gun) $(gun t.gun)]
|
?~ gup ~
|
||||||
|
?~ t.gun gup
|
||||||
|
(bind $(gun t.gun) |=(a=twig [%tsgr u.gup a]))
|
||||||
::
|
::
|
||||||
++ phax
|
++ phax
|
||||||
|= ruw=(list (list beer))
|
|= ruw=(list (list beer))
|
||||||
@ -8910,7 +8918,7 @@
|
|||||||
[%dtkt %dtzz %$ %cx rev]
|
[%dtkt %dtzz %$ %cx rev]
|
||||||
;~(plug hill rood)
|
;~(plug hill rood)
|
||||||
==
|
==
|
||||||
(cook prey (most ket rood))
|
(sear prey (most ket rood))
|
||||||
==
|
==
|
||||||
==
|
==
|
||||||
(stag %cnzz rope)
|
(stag %cnzz rope)
|
||||||
@ -9202,7 +9210,7 @@
|
|||||||
:~ [':' ;~(pfix col (toad expz))]
|
:~ [':' ;~(pfix col (toad expz))]
|
||||||
[',' (rune com %zpcm expb)]
|
[',' (rune com %zpcm expb)]
|
||||||
[';' (rune sem %zpsm expb)]
|
[';' (rune sem %zpsm expb)]
|
||||||
['^' ;~(pfix ket (cook prey (toad exps)))]
|
['^' ;~(pfix ket (sear prey (toad exps)))]
|
||||||
['>' (rune gar %zpgr expa)]
|
['>' (rune gar %zpgr expa)]
|
||||||
['=' (rune tis %zpts expa)]
|
['=' (rune tis %zpts expa)]
|
||||||
['?' (rune wut %zpwt hinh)]
|
['?' (rune wut %zpwt hinh)]
|
||||||
|
@ -1184,6 +1184,7 @@
|
|||||||
%delta (~(put in $(lob q.gar)) lob)
|
%delta (~(put in $(lob q.gar)) lob)
|
||||||
%indirect (~(put in $(lob s.gar)) lob)
|
%indirect (~(put in $(lob s.gar)) lob)
|
||||||
==
|
==
|
||||||
|
::
|
||||||
++ new-lobes-takos :: garg & repack
|
++ new-lobes-takos :: garg & repack
|
||||||
|= [b=(set lobe) a=(set tako)]
|
|= [b=(set lobe) a=(set tako)]
|
||||||
^- [(set tako) (set lobe)]
|
^- [(set tako) (set lobe)]
|
||||||
|
@ -1007,6 +1007,18 @@ scan backwards until we find the first revision committed before that date, and
|
|||||||
we produce that. If we requested a date before any revisions were committed,
|
we produce that. If we requested a date before any revisions were committed,
|
||||||
we produce `0`.
|
we produce `0`.
|
||||||
|
|
||||||
|
The definitions of `++aeon-to-tako` and `++tako-to-yaki` are trivial.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ aeon-to-tako ~(got by hit)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
++ tako-to-yaki ~(got by hut) :: grab yaki
|
||||||
|
```
|
||||||
|
|
||||||
|
We simply look up the aeon or tako in their respective maps (`hit` and `hut`).
|
||||||
|
|
||||||
Assuming we got a valid version number, `++aver` calls `++read-at-aeon:ze`,
|
Assuming we got a valid version number, `++aver` calls `++read-at-aeon:ze`,
|
||||||
which reads the requested data at the given revision.
|
which reads the requested data at the given revision.
|
||||||
|
|
||||||
@ -1567,10 +1579,6 @@ We let `sar` be the set of commits reachable from `a`. If `a` is null, then
|
|||||||
obviously no commits are reachable. Otherwise, we call `++reachable-takos` to
|
obviously no commits are reachable. Otherwise, we call `++reachable-takos` to
|
||||||
calculate this.
|
calculate this.
|
||||||
|
|
||||||
The type signature says everything you need to know about this. We take a set
|
|
||||||
of hashes of commits and data and convert them into the actual commits and data
|
|
||||||
in the most straightforward way possible.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
++ reachable-takos :: reachable
|
++ reachable-takos :: reachable
|
||||||
|= p=tako :: XX slow
|
|= p=tako :: XX slow
|
||||||
@ -1584,3 +1592,446 @@ in the most straightforward way possible.
|
|||||||
(~(uni in s) ^$(p q)) :: otherwise traverse
|
(~(uni in s) ^$(p q)) :: otherwise traverse
|
||||||
```
|
```
|
||||||
|
|
||||||
|
We very simply produce the set of the given tako plus its parents, recursively.
|
||||||
|
|
||||||
|
Back in `++reachable-between-takos`, we let `yak` be the yaki of `b`, the
|
||||||
|
ending commit. With this, we create a set that is the union of `sar` and all
|
||||||
|
takos reachable from `b`.
|
||||||
|
|
||||||
|
We pass `sar` into `++new-lobes` to get all the lobes referenced by any tako
|
||||||
|
referenced by `a`. The result is passed into `++new-lobes-takos` to do the
|
||||||
|
same, but not recomputing those in already calculated last sentence. This
|
||||||
|
produces the sets of takos and lobes we need.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ new-lobes :: object hash set
|
||||||
|
|= [b=(set lobe) a=(set tako)] :: that aren't in b
|
||||||
|
^- (set lobe)
|
||||||
|
%+ roll (~(tap in a) ~)
|
||||||
|
|= [tak=tako bar=(set lobe)]
|
||||||
|
^- (set lobe)
|
||||||
|
=+ yak=(tako-to-yaki tak)
|
||||||
|
%+ roll (~(tap by q.yak) ~)
|
||||||
|
|= [[path lob=lobe] far=_bar]
|
||||||
|
^- (set lobe)
|
||||||
|
?~ (~(has in b) lob) :: don't need
|
||||||
|
far
|
||||||
|
=+ gar=(lobe-to-blob lob)
|
||||||
|
?- -.gar
|
||||||
|
%direct (~(put in far) lob)
|
||||||
|
%delta (~(put in $(lob q.gar)) lob)
|
||||||
|
%indirect (~(put in $(lob s.gar)) lob)
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, we're creating a set of lobes referenced in a commit in `a`. We start
|
||||||
|
out with `b` as the initial set of lobes, so we don't need to recompute any of
|
||||||
|
the lobes referenced in there.
|
||||||
|
|
||||||
|
The algorithm is pretty simple, so we won't bore you with the details. We
|
||||||
|
simply traverse every commit in `a`, looking at every blob referenced there,
|
||||||
|
and, if it's not already in `b`, we add it to `b`. In the case of a direct
|
||||||
|
blob, we're done. For a delta or an indirect blob, we recursively add every
|
||||||
|
blob referenced within the blob.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ new-lobes-takos :: garg & repack
|
||||||
|
|= [b=(set lobe) a=(set tako)]
|
||||||
|
^- [(set tako) (set lobe)]
|
||||||
|
[a (new-lobes b a)]
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, we just update the set of lobes we're given with the commits we're given
|
||||||
|
and produce both sets.
|
||||||
|
|
||||||
|
This concludes our discussion of a local subscription.
|
||||||
|
|
||||||
|
Lifecycle of a Foreign Read or Subscription
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Foreign reads and subscriptions are handled in much the same way as local ones.
|
||||||
|
The interface is the same -- a vane or app sends a `%warp` kiss with the
|
||||||
|
request. The difference is simply that the `sock` refers to the foreign ship.
|
||||||
|
|
||||||
|
Thus, we start in the same place -- in `++call`, handling `%warp`. However,
|
||||||
|
since the two side of the `sock` are different, we follow a different path.
|
||||||
|
|
||||||
|
```
|
||||||
|
=+ wex=(do now p.q.hic p.q.q.hic ruf)
|
||||||
|
=+ ^= woo
|
||||||
|
?~ q.q.q.hic
|
||||||
|
abet:(ease:wex hen)
|
||||||
|
abet:(eave:wex hen u.q.q.q.hic)
|
||||||
|
[-.woo (posh q.p.q.hic p.q.q.hic +.woo ruf)]
|
||||||
|
```
|
||||||
|
|
||||||
|
If we compare this to how the local case was handled, we see that it's not all
|
||||||
|
that different. We use `++do` rather than `++un` and `++de` to set up the core
|
||||||
|
for the foreign ship. This gives us a `++de` core, so we either cancel or
|
||||||
|
begin the request by calling `++ease` or `++eave`, exactly as in the local
|
||||||
|
case. In either case, we call `++abet:de` to resolve our various types of
|
||||||
|
output into actual moves, as described in the local case. Finally, we call
|
||||||
|
`++posh` to update our raft, putting the modified rung into the raft.
|
||||||
|
|
||||||
|
We'll first trace through `++do`.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ do
|
||||||
|
|= [now=@da [who=ship him=ship] syd=@tas ruf=raft]
|
||||||
|
=+ ^= rug ^- rung
|
||||||
|
=+ rug=(~(get by hoy.ruf) him)
|
||||||
|
?^(rug u.rug *rung)
|
||||||
|
=+ ^= red ^- rede
|
||||||
|
=+ yit=(~(get by rus.rug) syd)
|
||||||
|
?^(yit u.yit `rede`[~2000.1.1 ~ [~ *rind] *dome])
|
||||||
|
((de now ~ ~) [who him] syd red ran.ruf)
|
||||||
|
```
|
||||||
|
|
||||||
|
If we already have a rung for this foreign ship, then we use that. Otherwise,
|
||||||
|
we create a new blank one. If we already have a rede in this rung, then we use
|
||||||
|
that, otherwise we create a blank one. An important point to note here is that
|
||||||
|
we let `ref` in the rede be `[~ *rind]`. Recall, for domestic desks `ref` is
|
||||||
|
null. We use this to distinguish between foreign and domestic desks in `++de`.
|
||||||
|
|
||||||
|
With this information, we create a `++de` core as usual.
|
||||||
|
|
||||||
|
Although we've already covered `++ease` and `++eave`, we'll go through them
|
||||||
|
quickly again, highlighting the case of foreign request.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ ease :: release request
|
||||||
|
|= hen=duct
|
||||||
|
^+ +>
|
||||||
|
=. qyx (~(del by qyx) hen)
|
||||||
|
?~ ref +>
|
||||||
|
|- ^+ +>+.$
|
||||||
|
=+ nux=(~(get by fod.u.ref) hen)
|
||||||
|
?~ nux +>+.$
|
||||||
|
%= +>+.$
|
||||||
|
say [[hen [(scot %ud u.nux) ~] for [u.nux syd ~]] say]
|
||||||
|
fod.u.ref (~(del by fod.u.ref) hen)
|
||||||
|
bom.u.ref (~(del by bom.u.ref) u.nux)
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, we still remove the duct from our cult (we maintain a cult even for
|
||||||
|
foreign desks), but we also need to tell the foreign desk to cancel our
|
||||||
|
subscription. We do this by sending a request (by appending to `say`, which
|
||||||
|
gets resolved in `++abet:de` to a `%want` kiss to ames) to the foreign ship to
|
||||||
|
cancel the subscription. Since we don't anymore expect a response on this
|
||||||
|
duct, we remove it from `fod` and `bom`, which are the maps between ducts,
|
||||||
|
raves, and request sequence numbers. Basically, we remove every trace of the
|
||||||
|
subscription from our request manager.
|
||||||
|
|
||||||
|
In the case of `++eave`, where we're creating a new request, everything is
|
||||||
|
exactly identical to the case of the local request except `++duce`. We said
|
||||||
|
that `++duce` simply puts the request into our cult. This is true for a
|
||||||
|
domestic request, but distinctly untrue for foreign requests.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ duce :: produce request
|
||||||
|
|= [hen=duct rov=rove]
|
||||||
|
^+ +>
|
||||||
|
=. qyx (~(put by qyx) hen rov)
|
||||||
|
?~ ref +>.$
|
||||||
|
|- ^+ +>+.$ :: XX why?
|
||||||
|
=+ rav=(reve rov)
|
||||||
|
=+ ^= vaw ^- rave
|
||||||
|
?. ?=([%& %v *] rav) rav
|
||||||
|
[%| [%ud let.dom] `case`q.p.rav r.p.rav]
|
||||||
|
=+ inx=nix.u.ref
|
||||||
|
%= +>+.$
|
||||||
|
say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
|
||||||
|
nix.u.ref +(nix.u.ref)
|
||||||
|
bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
|
||||||
|
fod.u.ref (~(put by fod.u.ref) hen inx)
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
If we have a request manager (i.e. this is a foreign desk), then we do the
|
||||||
|
approximate inverse of `++ease`. We create a rave out of the given request and
|
||||||
|
send it off to the foreign desk by putting it in `say`. Note that the rave is
|
||||||
|
created to request the information starting at the next revision number. Since
|
||||||
|
this is a new request, we put it into `fod` and `bom` to associate the request
|
||||||
|
with its duct and its sequence number. Since we're using another sequence
|
||||||
|
number, we must increment `nix`, which represents the next available sequence
|
||||||
|
number.
|
||||||
|
|
||||||
|
And that's really it for this side of the request. Requesting foreign
|
||||||
|
information isn't that hard. Let's see what it looks like on the other side.
|
||||||
|
When we get a request from another ship for information on our ship, that comes
|
||||||
|
to us in the form of a `%wart` from ames.
|
||||||
|
|
||||||
|
We handle a `%wart` in `++call`, right next to where we handle the `%warp` case.
|
||||||
|
|
||||||
|
```
|
||||||
|
%wart
|
||||||
|
?> ?=(%re q.q.hic)
|
||||||
|
=+ ryf=((hard riff) s.q.hic)
|
||||||
|
:_ ..^$
|
||||||
|
:~ :- hen
|
||||||
|
:^ %pass [(scot %p p.p.q.hic) (scot %p q.p.q.hic) r.q.hic]
|
||||||
|
%c
|
||||||
|
[%warp [p.p.q.hic p.p.q.hic] ryf]
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
Every request we receive should be of type `riff`, so we coerce it into that
|
||||||
|
type. We just convert this into a new `%warp` kiss that we pass to ourself.
|
||||||
|
This gets handled like normal, as a local request. When the request produces
|
||||||
|
a value, it does so like normal as a `%writ`, which is returned to `++take`
|
||||||
|
along the path we just sent it on.
|
||||||
|
|
||||||
|
```
|
||||||
|
%writ
|
||||||
|
?> ?=([@ @ *] tea)
|
||||||
|
=+ our=(need (slaw %p i.tea))
|
||||||
|
=+ him=(need (slaw %p i.t.tea))
|
||||||
|
:_ ..^$
|
||||||
|
:~ :- hen
|
||||||
|
[%pass ~ %a [%want [our him] [%r %re %c t.t.tea] p.+.q.hin]]
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
Since we encoded the ship we need to respond to in the path, we can just pass
|
||||||
|
our `%want` back to ames, so that we tell the requesting ship about the new
|
||||||
|
data.
|
||||||
|
|
||||||
|
This comes back to the original ship as a `%waft` from ames, which comes into
|
||||||
|
`++take`, right next to where we handled `%writ`.
|
||||||
|
|
||||||
|
```
|
||||||
|
%waft
|
||||||
|
?> ?=([@ @ ~] tea)
|
||||||
|
=+ syd=(need (slaw %tas i.tea))
|
||||||
|
=+ inx=(need (slaw %ud i.t.tea))
|
||||||
|
=+ ^= zat
|
||||||
|
=< wake
|
||||||
|
(knit:(do now p.+.q.hin syd ruf) [inx ((hard riot) q.+.q.hin)])
|
||||||
|
=^ mos ruf
|
||||||
|
=+ zot=abet.zat
|
||||||
|
[-.zot (posh q.p.+.q.hin syd +.zot ruf)]
|
||||||
|
[mos ..^$(ran.ruf ran.zat)] :: merge in new obj
|
||||||
|
```
|
||||||
|
|
||||||
|
This gets the desk and sequence number from the path the request was sent over.
|
||||||
|
This determines exactly which request is being responded to. We call
|
||||||
|
`++knit:de` to apply the changes to our local desk, and we call `++wake` to
|
||||||
|
update our subscribers. Then we call `++abet:de` and `++posh` as normal (like
|
||||||
|
in `++eave`).
|
||||||
|
|
||||||
|
We'll examine `++knit` and `++wake`, in that order.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ knit :: external change
|
||||||
|
|= [inx=@ud rot=riot]
|
||||||
|
^+ +>
|
||||||
|
?> ?=(^ ref)
|
||||||
|
|- ^+ +>+.$
|
||||||
|
=+ ruv=(~(get by bom.u.ref) inx)
|
||||||
|
?~ ruv +>+.$
|
||||||
|
=> ?. |(?=(~ rot) ?=(& -.q.u.ruv)) .
|
||||||
|
%_ .
|
||||||
|
bom.u.ref (~(del by bom.u.ref) inx)
|
||||||
|
fod.u.ref (~(del by fod.u.ref) p.u.ruv)
|
||||||
|
==
|
||||||
|
?~ rot
|
||||||
|
=+ rav=`rave`q.u.ruv
|
||||||
|
%= +>+.$
|
||||||
|
lim
|
||||||
|
?.(&(?=(| -.rav) ?=(%da -.q.p.rav)) lim `@da`p.q.p.rav)
|
||||||
|
::
|
||||||
|
haw.u.ref
|
||||||
|
?. ?=(& -.rav) haw.u.ref
|
||||||
|
(~(put by haw.u.ref) p.rav ~)
|
||||||
|
==
|
||||||
|
?< ?=(%v p.p.u.rot)
|
||||||
|
=. haw.u.ref
|
||||||
|
(~(put by haw.u.ref) [p.p.u.rot q.p.u.rot q.u.rot] ~ r.u.rot)
|
||||||
|
?. ?=(%w p.p.u.rot) +>+.$
|
||||||
|
|- ^+ +>+.^$
|
||||||
|
=+ nez=[%w [%ud let.dom] ~]
|
||||||
|
=+ nex=(~(get by haw.u.ref) nez)
|
||||||
|
?~ nex +>+.^$
|
||||||
|
?~ u.nex +>+.^$ :: should never happen
|
||||||
|
=. +>+.^$ =+ roo=(edis ((hard nako) u.u.nex))
|
||||||
|
?>(?=(^ ref.roo) roo)
|
||||||
|
%= $
|
||||||
|
haw.u.ref (~(del by haw.u.ref) nez)
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This is kind of a long gate, but don't worry, it's not bad at all.
|
||||||
|
|
||||||
|
First, we assert that we're not a domestic desk. That wouldn't make any sense
|
||||||
|
at all.
|
||||||
|
|
||||||
|
Since we have the sequence number of the request, we can get the duct and rave
|
||||||
|
from `bom` in our request manager. If we didn't actually request this data (or
|
||||||
|
the request was canceled before we got it), then we do nothing.
|
||||||
|
|
||||||
|
Else, we remove the request from `bom` and `fod` unless this was a subscription
|
||||||
|
request and we didn't receive a null riot (which would indicate the last
|
||||||
|
message on the subscription).
|
||||||
|
|
||||||
|
Now, if we received a null riot, then if this was a subscription request by
|
||||||
|
date, then we update `lim` in our request manager (representing the latest time
|
||||||
|
at which we have complete information for this desk) to the date that was
|
||||||
|
requested. If this was a single read request, then we put the result in our
|
||||||
|
simple cache `haw` to make future requests faster. Then we're done.
|
||||||
|
|
||||||
|
If we received actual data, then we put it into our cache `haw`. Unless it's a
|
||||||
|
`%w` request, we're done.
|
||||||
|
|
||||||
|
If it is a `%w` request, then we try to get the `%w` at our current head from
|
||||||
|
the cache. In general, that should be the thing we just put in a moment ago,
|
||||||
|
but that is not guaranteed. The most common case where this is different is
|
||||||
|
when we receive desk updates out of order. At any rate, since we now have new
|
||||||
|
information, we need to apply it to our local copy of the desk. We do so in
|
||||||
|
`++edis`, and then we remove the stuff we just applied from the cache, since
|
||||||
|
it's not really a true "single read", like what should really be in the cache.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ edis :: apply subscription
|
||||||
|
|= nak=nako
|
||||||
|
^+ +>
|
||||||
|
%= +>
|
||||||
|
hit.dom (~(uni by hit.dom) gar.nak)
|
||||||
|
let.dom let.nak
|
||||||
|
lat.ran %+ roll (~(tap in bar.nak) ~)
|
||||||
|
=< .(yeb lat.ran)
|
||||||
|
|= [sar=blob yeb=(map lobe blob)]
|
||||||
|
=+ zax=(blob-to-lobe sar)
|
||||||
|
%+ ~(put by yeb) zax sar
|
||||||
|
hut.ran %+ roll (~(tap in lar.nak) ~)
|
||||||
|
=< .(yeb hut.ran)
|
||||||
|
|= [sar=yaki yeb=(map tako yaki)]
|
||||||
|
%+ ~(put by yeb) r.sar sar
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This shows, of course, exactly why nako is defined the way it is. To become
|
||||||
|
completely up to date with the foreign desk, we need to merge `hit` with the
|
||||||
|
foreign one so that we have all the revision numbers. We update `let` so that
|
||||||
|
we know which revision is the head.
|
||||||
|
|
||||||
|
We merge the new blobs in `lat`, keying them by their hash, which we get from a
|
||||||
|
call to `++blob-to-lobe`. Recall that the hash is stored in the actual blob
|
||||||
|
itself. We do the same thing to the new yakis, putting them in `hut`, keyed by
|
||||||
|
their hash.
|
||||||
|
|
||||||
|
Now, our local dome should be exactly the same as the foreign one.
|
||||||
|
|
||||||
|
This concludes our discussion of `++knit`. Now the changes have been applied to
|
||||||
|
our local copy of the desk, and we just need to update our subscribers. We do
|
||||||
|
so in `++wake:de`.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ wake :: update subscribers
|
||||||
|
^+ .
|
||||||
|
=+ xiq=(~(tap by qyx) ~)
|
||||||
|
=| xaq=(list ,[p=duct q=rove])
|
||||||
|
|- ^+ ..wake
|
||||||
|
?~ xiq
|
||||||
|
..wake(qyx (~(gas by *cult) xaq))
|
||||||
|
?- -.q.i.xiq
|
||||||
|
&
|
||||||
|
=+ cas=?~(ref ~ (~(get by haw.u.ref) `mood`p.q.i.xiq))
|
||||||
|
?^ cas
|
||||||
|
%= $
|
||||||
|
xiq t.xiq
|
||||||
|
..wake ?~ u.cas (blub p.i.xiq)
|
||||||
|
(blab p.i.xiq p.q.i.xiq u.u.cas)
|
||||||
|
==
|
||||||
|
=+ nao=(~(case-to-aeon ze lim dom ran) q.p.q.i.xiq)
|
||||||
|
?~ nao $(xiq t.xiq, xaq [i.xiq xaq])
|
||||||
|
$(xiq t.xiq, ..wake (balk p.i.xiq u.nao p.q.i.xiq))
|
||||||
|
::
|
||||||
|
|
|
||||||
|
=+ mot=`moot`p.q.i.xiq
|
||||||
|
=+ nab=(~(case-to-aeon ze lim dom ran) p.mot)
|
||||||
|
?~ nab
|
||||||
|
$(xiq t.xiq, xaq [i.xiq xaq])
|
||||||
|
=+ huy=(~(case-to-aeon ze lim dom ran) q.mot)
|
||||||
|
?~ huy
|
||||||
|
=+ ptr=[%ud +(let.dom)]
|
||||||
|
%= $
|
||||||
|
xiq t.xiq
|
||||||
|
xaq [[p.i.xiq [%| ptr q.mot r.mot s.mot]] xaq]
|
||||||
|
..wake =+ ^= ear
|
||||||
|
(~(lobes-at-path ze lim dom ran) let.dom r.p.q.i.xiq)
|
||||||
|
?: =(s.p.q.i.xiq ear) ..wake
|
||||||
|
=+ fud=(~(make-nako ze lim dom ran) u.nab let.dom)
|
||||||
|
(bleb p.i.xiq let.dom fud)
|
||||||
|
==
|
||||||
|
%= $
|
||||||
|
xiq t.xiq
|
||||||
|
..wake =- (blub:- p.i.xiq)
|
||||||
|
=+ ^= ear
|
||||||
|
(~(lobes-at-path ze lim dom ran) u.huy r.p.q.i.xiq)
|
||||||
|
?: =(s.p.q.i.xiq ear) (blub p.i.xiq)
|
||||||
|
=+ fud=(~(make-nako ze lim dom ran) u.nab u.huy)
|
||||||
|
(bleb p.i.xiq +(u.nab) fud)
|
||||||
|
==
|
||||||
|
==
|
||||||
|
--
|
||||||
|
```
|
||||||
|
|
||||||
|
This is even longer than `++knit`, but it's pretty similar to `++eave`. We loop
|
||||||
|
through each of our subscribers `xiq`, processing each in turn. When we're done,
|
||||||
|
we just put the remaining subscribers back in our subscriber list.
|
||||||
|
|
||||||
|
If the subscriber is a single read, then, if this is a foreign desk (note that
|
||||||
|
`++wake` is called from other arms, and not only on foreign desks). Obviously,
|
||||||
|
if we find an identical request there, then we can produce the result
|
||||||
|
immediately. Referential transparency for the win. We produce the result with
|
||||||
|
a call to `++blab`. If this is a foreign desk but the result is not in the
|
||||||
|
cache, then we produce `++blub` (canceled subscription with no data) for
|
||||||
|
reasons entirely opaque to me. Seriously, it seems like we should wait until
|
||||||
|
we get an actual response to the request. If someone figures out why this is,
|
||||||
|
let me know. At any rate, it seems to work.
|
||||||
|
|
||||||
|
If this is a domestic desk, then we check to see if the case exists yet. If
|
||||||
|
it doesn't, then we simply move on to the next subscriber, consing this one
|
||||||
|
onto `xaq` so that we can check again the next time around. If it does exist,
|
||||||
|
then we call `++balk` to fulfill the request and produce it.
|
||||||
|
|
||||||
|
`++balk` is very simple, so we'll describe it here before we get to the
|
||||||
|
subscription case.
|
||||||
|
|
||||||
|
```
|
||||||
|
++ balk :: read and send
|
||||||
|
|= [hen=duct oan=@ud mun=mood]
|
||||||
|
^+ +>
|
||||||
|
=+ vid=(~(read-at-aeon ze lim dom ran) oan mun)
|
||||||
|
?~ vid (blub hen) (blab hen mun u.vid)
|
||||||
|
```
|
||||||
|
|
||||||
|
We call `++read-at-aeon` on the given request and aeon. If you recall, this
|
||||||
|
processes a `mood` at a particular aeon and produces the result, if there is
|
||||||
|
one. If there is data at the requested location, then we produce it with
|
||||||
|
`++blab`. Else, we call `++blub` to notify the subscriber that no data can
|
||||||
|
ever come over this subscriptioin since it is now impossible for there to ever
|
||||||
|
be data for the given request. Because referential transparency.
|
||||||
|
|
||||||
|
At any rate, back to `++wake`. If the given rave is a subscription request,
|
||||||
|
then we proceed similarly to how we do in `++eave`. We first try to get the
|
||||||
|
aeon referred to by the starting case. If it doesn't exist yet, then we can't
|
||||||
|
do anything interesting with this subscription, so we move on to the next one.
|
||||||
|
|
||||||
|
Otherwise, we try to get the aeon referrred to by the ending case. If it
|
||||||
|
doesn't exist yet, then we produce all the information we can. We call
|
||||||
|
`++lobes-at-path` at the given aeon and path to see if the requested path has
|
||||||
|
actually changed. If it hasn't, then we don't produce anything; else, we
|
||||||
|
produce the correct nako by calling `++bleb` on the result of `++make-nako`, as
|
||||||
|
in `++eave`. At any rate, we move on to the next subscription, putting back
|
||||||
|
into our cult the current subscription with a new start case of the next aeon
|
||||||
|
after the present.
|
||||||
|
|
||||||
|
If the aeon referred to by the ending case does exist, then we drop this
|
||||||
|
subscriber from our cult and satisfy its request immediately. This is the same
|
||||||
|
as before -- we check to see if the data at the path has actually changed,
|
||||||
|
producing it if it has; else, we call `++blub` since no more data can be
|
||||||
|
produced over this subscription.
|
||||||
|
|
||||||
|
This concludes our discussion of foreign requests.
|
||||||
|
Loading…
Reference in New Issue
Block a user