I am writing a bot for Matrix using Ruby which allows users to subscribe to RSS feeds and when a new item shows up on the feed it gets sent to the room.

The problem I have come up against is how do I get the program to sit and wait for new commands from users while also fetching feeds every 2 minutes?

Some solutions I have found would be to check for new commands and then check to see if it's time to fetch the feeds again. This might work because waiting for new commands from Matrix is non blocking as you can request all the new messages since last time without having to sit and wait for something to come in. This feels a little hacky though and I'm not sure if it's the best way to go about things.

Another solution would be to create 2 separate programs. One which listens for commands from users and another one that is run by a cron job that sends new messages to the room when it finds a new item on rss. This would be possible because Matrix doesn't have a constant connection like IRC but uses a HTTP API to send and receive messages. The problem I see with this one is managing a database shared between 2 programs seems overly complex and could result in issues.

Another way would be multithreading but I am pretty unfamiliar with how this works and ruby doesn't seem to support it from what I have seen.

What would be the best way to handle this? Are any of the things I have come up with a good solution?

  • The best way is the one that is most suitable for your specific scenario and requirements. – Robert Harvey Oct 28 '17 at 19:31

I am no Ruby expert, but after some brief research, I would probably use an in-process job scheduler. rufus-scheduler appears to be the go-to scheduler for Ruby.

At startup:

  • Connect to Matrix
  • Start the scheduler
  • Trap SIGINT so if someone sends Ctrl-C, I can clean up gracefully before exiting the process
  • Sleep the main thread forever

Rufus would schedule the "check RSS feeds" job to run every 2 minutes on background threads.

Below is a sketch of the idea. Obviously missing from this example are error handling, proper logging, etc.

#!/usr/bin/env ruby

require 'rufus-scheduler'

scheduler = Rufus::Scheduler.new

puts "connecting to Matrix"
conn = connect_matrix()

puts "scheduling the RSS job"
scheduler.every "2m" do
  puts "checking RSS feeds"
  puts "sending message to Matrix"

Signal.trap("INT") do
  # clean up gracefully
  puts "exiting"

puts "started"
| improve this answer | |
  • This seems like it could work. Will have to give it a shot. – Qwertie Nov 3 '17 at 3:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.