ichannel 6.1.1.1 → 7.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.
@@ -1,3 +1,17 @@
1
+ == v7.0.0
2
+ - IChannel::UNIXSocket#get! raises Timeout::Error
3
+ When a read does not complete in time a Timeout::Error will be
4
+ raised (IChannel::Redis#get! already has this behavior).
5
+
6
+ - IChannel::Redis#get is a blocking read.
7
+ IChannel::Redis#get now blocks on read(by using the BRPOP command)
8
+
9
+ - Remove serialization support for IChannel::UNIXSocket.
10
+ The support is severely limited and the source of too many
11
+ edge cases to continue support. Even if serialization was
12
+ limited to a single machine it only works under specific
13
+ circumstances.
14
+
1
15
  == v6.1.1.1
2
16
  - Documentation improvements
3
17
 
@@ -24,15 +38,15 @@
24
38
  - IChannel::UNIXSocket can now be serialized by Marshal.
25
39
  IChannel::UNIXSocket can be serialized by Marshal but there's a gotcha: it
26
40
  only really works on the same machine between one or more Ruby processes.
27
- The UNIXSocket#marshal_dump method is implemented to dump the FDs in an array,
28
- so this feature won't fair well across different machines or time but I've
41
+ The UNIXSocket#marshal_dump method is implemented to dump the FDs in an array,
42
+ so this feature won't fair well across different machines or time but I've
29
43
  found this feature useful nonetheless.
30
44
 
31
45
  - add IChannel.unix(…)
32
46
  Returns an instance of IChannel::UNIXSocket.
33
47
 
34
48
  - add IChannel::UNIXSocket
35
- rename IChannel as IChannel::UNIXSocket in preparation for multiple
49
+ rename IChannel as IChannel::UNIXSocket in preparation for multiple
36
50
  backends(UNIXSocket, Redis, …).
37
51
 
38
52
  == v5.2.0
@@ -50,29 +64,29 @@
50
64
 
51
65
  == v5.1.0
52
66
  - Remove restriction on size of message.
53
- IChannel#get can read a message of any size(before hand it was limited to
67
+ IChannel#get can read a message of any size(before hand it was limited to
54
68
  1MB in size). Thanks to @quezacoatl.
55
69
 
56
70
  - IChannel#readable? no longer blocks.
57
71
  IChannel#readable? no longer blocks for 0.1 seconds on IO.select call.
