ichannel 6.1.1.1 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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