Merge pull request #3479 from urbit/lf/graph-be

graph-view backend
This commit is contained in:
L 2020-09-15 15:48:44 -05:00 committed by GitHub
commit bbeaa0690e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 751 additions and 28 deletions

View File

@ -100,9 +100,7 @@
?~ path ?~ path
:: new subscribe :: new subscribe
:: ::
=/ [=graph:store mark=(unit mark:store)]
(get-graph:gra resource) (get-graph:gra resource)
[%0 now.bowl [%add-graph resource graph mark]]
:: resubscribe :: resubscribe
:: ::
=/ =time (slav %da i.path) =/ =time (slav %da i.path)

View File

@ -1,5 +1,5 @@
/- spider /- spider
/+ libstrand=strand, default-agent, verb /+ libstrand=strand, default-agent, verb, server
=, strand=strand:libstrand =, strand=strand:libstrand
|% |%
+$ card card:agent:gall +$ card card:agent:gall
@ -17,15 +17,25 @@
$: starting=(map yarn [=trying =vase]) $: starting=(map yarn [=trying =vase])
running=trie running=trie
tid=(map tid yarn) tid=(map tid yarn)
serving=(map tid [@ta =mark])
== ==
:: ::
+$ clean-slate-any +$ clean-slate-any
$^ clean-slate-ket $^ clean-slate-ket
$% clean-slate-sig $% clean-slate-sig
clean-slate-1
clean-slate clean-slate
== ==
:: ::
+$ clean-slate +$ clean-slate
$: %2
starting=(map yarn [=trying =vase])
running=(list yarn)
tid=(map tid yarn)
serving=(map tid [@ta =mark])
==
::
+$ clean-slate-1
$: %1 $: %1
starting=(map yarn [=trying =vase]) starting=(map yarn [=trying =vase])
running=(list yarn) running=(list yarn)
@ -133,7 +143,10 @@
sc ~(. spider-core bowl) sc ~(. spider-core bowl)
def ~(. (default-agent this %|) bowl) def ~(. (default-agent this %|) bowl)
:: ::
++ on-init on-init:def ++ on-init
^- (quip card _this)
:_ this
~[bind-eyre:sc]
++ on-save clean-state:sc ++ on-save clean-state:sc
++ on-load ++ on-load
|^ |^
@ -141,7 +154,9 @@
=+ !<(any=clean-slate-any old-state) =+ !<(any=clean-slate-any old-state)
=? any ?=(^ -.any) (old-to-1 any) =? any ?=(^ -.any) (old-to-1 any)
=? any ?=(~ -.any) (old-to-1 any) =? any ?=(~ -.any) (old-to-1 any)
?> ?=(%1 -.any) =^ upgrade-cards any
(old-to-2 any)
?> ?=(%2 -.any)
:: ::
=. tid.state tid.any =. tid.state tid.any
=/ yarns=(list yarn) =/ yarns=(list yarn)
@ -154,12 +169,26 @@
(handle-stop-thread:sc (yarn-to-tid i.yarns) |) (handle-stop-thread:sc (yarn-to-tid i.yarns) |)
=^ cards-2 this =^ cards-2 this
$(yarns t.yarns) $(yarns t.yarns)
[(weld cards-1 cards-2) this] [:(weld upgrade-cards cards-1 cards-2) this]
:: ::
++ old-to-1 ++ old-to-1
|= old=clean-slate-ket |= old=clean-slate-ket
^- clean-slate ^- clean-slate-1
1+old(starting (~(run by starting.old) |=([* v=vase] none+v))) 1+old(starting (~(run by starting.old) |=([* v=vase] none+v)))
::
++ old-to-2
|= old=clean-slate-any
^- (quip card clean-slate)
?> ?=(?(%1 %2) -.old)
?: ?=(%2 -.old)
`old
:- ~[bind-eyre:sc]
:* %2
starting.old
running.old
tid.old
~
==
-- --
:: ::
++ on-poke ++ on-poke
@ -172,6 +201,9 @@
%spider-input (on-poke-input:sc !<(input vase)) %spider-input (on-poke-input:sc !<(input vase))
%spider-start (handle-start-thread:sc !<(start-args vase)) %spider-start (handle-start-thread:sc !<(start-args vase))
%spider-stop (handle-stop-thread:sc !<([tid ?] vase)) %spider-stop (handle-stop-thread:sc !<([tid ?] vase))
::
%handle-http-request
(handle-http-request:sc !<([@ta =inbound-request:eyre] vase))
== ==
[cards this] [cards this]
:: ::
@ -182,6 +214,7 @@
?+ path (on-watch:def path) ?+ path (on-watch:def path)
[%thread @ *] (on-watch:sc t.path) [%thread @ *] (on-watch:sc t.path)
[%thread-result @ ~] (on-watch-result:sc i.t.path) [%thread-result @ ~] (on-watch-result:sc i.t.path)
[%http-response *] `state
== ==
[cards this] [cards this]
:: ::
@ -216,6 +249,7 @@
?+ wire (on-arvo:def wire sign-arvo) ?+ wire (on-arvo:def wire sign-arvo)
[%thread @ *] (handle-sign:sc i.t.wire t.t.wire sign-arvo) [%thread @ *] (handle-sign:sc i.t.wire t.t.wire sign-arvo)
[%build @ ~] (handle-build:sc i.t.wire sign-arvo) [%build @ ~] (handle-build:sc i.t.wire sign-arvo)
[%bind ~] `state
== ==
[cards this] [cards this]
:: On unexpected failure, kill all outstanding strands :: On unexpected failure, kill all outstanding strands
@ -228,6 +262,41 @@
-- --
:: ::
|_ =bowl:gall |_ =bowl:gall
::
++ bind-eyre
^- card
[%pass /bind %arvo %e %connect [~ /spider] %spider]
::
++ handle-http-request
|= [eyre-id=@ta =inbound-request:eyre]
^- (quip card _state)
?> authenticated.inbound-request
=/ url
(parse-request-line:server url.request.inbound-request)
?> ?=([%spider @t @t @t ~] site.url)
=* input-mark i.t.site.url
=* thread i.t.t.site.url
=* output-mark i.t.t.t.site.url
=/ =tid
(scot %uv (sham eny.bowl))
=. serving.state
(~(put by serving.state) tid [eyre-id output-mark])
=+ .^
=tube:clay
%cc
/(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/json/[input-mark]
==
?> ?=(^ body.request.inbound-request)
=/ body=json
(need (de-json:html q.u.body.request.inbound-request))
=/ input=vase
(tube !>(body))
=/ =start-args
[~ `tid thread input]
=^ cards state
(handle-start-thread start-args)
[cards state]
::
++ on-poke-input ++ on-poke-input
|= input |= input
=/ yarn (~(got by tid.state) tid) =/ yarn (~(got by tid.state) tid)
@ -394,6 +463,25 @@
:~ [%give %fact ~[/thread-result/[tid]] %thread-fail !>([term tang])] :~ [%give %fact ~[/thread-result/[tid]] %thread-fail !>([term tang])]
[%give %kick ~[/thread-result/[tid]] ~] [%give %kick ~[/thread-result/[tid]] ~]
== ==
++ thread-http-fail
|= [=tid =term =tang]
^- (quip card ^state)
=- (fall - `state)
%+ bind
(~(get by serving.state) tid)
|= [eyre-id=@ta output=mark]
:_ state(serving (~(del by serving.state) tid))
%+ give-simple-payload:app:server eyre-id
^- simple-payload:http
:_ ~ :_ ~
?. ?=(http-error:spider term)
((slog tang) 500)
?- term
%bad-request 400
%forbidden 403
%nonexistent 404
%offline 504
==
:: ::
++ thread-fail ++ thread-fail
|= [=yarn =term =tang] |= [=yarn =term =tang]
@ -402,7 +490,24 @@
=/ =tid (yarn-to-tid yarn) =/ =tid (yarn-to-tid yarn)
=/ fail-cards (thread-say-fail tid term tang) =/ fail-cards (thread-say-fail tid term tang)
=^ cards state (thread-clean yarn) =^ cards state (thread-clean yarn)
[(weld fail-cards cards) state] =^ http-cards state (thread-http-fail tid term tang)
[:(weld fail-cards cards http-cards) state]
::
++ thread-http-response
|= [=tid =vase]
^- (quip card ^state)
=- (fall - `state)
%+ bind
(~(get by serving.state) tid)
|= [eyre-id=@ta output=mark]
=+ .^
=tube:clay
%cc
/(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[output]/json
==
:_ state(serving (~(del by serving.state) tid))
%+ give-simple-payload:app:server eyre-id
(json-response:gen:server !<(json (tube vase)))
:: ::
++ thread-done ++ thread-done
|= [=yarn =vase] |= [=yarn =vase]
@ -413,8 +518,10 @@
:~ [%give %fact ~[/thread-result/[tid]] %thread-done vase] :~ [%give %fact ~[/thread-result/[tid]] %thread-done vase]
[%give %kick ~[/thread-result/[tid]] ~] [%give %kick ~[/thread-result/[tid]] ~]
== ==
=^ http-cards state
(thread-http-response tid vase)
=^ cards state (thread-clean yarn) =^ cards state (thread-clean yarn)
[(weld done-cards cards) state] [:(weld done-cards cards http-cards) state]
:: ::
++ thread-clean ++ thread-clean
|= =yarn |= =yarn
@ -474,5 +581,5 @@
:: ::
++ clean-state ++ clean-state
!> ^- clean-slate !> ^- clean-slate
1+state(running (turn (tap-yarn running.state) head)) 2+state(running (turn (tap-yarn running.state) head))
-- --

View File

@ -0,0 +1,61 @@
/- sur=graph-view
/+ resource, group-store
^?
=< [sur .]
=, sur
|%
++ dejs
=, dejs:format
|%
++ action
|^
^- $-(json ^action)
%- of
:~ create+create
delete+delete
join+join
leave+leave
groupify+groupify
::invite+invite
==
::
++ create
%- ou
:~ resource+(un dejs:resource)
title+(un so)
description+(un so)
mark+(uf ~ (mu so))
associated+(un associated)
==
::
++ leave
%- ot
:~ resource+dejs:resource
==
::
++ delete
%- ot
:~ resource+dejs:resource
==
::
++ join
%- ot
:~ resource+dejs:resource
ship+(su ;~(pfix sig fed:ag))
==
::
++ groupify
%- ou
:~ resource+(un dejs:resource)
to+(uf ~ (mu dejs:resource))
==
++ invite !!
::
++ associated
%- of
:~ group+dejs:resource
policy+policy:dejs:group-store
==
--
--
--

View File

@ -13,10 +13,16 @@
:: ::
++ get-graph ++ get-graph
|= res=resource |= res=resource
^- marked-graph:store ^- update:store
%+ scry-for marked-graph:store %+ scry-for update:store
/graph/(scot %p entity.res)/[name.res] /graph/(scot %p entity.res)/[name.res]
:: ::
++ get-update-log
|= rid=resource
^- update-log:store
%+ scry-for update-log:store
/update-log/(scot %p entity.rid)/[name.rid]
::
++ peek-update-log ++ peek-update-log
|= res=resource |= res=resource
^- (unit time) ^- (unit time)

View File

@ -241,6 +241,16 @@
;< our=@p bind:m get-our ;< our=@p bind:m get-our
(watch wire [our term] path) (watch wire [our term] path)
:: ::
++ scry
|* [=mold =path]
=/ m (strand ,mold)
^- form:m
?> ?=(^ path)
?> ?=(^ t.path)
;< =bowl:spider bind:m get-bowl
%- pure:m
.^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)
::
++ leave ++ leave
|= [=wire =dock] |= [=wire =dock]
=/ m (strand ,~) =/ m (strand ,~)
@ -285,6 +295,20 @@
[%pass /wait/(scot %da until) %arvo %b %wait until] [%pass /wait/(scot %da until) %arvo %b %wait until]
(send-raw-card card) (send-raw-card card)
:: ::
++ map-err
|* computation-result=mold
=/ m (strand ,computation-result)
|= [f=$-([term tang] [term tang]) computation=form:m]
^- form:m
|= tin=strand-input:strand
=* loop $
=/ c-res (computation tin)
?: ?=(%cont -.next.c-res)
c-res(self.next ..loop(computation self.next.c-res))
?. ?=(%fail -.next.c-res)
c-res
c-res(err.next (f err.next.c-res))
::
++ set-timeout ++ set-timeout
|* computation-result=mold |* computation-result=mold
=/ m (strand ,computation-result) =/ m (strand ,computation-result)
@ -478,6 +502,17 @@
`[%skip ~] `[%skip ~]
`[%done +>.sign-arvo.u.in.tin] `[%done +>.sign-arvo.u.in.tin]
== ==
:: +check-online: require that peer respond before timeout
::
++ check-online
|= [who=ship lag=@dr]
=/ m (strand ,~)
^- form:m
%+ (map-err ,~) |=(* [%offline *tang])
%+ (set-timeout ,~) lag
;< ~ bind:m
(poke [who %hood] %helm-hi !>(~))
(pure:m ~)
:: ::
:: Queue on skip, try next on fail %ignore :: Queue on skip, try next on fail %ignore
:: ::

