Thread and websocket

101 views
Skip to first unread message

Jean-eric Godard

unread,
Nov 6, 2021, 2:54:04 PM11/6/21
to Roda
Hello,

I'm trying to build a home monitoring system using roda.

I need to monitor a file on my server: when a file is modify I'd like to send a message using a websocket.

I try to implement a solution using the filewatcher gem, as shown below

plugin "faye/websocket", adapter: :thin, ping: 45
route do |r|
if Faye::WebSocket.websocket?(env)
ws = Faye::WebSocket.new(env)
ws.on :message do |event|
client_data = event.data
if client_data.is_json?
 data = JSON.parse(client_data)  
t=Thread.new do
Filewatcher.new(data[:file]).watch do |changes|
ws.send(data[:file]
end
t.join
...

The problem is that the roda doesnt respond anymore.
I imagine this is not the way to implement threads with Roda but didn't find how to proceed.

If someone can help me or teach me how to use threads whithin Roda I'll be very gratefull.

Thanks

Jean-Eric

Jeremy Evans

unread,
Nov 6, 2021, 3:09:20 PM11/6/21
to ruby...@googlegroups.com
Thin is an event driven webserver, and probably doesn't work well with creating and joining thread at runtime. For what it's worth, I'm not sure what the point of creating a thread just to join it immediately in this case.

Since it sounds like you only need unidirectional communication and not bidirectional communication, you are probably better off using something like message_bus as opposed to websockets.  The roda-message_bus gem provides message_bus integration for Roda.  If you really want to use websockets, you could try the websockets plugin (https://github.com/jeremyevans/roda/blob/2.28.0/lib/roda/plugins/websockets.rb).  It was removed in Roda 3 mostly because it made the tests take much longer and not be as reliable, but should still work fine.  You could just copy and paste the plugin code into your application.

Thanks,
Jeremy

Luke Stutters

unread,
Nov 6, 2021, 7:32:20 PM11/6/21
to ruby...@googlegroups.com
Dear Jean-Marc,

I am not sure why you want to keep watching these files. Files are not doing anything suspicious, it is the processes that are up to no good. But I know you have a file problem so this might help.

I have been developing something similar using Roda Server Sent Events because I do not like the web sockets. In fact, some of them are very suspicious. I could make a socket but I prefer not to.

The code that watches the suspicious file looks like this:

#!/usr/bin/ruby
# File watcher using Roda and SSE

require 'roda'
require 'filewatcher'

# Use an array of ruby queues to keep track of the connections
# Global variable is best variable
QUEUES = []

class App < Roda
  plugin :streaming # Makes the SSE work

  route do |r|
    # "Upgrade" the connection to an SSE
    response['Content-Type'] = 'text/event-stream'
    response['X-Accel-Buffering'] = 'no' # for nginx (boooooo)

    # Add the connection to the queue array
    q = Queue.new
    QUEUES << q
    stream(loop: true, async: true, callback: proc { QUEUES.delete(q) }) do |out|
      out << "data: #{q.pop}\n\n"
    end
  end
end

# Update all connections in a single thread
Thread.new do
  Filewatcher.new('my_suspicious_file.txt').watch do |changes|
    # Newlines break SSEs, need to do stuff like this:
    puts changes.inspect
    update = changes.gsub(/[\r\n]/, "\ndata: ")

    # Send the update to each SSE connection
    QUEUES.each do |q|
      q.push update
    end
  end
end

# Listen everywherrr
Rack::Handler.default.run(App, Hostname: '0.0.0.0', Port: 8080)

Then I can listen for file changes using this in ruby:

#!/usr/bin/ruby

# Listen for file eventz
require 'ld-eventsource'

sse_client = SSE::Client.new("http://localhost:8080") do |client|
  client.on_event do |event|
    puts "I received an event of type #{event.type}: #{event.data}"
  end
end

while true
  sleep 1
end

If you are a java script:
var evtSource = new EventSource("http://localhost:8080");
evtSource.onmessage = function(event) { console.log(event) }

You will have to install gems, you could use bundler but it makes me confused:
sudo gem install roda filewatcher ld-eventsource

It is not really what you asked for but I enjoyed making it.

--
You received this message because you are subscribed to the Google Groups "Roda" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-roda+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-roda/CADGZSSfXd2jhtME7tTeez73kC87_y%3DGJBH5SdQ4ry%3DGSvfwx%3Dg%40mail.gmail.com.

Jean-Eric Godard

unread,
Nov 7, 2021, 4:31:23 AM11/7/21
to Roda
Thanks Jeremy and Luke for your answers. 

To explain a bit more I’m building an open source cross platform frameworks based on Cordova Ruby and opal that can create applications, be booted and used as gui for FreeBSD  but  also has web mode. 
I chose to test the framework with two use cases : home automation and code learning,/machine scripting.
Both use case imply needs to use background  tasks. 
In the first use case I need to monitor various analog inputs and send a message to connected user when a value is reach. ( ex monitoring température ) so Ruby needs to check inputs every second and refresh the connected user browsers. 
In the second case user create script and when user save it user that subscribe the to the script have their background task refreshed ( ex : a new algorithm for home automation)

Anyway I’ll try both solutions,  maybe roda-message_bus could partially solve the problem. 
Jeremy you talk about websocket plugins isn’t it the one I already used I am a bit confused. 
Luke I’ll examine your answer it’ll take make a bit of time to understand and use it but it maybe an interesting way. 

The frameworks is also used to create websites, interactive video, video games, animations,  and much more..using Ruby. 
The state and code quality of the  project is closer to a proof of concept than a production ready solution for now. 
I’m not an expert programmer’ I just have the will to make it real!
If you are curious here is the link : https://github.com/atomecorp/atome

Thanks for your precious help. 

Cheers 

Jean-Eric 

Jean-eric Godard

unread,
Nov 7, 2021, 8:46:50 AM11/7/21
to Roda
hi again, 

Luke, after analyzing your solution I succeed to adapt to monitor analog inputs and files change in a separate thread and push the result using websockets,and it works perfectly!! 

Thanks a lot to you all!

Jean-Eric
Reply all
Reply to author
Forward
0 new messages