I'm trying to setup a serverside websocket client to be able to consume messages from an existing 3rd party websockets service.
I need to be able to:
- Continue running the existing app, which consists mainly of backend api services
- Consume messages from the 3rd party websocket server
- Use data from those messages in existing sidekiq workers
I have used the client side configuration from faye web sockets and followed the heroku/websockets example here both with and without the middleware config in app.rb. I can connect to the websocket and receive messages without issues, but that seems to lock up everything else and upon deploying to heroku the app crashes.
When configured as a middleware in app.rb the error is:
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
When not configured there, the app never even tries to start because EM takes over.
I ended up moving the EM code from the faye web sockets link above inside of a Sidekiq worker and this did the trick. But will this work? Can a sidekiq worker run indefinitely or will it eventually get terminated? I have been unable to find any examples that use strictly a server-side client, so I'm at a loss for whether this workaround is sustainable or not.
Any thoughts on what the best way to approach this is?
Obviously, the WebSocket client will use one thread (or the main one), blocking it permanently, stopping the rest of the app from running indefinitely.
This works because Sidekiq and Rails will run on different processes / dynos, but it definitely doesn't look like the cleanest way and Sidekiq is not fit for this kind of long-lived process like web servers.
You shouldn't use a long-running process as a middleware. A middleware should just delegate to the next one in the chain. Although there are ways to perhaps accomplish this, like running your server on a new thread (which might even fail due to GIL), the best is to use a different process entirely to run the websocket client which has access to the Rails context.
Your procfile could look like this:
That way your client is running in
parallel, as opposed toconcurrently(which is what it does now).If you still want to use the middleware (which I highly oppose), just run two different Rails processes, one with the middleware and one without.