View File

@ -1,7 +1,9 @@
/+ *graph-store /+ *graph-store
|_ upd=update |_ upd=update
++ grad %noun
++ grow ++ grow
|% |%
++ noun upd
++ json (update:enjs upd) ++ json (update:enjs upd)
-- --
:: ::

View File

@ -0,0 +1,13 @@
/+ *graph-view
|_ act=action
++ grad %noun
++ grow
|%
++ noun act
--
++ grab
|%
++ noun action
++ json action:dejs
--
--

View File

@ -0,0 +1,44 @@
/- *group
/+ resource
^?
|%
:: $associated: A group to associate, or a policy if it is unmanaged
::
+$ associated
$% [%group rid=resource]
[%policy =policy]
==
::
:: $error: An error from a graph-view poke
::
:: %offline: Ship is offline
:: %bad-perms: Not permitted
:: %unknown: Anything not described above
::
+$ error
?(%offline %bad-perms %unknown)
:: $action: A semantic action on graphs
::
:: %create: Create a graph and associated metadata
:: %delete: Delete a graph
:: %join: Join a graph
:: %invite: Invite users to a graph
:: %groupify: Make graph into managed group
::
+$ action
$%
$: %create
rid=resource
title=@t
description=@t
mark=(unit mark)
=associated
==
[%delete rid=resource]
[%leave rid=resource]
[%join rid=resource =ship]
::[%invite rid=resource ships=(set ship)]
[%groupify rid=resource to=(unit resource)]
==
--

