Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace polling in admin and status pages with realtime updates #473

Open
daltonfury42 opened this issue Jan 16, 2021 · 14 comments
Open

Replace polling in admin and status pages with realtime updates #473

daltonfury42 opened this issue Jan 16, 2021 · 14 comments
Assignees
Labels
discuss full-stack Requires work to be done at backend too

Comments

@daltonfury42
Copy link
Collaborator

daltonfury42 commented Jan 16, 2021

Is your feature request related to a problem? Please describe.
Currently our UI periodically calls the backend server in the background to get updates. Plus we have a Refresh button:

image

Describe the solution you'd like
Can we use FCM to push notifications to clients?

Describe alternatives you've considered
Else our simple polling method would work for now. But this is one step closer to building a more interactive dashboard in future.

Additional context
We might need to make backend changes if we are to do this. We are using FCM to push SMS events to the companion app. We would have to extend the backend to make this possible.

@daltonfury42 daltonfury42 changed the title Explore Firebase Cloud Message for Sending Updates Explore Firebase Cloud Messaging for Sending Updates Jan 16, 2021
@daltonfury42 daltonfury42 added full-stack Requires work to be done at backend too You Can Do This Will be accepted on priority and removed discuss labels Jan 17, 2021
@daltonfury42 daltonfury42 changed the title Explore Firebase Cloud Messaging for Sending Updates Integrate Firebase Cloud Messaging for Sending Updates Jan 17, 2021
@daltonfury42 daltonfury42 added discuss and removed You Can Do This Will be accepted on priority labels Jan 17, 2021
@daltonfury42
Copy link
Collaborator Author

@maaverik if we are doing this, does it makes sense to store such data globally in redux?

@maaverik
Copy link
Collaborator

maaverik commented Jan 17, 2021

Do you see a case where that would be beneficial? I can't really think of any. Each instance of our site would only need FCM notifications for only one component, right (either admin or status component) ?

@daltonfury42
Copy link
Collaborator Author

I was thinking then that the updates would be easier. We would be writing a service file that will listen and process push notifications. This file can update the global store, and then any component listening to it will get the update/rerender.

We don't want to have the react component listen for update, we want to keep it outside of react components if possible.

@maaverik
Copy link
Collaborator

Okay, I see your point. I was thinking of creating a service component and maintaining objects of it inside the status and admin components, but your idea sounds better. So you're saying maintain two redux state variables for admin and status which the respective components listen to and then use these in the service according to whether the client is a queue admin or member, right? Or did you mean something else?

@daltonfury42
Copy link
Collaborator Author

daltonfury42 commented Jan 17, 2021

Yes. Think through it more though. When we move into this design, the network calls made by queue.js and token.js service files would also update the same store from within the service files itself. That way, those network call updating the local component states would also go out of the component files, and become more centralised, which I think is a better design:

So it will be one source of truth, set by multiple service layer modules, and rendered by react at presentation layer.

@daltonfury42
Copy link
Collaborator Author

We are using redux toolkit, but the principles are borrowed from here: https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow

@maaverik maaverik self-assigned this Jan 23, 2021
@maaverik
Copy link
Collaborator

maaverik commented Jan 24, 2021

