No commit activity in last 3 years
No release in over 3 years
ProcessMailer for concurrent data processing
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

 Project Readme

Important note¶ ↑

This library is in an alpha state and still being developed and tested

ProcessMailer¶ ↑

The idea is simple. Mail data to processes.

What?¶ ↑

The ProcessMailer mails data. To processes. (Oh, it also allows you to send data to hooks, which uses a thread pool and doesn’t restrict memory access, but that’s not the point of this library!) So, the better question might be, why? Well, for one, you can make things faster. See, what’s great about this library is that you encapsulate your logic in little processes that have been forked. Data is then packaged up and sent to these processes where the processes can then do what ever they please to that piece of data. This simple design, though some what more complicated in use, allows you to make use of multiple cpus/cores where using something like a thread pool would keep you limited to a single core.

How does it work?¶ ↑

Well, the general overview is something like this:

Main<||>---------PostOffice<>----------*Postbox

In crappy, texty, UMLy fashion, what we have is a Main program composed of a PostOffice. That PostOffice has an aggregation of zero or more Postboxes it knows about. That’s the basic structure.

How about an example?¶ ↑

Sure, lets make something simple. We will start out using blocks:

require 'processmailer'

po = ProcessMailer::PostOffice.new
po.register{|a| puts "Decrement: #{a}"; a -= 1; a}
po.register{|a| puts "Increment: #{a}"; a += 1; a}

po.deliver(1)
sleep(2)
po.clean

First, we create our PostOffice. Next, we register two Postboxes using blocks. The argument is the Object that will be delivered via the PostOffice. After registering two Postboxes, we deliver a Fixnum. The PostOffice delivers messages to registered Postboxes using a thread pool, so our main line of execution will continue. So, lets sleep for a couple seconds to see some output generated. Finally, we clean the PostOffice which removes all registered Postboxes.

Blocks suck¶ ↑

Well, not really, but they can be a bit restrictive. For something a little more robust, we create a class that’s a subclass of Postbox, and let it do the work:

require 'processmailer'

class Test < ProcessMailer::Postbox
    def initialize(args)
        super
        @foo = 2
    end
    def process(obj)
        puts "Decrement: #{obj}"
        obj -= @foo
    end
end

po = ProcessMailer::PostOffice.new
po.register(Test)
po.register{|a| puts "Increment: #{a}"; a += 1; a}

po.deliver(1)
sleep(2)
po.clean

This is doing the same basic thing we did in the blocks. The Test class is simply a subclass of Postbox, and the process method is overridden to do the grunt work. The reason we send in a Class type, and not the instantiated object, is to allow the PostOffice to do the proper creation and forking. That’s pretty much it.

One last thing¶ ↑

The result of the process method or block for a given Postbox will be returned to the PostOffice for delivery. That is why the examples run continuously. Returning a nil value will stop delivery. This means that the example below will only output two lines:

require 'processmailer'

po = ProcessMailer::PostOffice.new
po.register{|a| puts "Decrement: #{a}"; nil}
po.register{|a| puts "Increment: #{a}"; nil}

po.deliver(1)
sleep(2)
po.clean

ASCII Representation:¶ ↑

[PostOffice]------[message]---->[Postbox]
      ^                             |
      -----------[return val]-------'

Informations¶ ↑

Author: spox <spox@modspox.com>
License: LGPLv3