View File

@ -5,4 +5,10 @@
+$ input [=tid =cage] +$ input [=tid =cage]
+$ tid tid:strand +$ tid tid:strand
+$ bowl bowl:strand +$ bowl bowl:strand
+$ http-error
$? %bad-request :: 400
%forbidden :: 403
%nonexistent :: 404
%offline :: 504
==
-- --

View File

@ -0,0 +1,60 @@
/- spider, graph=graph-store, *metadata-store, *group, group-store
/+ strandio, resource, graph-view
=>
|%
++ strand strand:spider
++ poke poke:strandio
++ poke-our poke-our:strandio
::
++ handle-group
|= [rid=resource =associated:graph-view]
=/ m (strand ,resource)
?: ?=(%group -.associated)
(pure:m rid.associated)
=/ =action:group-store
[%add-group rid policy.associated %&]
;< ~ bind:m (poke-our %group-store %group-action !>(action))
;< ~ bind:m
(poke-our %group-push-hook %push-hook-action !>([%add rid]))
(pure:m rid)
--
::
=, strand=strand:spider
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<(=action:graph-view arg)
?> ?=(%create -.action)
;< =bowl:spider bind:m get-bowl:strandio
:: Add graph to graph-store
::
?. =(our.bowl entity.rid.action)
(strand-fail:strandio %bad-request ~)
=/ =update:graph
[%0 now.bowl %add-graph rid.action *graph:graph mark.action]
;< ~ bind:m
(poke-our %graph-store graph-update+!>(update))
;< ~ bind:m
(poke-our %graph-push-hook %push-hook-action !>([%add rid.action]))
:: Add group, if graph is unmanaged
::
;< group=resource bind:m
(handle-group rid.action associated.action)
=/ group-path=path
(en-path:resource group)
:: Setup metadata
::
=/ =metadata
%* . *metadata
title title.action
description description.action
date-created now.bowl
creator our.bowl
==
=/ act=metadata-action
[%add group-path graph+(en-path:resource rid.action) metadata]
;< ~ bind:m (poke-our %metadata-hook %metadata-action !>(act))
;< ~ bind:m
(poke-our %metadata-hook %metadata-hook-action !>([%add-owned group-path]))
(pure:m !>(~))

