ichannel 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +45 -14
- data/ichannel.gemspec +1 -1
- data/lib/ichannel.rb +19 -13
- data/lib/ichannel/version.rb +1 -1
- data/test/ichannel_class_test.rb +14 -0
- metadata +6 -6
data/README.md
CHANGED
@@ -11,12 +11,14 @@ __OVERVIEW__
|
|
11
11
|
|
12
12
|
__DESCRIPTION__
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
A modern, flexible & easy to use interprocess communication(IPC) primitive. The
|
15
|
+
basic premise is that you can "put" and "get" Ruby objects to/from a channel.
|
16
|
+
This works across any Ruby process & its subprocesses, though, which is why it
|
17
|
+
can be useful. You could describe putting and getting objects to/from the channel
|
18
|
+
as message passing but the message could potentially be any Ruby object,
|
19
|
+
although I think sending small messages(as a Hash) works very well for most
|
20
|
+
scenarios. You have the potential to serialize any object that `Marshal` can
|
21
|
+
dump+load, though.
|
20
22
|
|
21
23
|
__EXAMPLES__
|
22
24
|
|
@@ -26,14 +28,43 @@ The first example shows off how you'd pass Ruby objects through a channel.
|
|
26
28
|
The serializer of choice is `Marshal` but it could just as easily be `JSON` or
|
27
29
|
`YAML`.
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
```ruby
|
32
|
+
channel = IChannel.new Marshal
|
33
|
+
pid = fork do
|
34
|
+
channel.put Process.pid
|
35
|
+
channel.put 'Hello!'
|
36
|
+
end
|
37
|
+
Process.wait pid
|
38
|
+
channel.get # => Fixnum
|
39
|
+
channel.get # => 'Hello!'
|
40
|
+
```
|
41
|
+
|
42
|
+
__SERIALIZERS__
|
43
|
+
|
44
|
+
To send Ruby objects between processes they have to be serialized, but on the
|
45
|
+
bright side the number of serializers to choose from is vast. Marshal, JSON, &
|
46
|
+
YAML are supported out of the box to name a few but adding support for other
|
47
|
+
serializers is a trivial amount of work.
|
48
|
+
|
49
|
+
For example, here is a MessagePack serializer you could use:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
require 'ichannel'
|
53
|
+
require 'msgpack'
|
54
|
+
serializer = Class.new do
|
55
|
+
def self.dump(msg)
|
56
|
+
MessagePack.pack msg
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.load(msg)
|
60
|
+
MessagePack.unpack msg
|
61
|
+
end
|
62
|
+
end
|
63
|
+
channel = IChannel.new serializer
|
64
|
+
```
|
65
|
+
|
66
|
+
As you can see above as long as the serializer responds to `.dump` & `.load` it
|
67
|
+
can be passed as a serializer to IChannel.
|
37
68
|
|
38
69
|
__REAL WORLD EXAMPLES__
|
39
70
|
|
data/ichannel.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.version = IChannel::VERSION
|
6
6
|
gem.authors = ["Robert Gleeson"]
|
7
7
|
gem.email = ["rob@flowof.info"]
|
8
|
-
gem.description = %q{A
|
8
|
+
gem.description = %q{A modern and easy-to-use interprocess communication
|
9
9
|
primitive.}
|
10
10
|
gem.summary = gem.description
|
11
11
|
gem.homepage = "https://github.com/robgleeson/ichannel"
|
data/lib/ichannel.rb
CHANGED
@@ -9,34 +9,33 @@ class IChannel
|
|
9
9
|
@serializer = serializer
|
10
10
|
end
|
11
11
|
|
12
|
-
#
|
13
|
-
# Close the channel.
|
14
|
-
#
|
15
|
-
# @return [void]
|
16
|
-
#
|
17
|
-
def close
|
18
|
-
[@reader.close,@writer.close]
|
19
|
-
end
|
20
|
-
|
21
12
|
#
|
22
13
|
# @return [Boolean]
|
23
|
-
# Returns true
|
14
|
+
# Returns true when the channel is closed.
|
24
15
|
#
|
25
16
|
def closed?
|
26
17
|
@reader.closed? && @writer.closed?
|
27
18
|
end
|
28
19
|
|
20
|
+
#
|
21
|
+
# Close the channel.
|
29
22
|
#
|
30
23
|
# @return [Boolean]
|
31
|
-
# Returns true
|
24
|
+
# Returns true when the channel has been closed.
|
25
|
+
# Returns nil when the channel is already closed.
|
32
26
|
#
|
33
|
-
def
|
34
|
-
|
27
|
+
def close
|
28
|
+
if !@reader.closed? && !@writer.closed?
|
29
|
+
!! [@reader.close, @writer.close]
|
30
|
+
end
|
35
31
|
end
|
36
32
|
|
37
33
|
#
|
38
34
|
# Add an object to the channel.
|
39
35
|
#
|
36
|
+
# @raise [IOError]
|
37
|
+
# When the channel cannot be written to.
|
38
|
+
#
|
40
39
|
# @param [Object] object
|
41
40
|
# An object to add to the channel.
|
42
41
|
#
|
@@ -44,6 +43,8 @@ class IChannel
|
|
44
43
|
_, writable, _ = IO.select [], [@writer], [], 0.1
|
45
44
|
if writable
|
46
45
|
@writer.send @serializer.dump(object), 0
|
46
|
+
else
|
47
|
+
raise IOError, 'The channel cannot be written to.'
|
47
48
|
end
|
48
49
|
end
|
49
50
|
alias_method :put, :write
|
@@ -51,6 +52,9 @@ class IChannel
|
|
51
52
|
#
|
52
53
|
# Receive a object from the channel.
|
53
54
|
#
|
55
|
+
# @raise [IOError]
|
56
|
+
# When the channel cannot be read from.
|
57
|
+
#
|
54
58
|
# @return [Object]
|
55
59
|
# The object added to the channel.
|
56
60
|
#
|
@@ -59,6 +63,8 @@ class IChannel
|
|
59
63
|
if readable
|
60
64
|
msg, _ = @reader.recvmsg
|
61
65
|
@serializer.load msg
|
66
|
+
else
|
67
|
+
raise IOError, 'The channel cannot be read from.'
|
62
68
|
end
|
63
69
|
end
|
64
70
|
alias_method :get, :recv
|
data/lib/ichannel/version.rb
CHANGED
data/test/ichannel_class_test.rb
CHANGED
@@ -16,6 +16,20 @@ class IChannelTest < Test::Unit::TestCase
|
|
16
16
|
assert_equal %w(a b c), @channel.get
|
17
17
|
end
|
18
18
|
|
19
|
+
def test_put_on_closed_channel
|
20
|
+
@channel.close
|
21
|
+
assert_raises IOError do
|
22
|
+
@channel.put %w(a)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_get_on_closed_channel
|
27
|
+
@channel.close
|
28
|
+
assert_raises IOError do
|
29
|
+
@channel.put %w(b)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
19
33
|
def test_queued_messages
|
20
34
|
pid = fork do
|
21
35
|
@channel.put %w(a)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ichannel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,9 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: ! "A
|
14
|
+
description: ! "A modern and easy-to-use interprocess communication \n primitive."
|
15
15
|
email:
|
16
16
|
- rob@flowof.info
|
17
17
|
executables: []
|
@@ -43,7 +43,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
43
43
|
version: '0'
|
44
44
|
segments:
|
45
45
|
- 0
|
46
|
-
hash: -
|
46
|
+
hash: -795267943345486764
|
47
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
48
|
none: false
|
49
49
|
requirements:
|
@@ -52,13 +52,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
52
|
version: '0'
|
53
53
|
segments:
|
54
54
|
- 0
|
55
|
-
hash: -
|
55
|
+
hash: -795267943345486764
|
56
56
|
requirements: []
|
57
57
|
rubyforge_project:
|
58
58
|
rubygems_version: 1.8.23
|
59
59
|
signing_key:
|
60
60
|
specification_version: 3
|
61
|
-
summary: A
|
61
|
+
summary: A modern and easy-to-use interprocess communication primitive.
|
62
62
|
test_files:
|
63
63
|
- test/ichannel_class_test.rb
|
64
64
|
- test/setup.rb
|