I've been researching FCM for a bit and I think it doesn't fit our requirement since it needs user permission to work. If users don't allow notifications, the underlying push API that FCM uses can't work, and we need to get permission even though we intend to use FCM only for getting real-time updates from the server and not show notifications. (https://stackoverflow.com/questions/53403792/can-i-use-firebase-cloud-messaging-without-notification-permission-javascript). Using other firebase solutions will become expensive, and besides, we've already tried that route once. I'm going to look into how effective using webSockets or long polling would be.

@daltonfury42
Copy link
Collaborator Author

daltonfury42 commented Jan 24, 2021

Yes, asking for user permissions, we should avoid.

@maaverik maaverik changed the title Integrate Firebase Cloud Messaging for Sending Updates Replace polling in admin and status pages with realtime updates Feb 7, 2021
@maaverik
Copy link
Collaborator

maaverik commented Feb 7, 2021

I have to think through this more, but I have two approaches right now. The idea is to make our update process event-driven; instead of every instance of our site constantly polling for updates, the server selectively sends updates. The queue admin gets updates only when some events happen on the queue with someone joining or leaving the queue, and for the queue members, we can handle changes in the number of people in front of them by sending a broadcast once someone's turn is up or someone is removed.

  1. Use websockets to manage bidirectional communication with the server on the admin and status pages. We can open a websocket connection and send both client and server updates using this. Looking into socket.io for this, not sure yet how well it works with our java backend.

  2. Use server-sent events. This way, the clients subscribe to a stream from the server (pertaining to a particular queue). The communication from client to server happens like before over http.

SSE seems more applicable to me for our use-case, but I'm still wondering if using websockets now will help us later on with adding new features. I also don't know yet about the impact on server performance on using websockets compared to SSE. Will do more research on this.
https://medium.com/system-design-blog/long-polling-vs-websockets-vs-server-sent-events-c43ba96df7c1

@daltonfury42
Copy link
Collaborator Author

daltonfury42 commented Feb 7, 2021

@maaverik at the end, compare all the approaches taking impact vs cost into account.

Our periodic refresh that we currently do works well, just that there is a 10s latency and people keep polling every 10s. Both of these are things we are fine with.

So whatever we do, since impact is low, we should make sure the cost is also low, to justify doing this.

For example, if we use something like websockets, suddenly backend becomes stateful, and the costs doesn't justify anymore. We should avoid going stateful as much as possible, unless there is a good reason to do so.

@daltonfury42
Copy link
Collaborator Author

daltonfury42 commented Apr 2, 2021

Adding one more possible approach to our list, since we are becoming more PWA compliant. This would not need us to have an open connection, and would allow us to post events even when the site is not open [ref]. Usage example with a java backend here.

The biggest downside is that it's still a experimental feature and not sure if it will work on all browsers or even cross browser. [ref]. Ideal solution would be one that would work even across web and native apps.

Regarding SSE, we have to look a bit deeper as to how we would have multiple event streams, one per each queue, and the resource impact due to having an open connection if they do.

Java has support for both. SSE and socket.io

@maaverik
Copy link
Collaborator

maaverik commented Apr 2, 2021

Oh cool, this is new. It's going to take me some time, but let me try getting a POC PR ready after understanding all these options.

I had stumbled on this paper that compares performance between polling, SSE and websockets (tldr; SSE and WS performs better for frequent small messages). It's a nice read.

@maaverik
Copy link
Collaborator

maaverik commented Apr 7, 2021

So I read more about these options. The push API would have been great for us, from what I understand, it's almost the same as Firebase cloud messaging, but it has the same user permission problem because of which we abandoned the FCM idea 😞. I'm pretty sure the majority of users won't give permissions for anything.

Of the other options, the open connection requirement is annoying, and we'll need to handle connection breaks, but if we want to go this route (which I think is worth trying out), I'm leaning towards SSE over WS. WS needs more headers and could become a headache when dealing with proxies or load balancing (ref) while SSE supports automatic reconnections (I think socket.io does this for WS too) and seems to need less maintenance overall.

I couldn't find any ready made solutions for having multiple event streams, we'll need to maintain some data structure on the server for bookkeeping. I have a vague idea of how we could approach this, let me think through it some more.

@daltonfury42
Copy link
Collaborator Author

Wondering how github... They update their UI when we push a new branch etc. 🤔

Of the other options, the open connection requirement is annoying, and we'll need to handle connection breaks, but if we want to go this route (which I think is worth trying out), I'm leaning towards SSE over WS. WS needs more headers and could become a headache when dealing with proxies or load balancing (ref) while SSE supports automatic reconnections (I think socket.io does this for WS too) and seems to need less maintenance overall.

Both seems ok to me. I'm also leaning to SSE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discuss full-stack Requires work to be done at backend too
Projects
None yet
Development

No branches or pull requests

2 participants