gitea icon indicating copy to clipboard operation
gitea copied to clipboard

WIP: Websocket replacement for Eventstream

Open zeripath opened this issue 3 years ago • 7 comments
trafficstars

Very much work-in-progress attempt at converting the eventstream into a websocket.

The idea would be to use the reader to allow for more notifications to be watched and so on.

zeripath avatar Jul 29 '22 21:07 zeripath

So the problem I'm having right now is that the Dom update after the notification event has been received isn't happening and I just don't understand why. Hence all the logging there.

zeripath avatar Jul 29 '22 22:07 zeripath

Note to frontport #20544 into this PR.

Gusted avatar Jul 29 '22 22:07 Gusted

OK... now the next thing to do is to either merge the websocket and eventsource sharedworkers or just kill the eventsource sharedworker.

Realistically I think everything that supports eventsources also supports websockets so it's probably not worth keeping both around unless there's some reason why websocket cannot be supported on the server end but eventsource can be. (Is there?)

I think we could also make a COMET backend also work too.


OK looking at things like Socket.io and sockjs there are still cases where WebSocket won't work because of proxies so we will still need to have a fall back. However, in both of these cases the go server backends appear in a poor state so we need to just do the work to implement this ourselves I think.

Now the EventSource would still work as the SSE in those cases so we just need the POST part to work and some way to detect when the WebSocket just isn't going to work.

zeripath avatar Jul 30 '22 11:07 zeripath

I'd just kill the EventSource. As I see it, it's a graceful degradation if WebSocket doesn't work because the features that rely on it are not something I would consider critical.

silverwind avatar Aug 02 '22 19:08 silverwind

As for reconnection behaviour, you can take a hint from sockette or even use it as it's a tiny wrapper.

silverwind avatar Aug 02 '22 19:08 silverwind

Actually I may have some SharedWorker WebSocket code with reconnects to share as I'm working on one currently. Still need to clean it up thought.

silverwind avatar Aug 02 '22 21:08 silverwind

Here's my rather terse script of a SharedWorker that processes JSON on a WebSocket and does the reconnecting. It's based on sockette with all the cruft removed. I'm not sure if ECONNREFUSED actually applies to web, I know this error code only from Node.js, but I guess it does not hurt to keep.

I think it's preferable to do as little work as possible in the worker because workers are a pain in the ass to debug. Just have the worker passing the JSON and have the main thread do the rest.

onconnect = async ({ports: [port]}) => {
  let ws;

  function open() {
    return new Promise((resolve) => {
      ws = new WebSocket(`${location.origin.replace(/^http/, "ws")}/ws`);
      ws.addEventListener("message", ({data}) => port.postMessage(JSON.parse(data)));
      ws.addEventListener("open", resolve);
      ws.addEventListener("close", () => setTimeout(open, 1000));
      ws.addEventListener("error", (e) => e?.code === "ECONNREFUSED" && setTimeout(open, 1000));
    });
  }

  port.addEventListener("message", ({data}) => {
    ws.send(JSON.stringify(data));
  });

  await open();
  port.start();
};

silverwind avatar Aug 03 '22 14:08 silverwind

Would still recommend using the SharedWorker code from https://github.com/go-gitea/gitea/pull/20543#issuecomment-1204032900, or if SharedWorker proves too hard (it certainly sucks to debug SharedWorker in Chrome or Firefox), websocket could be done on main thread as well (with similar websocket init code), but it'll eat more resources, both server- and client-side.

silverwind avatar Sep 05 '22 21:09 silverwind