Robbie
Robbie

Reputation: 725

How is event-driven programming done?

My question is pretty simple: how is event-driven programming actually achieved?

To elaborate: I have a Rails application, every time a user makes a change on the website, the model writes that "change" to a text file (as JSON.)

What I'd like to do is hook an IRC bot to that "event." (the creation/modification of the text file.)

How is this done in general? It seems like it'd basically be an infinite loop. In pseudocode:

while (I'm Listening)
do
  if (output.txt Is changed)
    process("output.txt")

If this is how event-driven programming is achieved - how does it avoid locking up the CPU? As infinite loops have a tendency to do?

Edit- The IRC server/bot are hosted on a locally maintained box. The Rails application is hosted on a shared server. As of now, the only way I know for my IRC bot to communicate with the Rails app is via an HTTP request to the server (or something similar.) As I stated though, this question is really more general, as I'd like to garner a knowledge of event-driven programming in general.

I apologize if this question is impossibly simple, but my understanding of event driven programming consists of attaching pre-made event handlers to objects with jQuery; which really doesn't help when attaching an IRC bot [written in Ruby] to file I/O.

Thanks, Robbie

Upvotes: 2

Views: 5397

Answers (5)

Matchu
Matchu

Reputation: 85792

I'm not sure of the black magic behind it, but the popular Ruby gem EventMachine has a watch_file method that seems to handle your exact use case. No need to do all the heavy lifting yourself when someone else has already done it for you.

Share and enjoy.

EDIT: Your comment on Dave Sims's answer seems to imply that your Rails app and IRC bot live on different filesystems, and that the JSON file is served over HTTP. If that's the case, you're waiting on HTTP requests, anyway, and so sending an HTTP request as often as possible (though I'd recommend taking some small pauses to avoid upsetting your server) shouldn't block out the CPU, since it will pause while waiting for a response from the server. If the bot script needs to be performing other actions in the meantime, basing it on EventMachine and using the em-http gem to send event-based HTTP requests should take care of that.

I'm still not totally clear on exactly what you're doing, though.

Upvotes: 2

hurikhan77
hurikhan77

Reputation: 5931

Maybe you should create a DRb server or use a solution which uses this, like delayed_job. You can run the workers on different machines. The connection is made by connecting to a special port on your server. All you need to do is open this port on your firewall for the dedicated machine running the IRC bot. You can put ruby objects on the queue, so every change to the file can be mirrored by putting a ruby object on the queue which also contains this change. The worker will grab this a few seconds later, it will not be instant. But it's still pretty fast, uses low CPU and it is able to handle network outages.

Upvotes: 1

Ed Swangren
Ed Swangren

Reputation: 124642

A basic model that I am familiar with is done by creating a class which exposes events which can be subscribed to. This can be as simple as a collection of methods.

class Foo
  attr_accessor :event  #obviously not the right way to do it, but it will suffice

  def initialize
    @event = []
  end

  private
  def fire_event
    @event.each { |sub| sub.call }
  end
end

Now clients of this class can pass in a method that they wish to be executed when the event is fired.

f = Foo.new
f.event << lambda { puts 'event was fired' }

When the Foo class calls the fire_event method each procedure in the collection of procedures will be executed. There is no loop constantly checking some condition. When the condition arises, the firing method is called and the procedures are executed.

On a side note the example above is just that; an example. A real world event architecture would be more robust, but the will be similar. This may not even apply to your actual situation, but I am not a web guy and I don't know RoR and JSON and all those other fancy keywords, so I went high level. Hopefully it helps.

Upvotes: 2

Dave Sims
Dave Sims

Reputation: 5128

In general the sort of while/listener loop you're describing is created in a thread, for instance a UDP or TCP server waiting for a connection. But that doesn't really sound applicable to your concern. Rails and ActiveRecord define a number of built-in Observer-pattern style hooks on ActiveRecord models that may be of use to you. See here: http://api.rubyonrails.org/classes/ActiveRecord/Observer.html

If you really need to monitor the state of an external file and ActiveRecord or ActiveRecord-style callbacks don't work for you, you might monitor the file with a simplistic Ruby daemon process that manages the blocking while loop. But I'm still not sure why you wouldn't simply use the Rails code that modifies the file to also notify your IRC bot/process etc.

Upvotes: 1

Starkey
Starkey

Reputation: 9781

More often, its like this:

while (I'm Waiting to be notified) 
do 
  if (output.txt Is changed) 
    process("output.txt") 

There are ways in the OS (any OS) to wait to be notified without taking CPU time (such as a condition variable.) No event driven loop is sitting there spinning waiting for an event.

Upvotes: 4

Related Questions