eyre: replace channel upon new GET request

As SSE are unidirectional, the client always realises that the
connection has failed faster than the server does. Hence, resuming a
subscription is useless, because channels can only be bound to one duct
at a time. Now, instead of failing a request for a channel
that is already bound to a duct, we replace the duct and continue
normally.
This commit is contained in:
Liam Fitzgerald 2021-06-24 10:24:55 +10:00
parent f0e11a8456
commit 9aaa44ff33
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
2 changed files with 19 additions and 10 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e0c05655f47ff81c8d4985a061d3ff57526a436adf25f667432a48c5cd10d438 oid sha256:9853dba422e06413e04c545a37f4a5eb92049000c30eedc8b56f23c82d484231
size 12190347 size 12392322

View File

@ -1206,15 +1206,24 @@
?~ maybe-channel=(~(get by session.channel-state.state) channel-id) ?~ maybe-channel=(~(get by session.channel-state.state) channel-id)
%^ return-static-data-on-duct 404 'text/html' %^ return-static-data-on-duct 404 'text/html'
(error-page 404 %.y url.request ~) (error-page 404 %.y url.request ~)
:: if there's already a duct listening to this channel, we must 400
::
?: ?=([%| *] state.u.maybe-channel)
%^ return-static-data-on-duct 400 'text/html'
(error-page 400 %.y url.request "channel already bound")
:: when opening an event-stream, we must cancel our timeout timer :: when opening an event-stream, we must cancel our timeout timer
:: if there's no duct already bound. Else, kill the old request
:: and replace it
:: ::
=. moves =^ cancel-moves state
[(cancel-timeout-move channel-id p.state.u.maybe-channel) moves] ?. ?=([%| *] state.u.maybe-channel)
:_ state
(cancel-timeout-move channel-id p.state.u.maybe-channel)^~
=/ cancel-heartbeat
?~ heartbeat.u.maybe-channel ~
:_ ~
%+ cancel-heartbeat-move channel-id
[date duct]:u.heartbeat.u.maybe-channel
=- [(weld cancel-heartbeat -<) ->]
%. [%cancel ~]
%* . handle-response
duct p.state.u.maybe-channel
==
:: the request may include a 'Last-Event-Id' header :: the request may include a 'Last-Event-Id' header
:: ::
=/ maybe-last-event-id=(unit @ud) =/ maybe-last-event-id=(unit @ud)
@ -1283,7 +1292,7 @@
|= =channel |= =channel
channel(events ~, state [%| duct], heartbeat (some [heartbeat-time duct])) channel(events ~, state [%| duct], heartbeat (some [heartbeat-time duct]))
:: ::
[[heartbeat (weld http-moves moves)] state] [[heartbeat :(weld http-moves cancel-moves moves)] state]
:: +acknowledge-events: removes events before :last-event-id on :channel-id :: +acknowledge-events: removes events before :last-event-id on :channel-id
:: ::
++ acknowledge-events ++ acknowledge-events