Object Channel

In some testing scenarios (such as signal handling), it is helpful to be able to test from outside a process; common methods for communicating between two ends of a fork include pushing data to an intermediary, such as a database or filesystem, but both have side-effects: additional dependencies (many of which have their own dependencies) and/or the need for post-run cleanup.

To avoid this, I often use IO.pipe:

reader,writer = IO.pipe

child_pid = fork do
  reader.close
  writer.write( "Hello, I'm #{Process.pid}" )
  writer.close
end
writer.close

message_from_child = reader.read
reader.close

puts Process.pid          # => 12338
puts child_pid            # => 12345
puts message_from_child   # => "Hello, I'm 12345"

But that has several drawbacks:

  • read only works if all write ends of the pipe are closed; keeping track of which is open and which is closed is a pain, especially if you have to fork several layers deep.
  • only a single message can be passed; multiple messages adds complexity, and complicated test cases aren't a good idea
  • only strings can be passed; sure Objects can be serialized, but...

A Simpler Way

Adding this kind of logic directly into your tests is a bad idea; it makes them unnecessarily complicated, hard to read, and easy to get wrong. ObjectChannel abstracts all that away so you can just test. Here's the same simple example, but this time without all the pipe-closing:

require 'object-channel'

p2c = ObjectChannel.fork do |c2p|
  c2p.transmit( "Hello, I'm #{Process.pid}" )
end

puts Process.pid          # => 12338
puts p2c.pid              # => 12345
puts p2c.receive!         # => "Hello, I'm 12345"

Features

ObjectChannel provides the following features:

  • Full-fledged objects, not just strings
  • Bi-directional channel
  • Blocking and non-blocking access
  • block-invoke supported and fully optional
  • No additional dependencies
  • No cleanup necessary

Check out the specs for examples.

License & Contributing

Project is (c) 2012 Simply Measured and released under an MIT-style license

  • This project uses Vincent Driessen's Git-Flow branching model.
  • Check out the latest develop to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.