@@ -18,6 +18,7 @@ import Ur.Cmd
1818import Ur.Cmd.Internal
1919import Ur.Constructor as C
2020import Ur.Deconstructor as D
21+import Ur.NounDiff exposing (Patch, deconstructPatch)
2122import Ur.Requests exposing (..)
2223import Ur.Sub
2324import Ur.Sub.Internal
@@ -32,6 +33,7 @@ type alias SubDict msg =
3233 ( String, String, List String )
3334 { deconstructor : D.Deconstructor (msg -> msg) msg
3435 , number : Int
36+ , sink : Bool
3537 }
3638
3739
@@ -49,6 +51,7 @@ type alias Model app msg =
4951 , eventId : Int
5052 , flags : Flags
5153 , requestsToRetry : List UrbitRequest
54+ , sinks : Dict Int Noun
5255 }
5356
5457
@@ -171,7 +174,6 @@ update inp msg model =
171174 ( appModel, appCmds ) =
172175 inp.update msg_ model.app
173176
174− -- { subscriptions, eventId, subscriptionRequests, subscriptionIntMapping } =
175177 subsResult =
176178 processUrSubs
177179 model.eventId
@@ -244,14 +246,51 @@ update inp msg model =
244246 Dict.get messageId model.subscriptionIntMapping
245247 |> Maybe.andThen (\key -> Dict.get key model.subscriptions)
246248 of
247− Just { deconstructor } ->
248− case D.run (D.cell D.ignore (D.cell D.ignore deconstructor)) rest of
249− Just subMsg ->
250− ( model_, pureCmd (AppMsg subMsg) )
251−
252− -- Got gargbage
253− Nothing ->
254− ( model_, ackCmd )
249+ Just { deconstructor, sink } ->
250+ if sink then
251+ case D.run (D.cell D.ignore (D.cell D.ignore deconstructSink)) rest of
252+ Just (Flush noun) ->
253+ ( { model | sinks = Dict.insert messageId noun model.sinks }
254+ , case D.run deconstructor noun of
255+ Just subMsg ->
256+ pureCmd (AppMsg subMsg)
257+
258+ -- Got garbage
259+ Nothing ->
260+ Cmd.none
261+ )
262+
263+ Just (Drain patch) ->
264+ case Dict.get messageId model.sinks of
265+ Just oldNoun ->
266+ let
267+ newNoun =
268+ Ur.NounDiff.apply patch oldNoun
269+ in
270+ ( { model | sinks = Dict.insert messageId newNoun model.sinks }
271+ , case D.run deconstructor newNoun of
272+ Just subMsg ->
273+ pureCmd (AppMsg subMsg)
274+
275+ Nothing ->
276+ Cmd.none
277+ )
278+
279+ Nothing ->
280+ ( model, Cmd.none )
281+
282+ -- Got garbage
283+ Nothing ->
284+ ( model, Cmd.none )
285+
286+ else
287+ case D.run (D.cell D.ignore (D.cell D.ignore deconstructor)) rest of
288+ Just subMsg ->
289+ ( model_, pureCmd (AppMsg subMsg) )
290+
291+ -- Got gargbage
292+ Nothing ->
293+ ( model_, ackCmd )
255294
256295 -- Got a fact for a subscription we do not hold
257296 Nothing ->
@@ -280,7 +319,7 @@ update inp msg model =
280319 |> tag model.eventId
281320 in
282321 ( { model | eventId = eventId }
283− , send { url = url, requests = reqs, success = OpenConnection, error = NeedsActivation }
322+ , send { url = url, requests = reqs, success = OpenConnection, error = Noop }
284323 )
285324
286325 Noop ->
@@ -307,6 +346,19 @@ update inp msg model =
307346 )
308347
309348
349+type Sink
350+ = Flush Noun
351+ | Drain Patch
352+
353+
354+deconstructSink : D.Deconstructor (Sink -> c) c
355+deconstructSink =
356+ D.oneOf
357+ [ D.cell (D.const D.cord "flush") D.tar |> D.map Flush
358+ , D.cell (D.const D.cord "drain") deconstructPatch |> D.map Drain
359+ ]
360+
361+
310362processCmd : EventId -> Ur.Cmd.Cmd msg -> ( EventId, Cmd (Msg msg), List ( EventId, UrbitRequest ) )
311363processCmd eventId urCmds =
312364 let
@@ -336,10 +388,10 @@ pureCmd msg =
336388
337389processUrSubs :
338390 EventId
339− -> Dict ( Ship, Agent, Path ) { deconstructor : d, number : EventId }
340− -> Dict ( Ship, Agent, Path ) d
391+ -> Dict ( Ship, Agent, Path ) { deconstructor : d, number : EventId, sink : Bool }
392+ -> Dict ( Ship, Agent, Path ) { deconstructor : d, sink : Bool }
341393 ->
342− { subscriptions : Dict ( Ship, Agent, Path ) { deconstructor : d, number : EventId }
394+ { subscriptions : Dict ( Ship, Agent, Path ) { deconstructor : d, number : EventId, sink : Bool }
343395 , eventId : EventId
344396 , subscriptionRequests : List ( EventId, UrbitRequest )
345397 , subscriptionIntMapping : Dict EventId ( Ship, Agent, Path )
@@ -348,7 +400,7 @@ processUrSubs eventId existingSubscriptions urbitSubs_ =
348400 let
349401 urbitSubs =
350402 urbitSubs_
351− |> Dict.map (\_ deconstructor -> { deconstructor = deconstructor })
403+ |> Dict.map (\_ { deconstructor, sink } -> { deconstructor = deconstructor, sink = sink })
352404
353405 ( eventId_, newSubscriptionActions ) =
354406 Dict.diff urbitSubs existingSubscriptions
@@ -371,10 +423,11 @@ processUrSubs eventId existingSubscriptions urbitSubs_ =
371423 newSubscriptions =
372424 Dict.merge
373425 (\_ _ x -> x)
374− (\key number { deconstructor } ->
426+ (\key number { deconstructor, sink } ->
375427 Dict.insert key
376428 { deconstructor = deconstructor
377429 , number = number
430+ , sink = sink
378431 }
379432 )
380433 (\_ _ x -> x)
@@ -417,6 +470,7 @@ init inp ( app, appCmds ) flags =
417470 inp.urbitUrl app ++ "/~/channel/" ++ flags.uid
418471 in
419472 ( { subscriptions = subsResult.subscriptions
473+ , sinks = Dict.empty
420474 , subscriptionIntMapping = subsResult.subscriptionIntMapping
421475 , app = app
422476 , connected = False
@@ -439,7 +493,7 @@ init inp ( app, appCmds ) flags =
439493
440494subscriptions :
441495 { a | subscriptions : b -> Sub msg, onEventSourceMsg : (JD.Value -> Msg c) -> Sub (Msg msg) }
442− -> { d | app : b, requestsToRetry : List e }
496+ -> { d | app : b, requestsToRetry : List e, connected : Bool }
443497 -> Sub (Msg msg)
444498subscriptions inp model =
445499 Sub.batch
@@ -450,4 +504,9 @@ subscriptions inp model =
450504
451505 else
452506 Time.every 1000 (always RetryRequests)
507+ , if not model.connected then
508+ Time.every 10000 (always NeedsActivation)
509+
510+ else
511+ Sub.none
453512 ]