ingesolvoll / kee-frame

re-frame with batteries included
Eclipse Public License 2.0
357 stars 27 forks source link

kee-frame with chord #26

Closed schmfr closed 6 years ago

schmfr commented 6 years ago

I would like to use kee-frame and sente (with websockets) for my SPA. When the browser opens a url like http://kee-frame-sample.herokuapp.com/league/452/table I have to wait for an established websocket connection of sente before the controller can handle the url. Because the controller needs the established websocket to request additional data. Currently I am using a set of re-frame events and app-db modifications to accomplish this. Do you know a more sophisticated approach? An integration in kee-frame would be even nicer.

ingesolvoll commented 6 years ago

It's a bit difficult to say without looking at more specific examples. But let me try to make some assumptions and suggest something, and then you can tell me what does not match.

I have the same case at work, where we start and stop websockets on certain URLs. The code is not that much shorter in kee-frame, but in my experience it's much easier to follow the logic.

Nothing stops you from using several different controllers for the same URL. I discovered this trick early on, it's very useful! See https://github.com/ingesolvoll/kee-frame-sample/blob/master/src/cljs/kee_frame_sample/controller/live.cljs, where I used this trick to trigger an event both immediately and every 10 seconds.

ingesolvoll commented 6 years ago
(reg-controller ::socket-controller
                {:params (fn [{:keys [handler route-params]}]
                           (when (= :my-socket-page handler)
                             true)) ;; Or some other value that should be sent to the start event
                 :start  [::start-the-socket]
                 :stop  [::stop-the-socket]})
schmfr commented 6 years ago

Thanks for the nice hint. Even though I need a websocket for all urls I will use the suggested logic.

Besides that I still have the problem of how to delay the request of further data in the controller until the websocket is established. Currently I am using some kind of queuing to accomplish this.

  1. Open the url /your/page/that/needs/a/socket/and/data/XYZ.
  2. A controller triggers the event [:start-the-socket] and another controller triggers [:queue-data-to-request "XYZ"]. (The order of these events is out of my control.)
  3. The handler for :queue-data-to-request appends some {:queue-data-to-request "XYZ"} to app-db.
  4. When the websocket is established an event [:websocket-established] is triggered.
  5. The handler for :websocket-established dispatches events that request the data from :queue-data-to-request.

I am not that experienced in developing a SPA but for me it seems a lot of code for a "common problem". Moreover it suffers of a (maybe unrealistic) race-condition that occurs when the websocket is established before the handler for :queue-data-to-request was executed.

Do you know any logic/pattern to avoid the drawbacks of my current solution?

ingesolvoll commented 6 years ago

Actually we have pretty much identical problems on our end. You depend on a socket for sending and receiving messages. Both initial messages and continuous messages. The initial message is sent only once, so you can't drop that one. And you don't have control over timing, so initial message must be queued somehow until the socket is ready.

I'm not sure if this is something kee-frame is supposed to solve. But if there is a natural fit, I would love to hear any ideas. We have tried a few things, in addition to your procedure. One promising lead is to put a core.async buffer channel in front of the websocket, so you send message to the buffer channel. Then there is logic to pipe messages from the buffer channel to the websocket when it's available.

schmfr commented 6 years ago

Thanks a lot for your reply. This gives me confidence that I do not solve the problem totally inappropriate.

From my point of view I would appreciate the integration of an optional buffer channel into kee-frame. Moreover you can provide effect-handlers for [:add-event-to-queue myevent] and :dispatch-all-queued-events (or/and :dispatch-last-queued-event).

Well, obviously the decision is up to you whether this in the scope of kee-frame or not.

ingesolvoll commented 6 years ago

For now I'm thinking it's outside the scope.

It was definitely very useful to hear about your case though. As I said we are working on the same thing, and we're not happy how it looks either. Will keep working on it, and it might become a blog post or something else in the future. Thanks for posting the issue, will close it now.

mudgen commented 6 years ago

I look forward to any blog post that might come out regarding this. I am also interested in adding web sockets to my kee-frame application.

ingesolvoll commented 6 years ago

Got some ideas around this, will use this issue to track them