View File

@ -0,0 +1,70 @@
/- spider, graph-view, graph=graph-store, *metadata-store, *group
/+ strandio, resource
=>
|%
++ strand strand:spider
++ poke poke:strandio
++ poke-our poke-our:strandio
::
++ scry-metadata
|= rid=resource
=/ m (strand ,(unit resource))
;< paxs=(unit (set path)) bind:m
%+ scry:strandio ,(unit (set path))
;: weld
/gx/metadata-store/resource/publish
(en-path:resource rid)
/noun
==
?~ paxs (pure:m ~)
?~ u.paxs (pure:m ~)
(pure:m `(de-path:resource n.u.paxs))
::
++ scry-group
|= rid=resource
=/ m (strand ,group)
;< ugroup=(unit group) bind:m
%+ scry:strandio ,(unit group)
;: weld
/gx/group-store/groups
(en-path:resource rid)
/noun
==
(pure:m (need ugroup))
::
++ delete-graph
|= rid=resource
=/ m (strand ,~)
^- form:m
;< ~ bind:m
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
;< =bowl:spider bind:m get-bowl:strandio
;< ~ bind:m
(poke-our %graph-store %graph-update !>([%0 now.bowl %archive-graph rid]))
(pure:m ~)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<(=action:graph-view arg)
?> ?=(%delete -.action)
;< =bowl:spider bind:m get-bowl:strandio
?. =(our.bowl entity.rid.action)
(strand-fail:strandio %bad-request ~)
;< ugroup-rid=(unit resource) bind:m
(scry-metadata rid.action)
?~ ugroup-rid !!
;< =group bind:m
(scry-group u.ugroup-rid)
?. hidden.group
;< ~ bind:m
(delete-graph rid.action)
(pure:m !>(~))
;< ~ bind:m
(poke-our %group-push-hook %push-hook-action !>([%remove rid.action]))
;< ~ bind:m
(poke-our %group-store %group-action !>([%remove-group rid.action]))
;< ~ bind:m (delete-graph rid.action)
(pure:m !>(~))

View File

@ -0,0 +1,74 @@
/- spider, graph-view, graph=graph-store, *metadata-store, *group, *metadata-store
/+ strandio, resource
=>
|%
++ strand strand:spider
++ poke poke:strandio
++ poke-our poke-our:strandio
::
++ check-live
|= who=ship
=/ m (strand ,~)
^- form:m
%+ (set-timeout:strandio ,~) ~s20
;< ~ bind:m
(poke [who %hood] %helm-hi !>(~))
(pure:m ~)
::
++ scry-group
|= rid=resource
=/ m (strand ,group)
^- form:m
;< ugroup=(unit group) bind:m
%+ scry:strandio (unit group)
%+ weld /gx/group-store/groups
(snoc (en-path:resource rid) %noun)
?> ?=(^ ugroup)
(pure:m u.ugroup)
::
++ scry-metadatum
|= rid=resource
=/ m (strand ,metadata)
^- form:m
=/ enc-path=@t
(scot %t (spat (en-path:resource rid)))
;< umeta=(unit metadata) bind:m
%+ scry:strandio (unit metadata)
%+ weld /gx/metadata-store/metadata
/[enc-path]/graph/[enc-path]/noun
?> ?=(^ umeta)
(pure:m u.umeta)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<(=action:graph-view arg)
?> ?=(%groupify -.action)
;< =group bind:m (scry-group rid.action)
?. hidden.group
(strand-fail:strandio %bad-request ~)
;< =metadata bind:m
(scry-metadatum rid.action)
?~ to.action
;< ~ bind:m
%+ poke-our %contact-view
contact-view-action+!>([%groupify rid.action title.metadata description.metadata])
(pure:m !>(~))
;< new=^group bind:m (scry-group u.to.action)
?< hidden.new
=/ new-path
(en-path:resource u.to.action)
=/ app-path
(en-path:resource rid.action)
=/ add-md=metadata-action
[%add new-path graph+app-path metadata]
;< ~ bind:m
(poke-our %metadata-store metadata-action+!>(add-md))
;< ~ bind:m
%+ poke-our %metadata-store
metadata-action+!>([%remove app-path graph+app-path])
;< ~ bind:m
(poke-our %group-store %group-update !>([%remove-group rid.action]))
(pure:m !>(~))

View File

@ -0,0 +1,61 @@
/- spider, graph-view, graph=graph-store, *metadata-store, *group
/+ strandio, resource
=>
|%
++ strand strand:spider
++ fail strand-fail:strand
++ poke poke:strandio
++ poke-our poke-our:strandio
::
++ scry-metadata
|= rid=resource
=/ m (strand ,(unit resource))
^- form:m
;< pax=(unit (set path)) bind:m
%+ scry:strandio ,(unit (set path))
;: weld
/gx/metadata-store/resource/graph
(en-path:resource rid)
/noun
==
%- pure:m
?~ pax ~
?~ u.pax ~
`(de-path:resource n.u.pax)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<(=action:graph-view arg)
?> ?=(%join -.action)
;< =bowl:spider bind:m get-bowl:strandio
?: =(our.bowl entity.rid.action)
(fail %bad-request ~)
;< group=(unit resource) bind:m (scry-metadata rid.action)
?^ group
:: We have group, graph is managed
;< ~ bind:m
%+ poke-our %graph-pull-hook
pull-hook-action+!>([%add ship.action rid.action])
(pure:m !>(~))
:: Else, add group then join
;< ~ bind:m
%+ (map-err:strandio ,~) |=(* [%forbidden ~])
%+ poke
[ship.action %group-push-hook]
group-update+!>([%add-members rid.action (sy our.bowl ~)])
::
;< ~ bind:m
%+ poke-our %group-pull-hook
pull-hook-action+!>([%add ship.action rid.action])
::
;< ~ bind:m
%+ poke-our %metadata-hook
metadata-hook-action+!>([%add-synced ship.action rid.action])
::
;< ~ bind:m
%+ poke-our %graph-pull-hook
pull-hook-action+!>([%add ship.action rid.action])
(pure:m !>(~))

View File

@ -0,0 +1,67 @@
/- spider, graph-view, graph=graph-store, *metadata-store, *group
/+ strandio, resource
=>
|%
++ strand strand:spider
++ poke poke:strandio
++ poke-our poke-our:strandio
::
++ scry-metadata
|= rid=resource
=/ m (strand ,resource)
^- form:m
;< pax=(unit (set path)) bind:m
%+ scry:strandio ,(unit (set path))
;: weld
/gx/metadata-store/resource/graph
(en-path:resource rid)
/noun
==
?> ?=(^ pax)
?> ?=(^ u.pax)
(pure:m (de-path:resource n.u.pax))
::
++ scry-group
|= rid=resource
=/ m (strand ,group)
^- form:m
;< ugroup=(unit group) bind:m
%+ scry:strandio ,(unit group)
;: weld
/gx/group-store/resource/graph
(en-path:resource rid)
/noun
==
(pure:m (need ugroup))
::
++ delete-graph
|= rid=resource
=/ m (strand ,~)
^- form:m
;< ~ bind:m
(poke-our %graph-pull-hook %pull-hook-action !>([%remove rid]))
;< ~ bind:m
(poke-our %graph-store %graph-update !>([%archive-graph rid]))
(pure:m ~)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<([=action:graph-view ~] arg)
?> ?=(%leave -.action)
;< =bowl:spider bind:m get-bowl:strandio
?: =(our.bowl entity.rid.action)
(strand-fail:strandio %bad-request ~)
;< group-rid=resource bind:m (scry-metadata rid.action)
;< g=group bind:m (scry-group group-rid)
?. hidden.g
;< ~ bind:m (delete-graph rid.action)
(pure:m !>(~))
;< ~ bind:m
(poke-our %group-push-hook %pull-hook-action !>([%remove rid.action]))
;< ~ bind:m
(poke-our %group-store %group-action !>([%remove-group rid.action]))
;< ~ bind:m (delete-graph rid.action)
(pure:m !>(~))

View File

@ -57,4 +57,16 @@ export default class BaseApi<S extends object = {}> {
scry<T>(app: string, path: Path): Promise<T> { scry<T>(app: string, path: Path): Promise<T> {
return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise<T>); return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise<T>);
} }
async spider<T>(inputMark: string, outputMark: string, threadName: string, body: any): Promise<T> {
const res = await fetch(`/spider/${inputMark}/${threadName}/${outputMark}.json`, {
method: 'POST',
body: JSON.stringify(body)
});
return res.json();
}
} }