58
- Thanks to quezacoatl(https://github.com/quezacoatl) for the initial
59
- implementation.
72
+ Thanks to quezacoatl(https://github.com/quezacoatl) for the initial
73
+ implementation.
60
74
 
61
75
  == v5.0.0
62
76
  - Remove IChannel#empty?
63
- I think the #readable? method is all you need, and is a much more
77
+ I think the #readable? method is all you need, and is a much more
64
78
  accurate description of what the method is asking. We cannot determine
65
- if the channel is really empty, but we can ask if it is readable at the
79
+ if the channel is really empty, but we can ask if it is readable at the
66
80
  time you ask.
67
81
 
68
82
  == v4.1.0
69
83
  - Add IChannel#readable?
70
- A method that can tell you whether or not a read would block.
84
+ A method that can tell you whether or not a read would block.
71
85
  When it returns true, a read shouldn't block, on the other hand
72
86
  if it were false it'd likely block by the time you call #get.
73
87
  == v4.0.0
74
88
  - Modify IChannel#empty?
75
- It now returns true in case the underlying UNIXSocket being used as a
89
+ It now returns true in case the underlying UNIXSocket being used as a
76
90
  reader is closed.
77
91
 
78
92
  == v3.1.0
@@ -80,7 +94,7 @@
80
94
  IChannel#empty? returns true when the channel is empty(nothing to read).
81
95
 
82
96
  - Micro speed improvement on #write!, & #recv! operations.
83
- By passing nil instead of creating two empty arrays for every read/write
97
+ By passing nil instead of creating two empty arrays for every read/write
84
98
  operation we should see a very small improvement in their performance.
85
99
 
86
- - Add ChangeLog.txt
100
+ - Add ChangeLog.txt
data/README.md CHANGED
@@ -1,44 +1,42 @@
1
- __OVERVIEW__
1
+ __OVERVIEW__
2
2
 
3
- | Project | ichannel
3
+ | Project | ichannel
4
4
  |:----------------|:--------------------------------------------------
5
5
  | Homepage | https://github.com/robgleeson/ichannel
6
- | Documentation | http://rubydoc.info/github/robgleeson/ichannel/frames
6
+ | Documentation | http://rubydoc.info/github/robgleeson/ichannel/frames
7
+ | Metrics | [![Code Climate](https://codeclimate.com/github/robgleeson/ichannel.png)](https://codeclimate.com/github/robgleeson/ichannel)
7
8
  | CI | [![Build Status](https://travis-ci.org/robgleeson/ichannel.png)](https://travis-ci.org/robgleeson/ichannel)
8
- | Author | Robert Gleeson
9
+ | Author | Robert Gleeson
9
10
 
10
11
 
11
12
  __DESCRIPTION__
12
13
 
13
14
  ichannel is a channel for interprocess communication between ruby processes on
14
- the same machine or network. The basic premise is that you can "put" a ruby
15
- object onto the channel and on the other end(maybe in a different process,
15
+ the same machine or network. The basic premise is that you can "put" a ruby
16
+ object onto the channel and on the other end(maybe in a different process,
16
17
  or maybe on a different machine) you can "get" the object from the channel.
17
-
18
- The two main modes of transport are a [UNIXSocket](http://www.ruby-doc.org/stdlib-2.0/libdoc/socket/rdoc/UNIXSocket.html)
19
- and [redis](https://redis.io). A (unbound) unix socket is local to one machine but it can
20
- act as a queue, it has no external dependencies, & it shares the same interface
21
- as its redis counterpart. A redis channel can do all of the above but also expand
22
- its reach beyond one machine by sending and receiving messages from other
23
- channels running on different machines.
24
-
25
- A channel depends on a serializer when reading and writing from the underlying
26
- transport(i.e: redis or a unix socket) but the choice of serializer is up
27
- to you. The default is set to be [Marshal](http://ruby-doc.org/core-2.0/Marshal.html)
28
- but a serializer can be any object that implements dump and load. A few off the top of
29
- my head would be JSON, YAML, or MessagePack(with a wrapper, see examples).
18
+ A [unix socket](http://www.ruby-doc.org/stdlib-2.0/libdoc/socket/rdoc/UNIXSocket.html)
19
+ (local to a single machine) or [redis](https://redis.io) can be used for
20
+ transport.
21
+
22
+ A channel depends on a serializer when reading and writing from the underlying
23
+ socket(e.g: redis or a unix socket) but you can use any serializer that
24
+ implements the dump and load methods. The default is set to be
25
+ [Marshal](http://ruby-doc.org/core-2.0/Marshal.html) since it is a core
26
+ ruby module but you could also use JSON, YAML, MessagePack, or <insert your
27
+ serializer here>.
30
28
 
31
29
  __EXAMPLES__
32
30
 
33
31
  __1.__
34
32
 
35
- A demo of how to pass ruby objects through a channel and also between processes.
36
- [Marshal](http://rubydoc.info/stdlib/core/Marshal) is the serializer of choice,
37
- and a streamed UNIXSocket is mode of transport:
33
+ A demo of how to pass ruby objects through a channel and also between processes.
34
+ [Marshal](http://rubydoc.info/stdlib/core/Marshal) is the serializer of choice,
35
+ and a streamed UNIXSocket is used for transport:
38
36
 
39
37
  ```ruby
40
38
  channel = IChannel.unix Marshal
41
- pid = fork do
39
+ pid = fork do
42
40
  channel.put Process.pid
43
41
  channel.put 'Hello!'
44
42
  end
@@ -46,15 +44,28 @@ Process.wait pid
46
44
  channel.get # => Fixnum
47
45
  channel.get # => 'Hello!'
48
46
  ```
49
-
50
47
  __2.__
51
48
 
49
+ A demo of a channel sending messages between machines by using
50
+ [redis](https://redis.io) for transport:
51
+
52
+ ```ruby
53
+ channel = IChannel.redis Marshal, host: "10.0.0.1", key: "readme-example"
54
+ channel.put %w(a)
55
+
56
+ # In another process, on another machine, far away…
57
+ channel = IChannel.redis Marshal, host: "10.0.0.1", key: "readme-example"
58
+ channel.get # => ["a"]
59
+ ```
60
+
61
+ __3.__
62
+
52
63
  Knowing when a channel is readable can be useful so that you can avoid a
53
- blocking read on the underlying UNIXSocket. This (bad) example demonstrates
64
+ blocking read on the underlying UNIXSocket. This (bad) example demonstrates
54
65
  how to do that:
55
66
 
56
67
  ```ruby
57
- channel = IChannel.unix Marshal
68
+ channel = IChannel.unix Marshal
58
69
  pid = fork do
59
70
  sleep 3
60
71
  channel.put 42
@@ -66,20 +77,6 @@ channel.get # => 42
66
77
  Process.wait pid
67
78
  ```
68
79
 
69
- __3.__
70
-
71
- A demo of a channel sending messages between machines by using
72
- [redis](https://redis.io) as a backend:
73
-
74
- ```ruby
75
- channel = IChannel.redis Marshal, key: "readme-example"
76
- channel.put %w(a)
77
-
78
- # In another process, on another machine, far away…
79
- channel = IChannel.redis Marshal, key: "readme-example"
80
- channel.get # => ["a"]
81
- ```
82
-
83
80
  __4.__
84
81
 
85
82
  MessagePack doesn't implement `dump` or `load` but a wrapper can be easily
@@ -102,18 +99,16 @@ __PLATFORM SUPPORT__
102
99
 
103
100
  _supported_
104
101
 
105
- * CRuby (1.9+)
102
+ * CRuby (1.9+)
106
103
  * Rubinius (1.9+)
107
104
  * JRuby (1.9+ - some tests skipped)
108
- JRuby is supported and passes the test suite but it has a few skips.
109
- Three skips are because jruby does not implement Kernel.fork and one
110
- looks like a possible bug in JRuby's Marshal when trying to deserialize
111
- a channel that uses a unix socket. The other 24 tests pass on jruby, &
112
- those tests cover both unix sockets & redis.
105
+ JRuby is supported and passes the test suite but it has a few skips.
106
+ Three skips are because jruby does not implement Kernel.fork.
107
+ The other tests pass on jruby, & those tests cover both unix sockets & redis.
113
108
 
114
109
  _unsupported_
115
110
 
116
- * Any 1.8 implementation
111
+ * Any 1.8 implementation
117
112
  * MacRuby
118
113
 
119
114
  __INSTALL__
@@ -128,8 +123,8 @@ And to finish:
128
123
  $ gem install ichannel
129
124
 
130
125
  __SEE ALSO__
131
-
132
- - [ifuture](https://github.com/Havenwood/ifuture)
126
+
127
+ - [ifuture](https://github.com/Havenwood/ifuture)
133
128
  futures built on process forks and ichannel.
134
129
 
135
130
  __LICENSE__
@@ -5,8 +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 modern and easy-to-use interprocess communication
9
- primitive.}
8
+ gem.description = %q{interprocess communication channel}
10
9
  gem.summary = gem.description
11
10
  gem.homepage = "https://github.com/robgleeson/ichannel"
12
11
 
@@ -3,8 +3,8 @@ module IChannel
3
3
  require_relative "ichannel/unix_socket"
4
4
 
5
5
  #
6
- # @param
7
- # (see UNIXSocket#initialize)
6
+ # @param
7
+ # (see UNIXSocket#initialize).
8
8
  #
9
9
  # @return
10
10
  # (see UNIXSocket#initialize)
@@ -24,6 +24,6 @@ module IChannel
24
24
  unless defined?(IChannel::Redis)
25
25
  require_relative "ichannel/redis"
26
26
  end
27
- IChannel::Redis.new serializer, options
27
+ Redis.new serializer, options
28
28
  end
29
29
  end
@@ -100,27 +100,26 @@ class IChannel::Redis
100
100
 
101
101
  #
102
102
  # @param [Fixnum] timeout
103
- # The amount of time to wait for the read to complete.
103
+ # The number of seconds (as an Integer) to wait before a time out will occur.
104
104
  #
105
105
  # @raise [IOError]
106
106
  # When the channel is closed or empty.
107
107
  #
108
108
  # @raise [Timeout::Error]
109
- # When the read does not complete in time.
109
+ # When _timeout_ seconds pass and the read has not completed.
110
110
  #
111
111
  # @return [Object]
112
112
  # The object read from the channel.
113
113
  #
114
- def recv!(timeout = 0.1)
114
+ def recv!(timeout = 1)
115
115
  if closed?
116
116
  raise IOError, 'The channel cannot be read from (closed).'
117
- elsif empty?
118
- raise IOError, 'The channel cannot be read from (empty).'
117
+ end
118
+ _, payload = @redis.brpop @key, timeout
119
+ if payload
120
+ @last_msg = @serializer.load(payload)
119
121
  else
120
- Timeout.timeout(timeout) do
121
- dump = @redis.rpop @key
122
- @last_msg = @serializer.load dump
123
- end
122
+ raise Timeout::Error, "timeout on read after #{timeout} seconds"
124
123
  end
125
124
  end
126
125
  alias_method :get!, :recv!
@@ -128,7 +128,7 @@ module IChannel
128
128
  # @raise [IOError]
129
129
  # (see IChannel#recv)
130
130
  #
131
- # @raise [IOError]
131
+ # @raise [Timeout::Error]
132
132
  # When _timeout_ seconds elapse & the channel remains unreadable.
133
133
  #
134
134
  # @return [Object]
@@ -143,7 +143,7 @@ module IChannel
143
143
  msg = readable[0].readline(SEP).chomp SEP
144
144
  @last_msg = @serializer.load msg
145
145
  else
146
- raise IOError, 'The channel cannot be read from.'
146
+ raise Timeout::Error, 'Time out on read (waited for %s second(s))' % [timeout]
147
147
  end
148
148
  end
149
149
  alias_method :get!, :recv!
@@ -160,17 +160,5 @@ module IChannel
160
160
  !! readable
161
161
  end
162
162
  end
163
-
164
- # @api private
165
- def marshal_load(array)
166
- @serializer, reader, writer, @last_msg = array
167
- @reader = ::UNIXSocket.for_fd(reader)
168
- @writer = ::UNIXSocket.for_fd(writer)
169
- end
170
-
171
- # @api private
172
- def marshal_dump
173
- [@serializer, @reader.to_i, @writer.to_i, @last_msg]
174
- end
175
163
  end
176
164
  end
@@ -1,3 +1,3 @@
1
1
  module IChannel
2
- VERSION = "6.1.1.1"
2
+ VERSION = "7.0.0"
3
3
  end
@@ -12,6 +12,9 @@ class IChannelRedisTest < IChannelUNIXTest
12
12
  @channel.close
13
13
  end
14
14
 
15
- def test_serialization() end
16
- def test_serialization_in_fork() end
15
+ def test_timeout_on_get
16
+ assert_raises Timeout::Error do
17
+ @channel.get! 1
18
+ end
19
+ end
17
20
  end
@@ -26,31 +26,22 @@ class IChannelUNIXTest < Test::Unit::TestCase
26
26
  end
27
27
  end
28
28
 
29
- def test_last_msg_after_read
30
- @channel.put [42]
31
- @channel.get
32
- assert_equal [42], @channel.last_msg
29
+ def test_blocking_get
30
+ assert_raises Timeout::Error do
31
+ Timeout.timeout(1) { @channel.get }
32
+ end
33
33
  end
34
34
 
35
- def test_serialization_in_fork
36
- if RUBY_ENGINE == "jruby"
37
- skip "jruby does not implement Kernel.fork"
38
- end
39
- dump = Marshal.dump(@channel)
40
- pid = fork do
41
- Marshal.load(dump).put [42]
35
+ def test_timeout_on_get
36
+ assert_raises Timeout::Error do
37
+ @channel.get! 0.1
42
38
  end
43
- Process.wait pid
44
- assert_equal [42], @channel.get
45
39
  end
46
40
 
47
- def test_serialization
48
- if RUBY_ENGINE == "jruby"
49
- skip "fails on jruby"
50
- end
41
+ def test_last_msg_after_read
51
42
  @channel.put [42]
52
- dump = Marshal.dump @channel
53
- assert_equal [42], Marshal.load(dump).get
43
+ @channel.get
44
+ assert_equal [42], @channel.last_msg
54
45
  end
55
46
 
56
47
  def test_fork
@@ -63,7 +54,7 @@ class IChannelUNIXTest < Test::Unit::TestCase
63
54
  Process.wait pid
64
55
  assert_equal [42], @channel.get
65
56
  end
66
-
57
+
67
58
  def test_last_msg
68
59
  @channel.put %w(a)
69
60
  @channel.put %w(b)
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: 6.1.1.1
4
+ version: 7.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: 2013-05-06 00:00:00.000000000 Z
12
+ date: 2013-07-29 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: ! "A modern and easy-to-use interprocess communication \n primitive."
14
+ description: interprocess communication channel
15
15
  email:
16
16
  - rob@flowof.info
17
17
  executables: []
@@ -51,7 +51,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
51
  version: '0'
52
52
  segments:
53
53
  - 0
54
- hash: 1434889147865179878
54
+ hash: -3143838182628750731
55
55
  required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  none: false
57
57
  requirements:
@@ -60,13 +60,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
60
  version: '0'
61
61
  segments:
62
62
  - 0
63
- hash: 1434889147865179878
63
+ hash: -3143838182628750731
64
64
  requirements: []
65
65
  rubyforge_project:
66
66
  rubygems_version: 1.8.23
67
67
  signing_key:
68
68
  specification_version: 3
69
- summary: A modern and easy-to-use interprocess communication primitive.
69
+ summary: interprocess communication channel
70
70
  test_files:
71
71
  - test/ichannel_redis_test.rb
72
72
  - test/ichannel_unix_test.rb