:resume-subscriptions? on subsequent init
hipitihop opened this issue · comments
We use JWT auth tokens with expiry time and organise to refresh the JWT token prior to expiry, in turn, when we get the refreshed token, we dispatch ::re-graph/init again, however, despite specifying
:resume-subscriptions? true
any existing subscriptions are dropped.
Is this a bug or do you recommend a way to deal with this use case ?
Hi,
That option is actually to determine the behaviour when the websocket connection is lost and then reconnected - it will re-subscribe if that flag is true, and won't if not. If you re-initialise re-graph it loses all state including which subscriptions existed (its usage is here: https://github.com/oliyh/re-graph/blob/master/src/re_graph/internals.cljc#L211)
There's nothing to directly support your use case, but it should be possible. You need to reach into the re-frame database via re-frame.db/app-db
and set your new connection-init-payload
(where I presume your token goes) at [:re-graph :re-graph.internals/default :websocket :connection-init-payload]
and then grab the websocket connection at [:re-graph :re-graph.internals/default :websocket :connection]
and close it - that should trigger re-graph into reconnecting the websocket, sending the new connection-init-payload
and resuming subscriptions.
If this works for you then we could add a new API call to achieve this so you're not delving around in the internals.
Hi thanks for your help @hipitihop and I work together
The following code worked to refresh the jwt authentication
(reg-event-fx
::success-jwt
(fn success-jwt-handler
[{:keys [db]} [_ jwt]]
(let [ms-prior-exp (* 5 60 1000) ; 5 minutes in milliseconds
jwt (utils/map->nsmap jwt "jwt")
refresh-ms (-> (get jwt :jwt/exp)
(* 1000)
(time.coerce/from-long)
(refresh-in-milliseconds ms-prior-exp))
headers {:headers {"Authorization" (str "Bearer " (get jwt :jwt/token))}}]
;; Hang on to the token we were given and init re-graph
(debug "Will refresh JWT in " refresh-ms "ms")
{:db (-> db
(assoc :jwt jwt)
(assoc-in [:re-graph :re-graph.internals/default
:websocket :connection-init-payload] headers)
(update-in [:re-graph :re-graph.internals/default
:websocket :connection] #(.close %)))
:dispatch-later [{:ms refresh-ms :dispatch [::fetch-jwt (get db :session) 1 true]}]}
))))
note the above code is heavy edited.
An API call to refresh the connection-payload would be great.
would also be nice if it triggered an immediate re-connection instead of having to wait the 5000ms or whatever the default timeout is.
Thanks
Hi,
Glad that worked. I just had a simpler idea - if your server side would support it, could you just update the connection init payload and then call (dispatch [:re-graph.internals/connection-init])
to send it to the server? Then you don't have the overhead of new connections and the delay.
Hi @stumitchell and @hipitihop did you have a chance to look at my suggestion?
Thanks,
yeah that seems to work too,
Not noticeably faster though still about a 6 second delay,
Stu
Hi @stumitchell and @hipitihop I have just pushed 0.1.14-SNAPSHOT
to clojars which adds the re-init
api described in the README, this should be a more elegant solution for you.