View File

@ -1,7 +1,9 @@
import BaseApi from './base'; import BaseApi from './base';
import { StoreState } from '../store/type'; import { StoreState } from '../store/type';
import { Patp, Path, PatpNoSig } from '~/types/noun'; import { Patp, Path, PatpNoSig } from '~/types/noun';
import _ from 'lodash';
import {makeResource, resourceFromPath} from '../lib/group';
import {GroupPolicy, Enc, Post} from '~/types';
export const createPost = (contents: Object[], parentIndex: string = '') => { export const createPost = (contents: Object[], parentIndex: string = '') => {
return { return {
@ -20,6 +22,68 @@ export default class GraphApi extends BaseApi<StoreState> {
return this.action('graph-store', 'graph-update', action) return this.action('graph-store', 'graph-update', action)
} }
private viewAction(threadName: string, action: any) {
return this.spider('graph-view-action', 'json', threadName, action);
}
createManagedGraph(name: string, title: string, description: string, group: Path) {
const associated = { group: resourceFromPath(group) };
const resource = makeResource(`~${window.ship}`, name);
return this.viewAction('graph-create', {
"create": {
resource,
title,
description,
associated
}
});
}
createUnmanagedGraph(name: string, title: string, description: string, policy: Enc<GroupPolicy>) {
const resource = makeResource(`~${window.ship}`, name);
return this.viewAction('graph-create', {
"create": {
resource,
title,
description,
associated: { policy }
}
});
}
joinGraph(ship: Patp, name: string) {
const resource = makeResource(ship, name);
return this.viewAction('graph-join', {
join: {
resource,
ship,
}
});
}
deleteGraph(name: string) {
const resource = makeResource(`~${window.ship}`, name);
return this.viewAction('graph-delete', {
"delete": {
resource
}
});
}
groupifyGraph(ship: Patp, name: string, toPath?: string) {
const resource = makeResource(ship, name);
const to = toPath && resourceFromPath(toPath);
return this.viewAction('graph-groupify', {
groupify: {
resource,
to
}
});
}
addGraph(ship: Patp, name: string, graph: any, mark: any) { addGraph(ship: Patp, name: string, graph: any, mark: any) {
this.storeAction({ this.storeAction({
'add-graph': { 'add-graph': {
@ -38,16 +102,17 @@ export default class GraphApi extends BaseApi<StoreState> {
}); });
} }
addPost(ship: Patp, name: string, post: Object) { addPost(ship: Patp, name: string, post: Post) {
let nodes = {}; let nodes = {};
const resource = { ship, name };
nodes[post.index] = { nodes[post.index] = {
post, post,
children: { empty: null } children: { empty: null }
}; };
this.storeAction({ return this.storeAction({
'add-nodes': { 'add-nodes': {
resource: { ship, name }, resource,
nodes nodes
} }
}); });
@ -63,7 +128,7 @@ export default class GraphApi extends BaseApi<StoreState> {
} }
removeNodes(ship: Patp, name: string, indices: string[]) { removeNodes(ship: Patp, name: string, indices: string[]) {
this.storeAction({ return this.storeAction({
'remove-nodes': { 'remove-nodes': {
resource: { ship, name }, resource: { ship, name },
indices indices
@ -107,7 +172,7 @@ export default class GraphApi extends BaseApi<StoreState> {
}); });
} }
getGraphSubset(ship: string, resource: string, start: string, end: start) { getGraphSubset(ship: string, resource: string, start: string, end: string) {
this.scry<any>( this.scry<any>(
'graph-store', 'graph-store',
`/graph-subset/${ship}/${resource}/${end}/${start}` `/graph-subset/${ship}/${resource}/${end}/${start}`

View File

@ -13,3 +13,8 @@ export function resourceFromPath(path: Path): Resource {
const [, , ship, name] = path.split('/'); const [, , ship, name] = path.split('/');
return { ship, name } return { ship, name }
} }
export function makeResource(ship: string, name:string) {
return { ship, name };
}

View File

@ -140,10 +140,21 @@ const addNodes = (json, state) => {
}; };
const removeNodes = (json, state) => { const removeNodes = (json, state) => {
const _remove = (graph, index) => {
if (index.length === 1) {
graph.delete(index[0]);
} else {
const child = graph.get(index[0]);
_remove(child.children, index.slice(1));
graph.set(index[0], child);
}
};
const data = _.get(json, 'remove-nodes', false); const data = _.get(json, 'remove-nodes', false);
if (data) { if (data) {
console.log(data); console.log(data);
if (!(data.resource in state.graphs)) { return; } const { ship, name } = data.resource;
const res = `${ship}/${name}`;
if (!(res in state.graphs)) { return; }
data.indices.forEach((index) => { data.indices.forEach((index) => {
console.log(index); console.log(index);
@ -151,13 +162,7 @@ const removeNodes = (json, state) => {
let indexArr = index.split('/').slice(1).map((ind) => { let indexArr = index.split('/').slice(1).map((ind) => {
return parseInt(ind, 10); return parseInt(ind, 10);
}); });
_remove(state.graphs[res], indexArr);
if (indexArr.length === 1) {
state.graphs[data.resource].delete(indexArr[0]);
} else {
// TODO: recursive
}
}); });
} }
}; };

View File

@ -12,6 +12,7 @@ import { LaunchState, WeatherState } from '~/types/launch-update';
import { LinkComments, LinkCollections, LinkSeen } from '~/types/link-update'; import { LinkComments, LinkCollections, LinkSeen } from '~/types/link-update';
import { ConnectionStatus } from '~/types/connection'; import { ConnectionStatus } from '~/types/connection';
import { BackgroundConfig, LocalUpdateRemoteContentPolicy } from '~/types/local-update'; import { BackgroundConfig, LocalUpdateRemoteContentPolicy } from '~/types/local-update';
import {Graphs} from '~/types/graph-update';
export interface StoreState { export interface StoreState {
// local state // local state
@ -36,7 +37,7 @@ export interface StoreState {
groupKeys: Set<Path>; groupKeys: Set<Path>;
permissions: Permissions; permissions: Permissions;
s3: S3State; s3: S3State;
graphs: Object; graphs: Graphs;
graphKeys: Set<String>; graphKeys: Set<String>;

View File

@ -0,0 +1,30 @@
import {Patp} from "./noun";
export interface TextContent { text: string; };
export interface UrlContent { url: string; }
export interface CodeContent { expresssion: string; output: string; };
export interface ReferenceContent { uid: string; }
export type Content = TextContent | UrlContent | CodeContent | ReferenceContent;
export interface Post {
author: Patp;
contents: Content[];
hash?: string;
index: string;
pending?: boolean;
signatures: string[];
'time-sent': number;
}
export interface GraphNode {
children: Graph;
post: Post;
}
export type Graph = Map<number, GraphNode>;
export type Graphs = { [rid: string]: Graph };

View File

@ -5,6 +5,7 @@ export * from './connection';
export * from './contact-update'; export * from './contact-update';
export * from './global'; export * from './global';
export * from './group-update'; export * from './group-update';
export * from './graph-update';
export * from './invite-update'; export * from './invite-update';
export * from './launch-update'; export * from './launch-update';
export * from './link-listen-update'; export * from './link-listen-update';