zchannel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6b734e305c5b58ff2748a914726a87b17096ae28
4
+ data.tar.gz: fbc41b5a2ffd5323197761ffcb3298c829dd79db
5
+ SHA512:
6
+ metadata.gz: ac889c3e6f4704c42e97e58da6268c5a06e1b6defd670b2c43984e008def714ef9b59f1ef1041454f3005e62ffde5f4eca65359a7d135bda64c4447cc8d808c9
7
+ data.tar.gz: 9a5c36e1c85da9783fb05703eb7271b951aec14e99008db97bdfc6e0d5bfa0954ea7f4a2634abbb1db98d428460d06754a49881d58eff796e635033238857da9
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ * text eol=lf
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .gems
2
+ .bundle
3
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - rbx-19mode
6
+ # - ruby-head
7
+
8
+ env:
9
+ - REDIS=1 SERIALIZER=YAML
10
+ - REDIS=1 SERIALIZER=Marshal
11
+ - REDIS=1 SERIALIZER=JSON
12
+
13
+ services:
14
+ - redis-server
15
+
16
+ notifications:
17
+ email: true
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ -m markdown -M redcarpet
2
+ -
3
+ README.md
4
+ LICENSE.txt
5
+ ChangeLog.txt
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+ gem "test-unit"
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ __zchannel__
2
+
3
+ zchannel is a library that assists with InterProcess Communication, or
4
+ IPC for short. It provides a high level and easy to use API for sending
5
+ Ruby objects between processes that are running on the same machine.
6
+ A channel is implemented on top of an unbound UNIXSocket, and objects
7
+ are serialized with a serializer of your choosing although the examples
8
+ use the "Marshal" serializer, which is available without any extra
9
+ dependencies.
10
+
11
+ __Examples__
12
+
13
+ __1.__
14
+
15
+ ```ruby
16
+ chan = ZChannel.unix Marshal
17
+ Process.wait fork { chan.send "Hello, world!" }
18
+ chan.recv # => "Hello, world!"
19
+ ```
20
+
21
+ __Install__
22
+
23
+ * Rubygems
24
+
25
+ ```
26
+ $ gem install zchannel
27
+ ```
28
+
29
+ * Bundler
30
+
31
+ ```ruby
32
+ gem "zchannel", "~> 0.1"
33
+ ```
34
+
35
+ __License__
36
+
37
+ ```
38
+ This is free and unencumbered software released into the public domain.
39
+
40
+ Anyone is free to copy, modify, publish, use, compile, sell, or
41
+ distribute this software, either in source code form or as a compiled
42
+ binary, for any purpose, commercial or non-commercial, and by any
43
+ means.
44
+
45
+ In jurisdictions that recognize copyright laws, the author or authors
46
+ of this software dedicate any and all copyright interest in the
47
+ software to the public domain.
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
53
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
54
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
55
+ OTHER DEALINGS IN THE SOFTWARE.
56
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ Rake::TestTask.new(:test) do |t|
4
+ t.test_files = Dir['test/*_test.rb']
5
+ end
6
+ task default: :test
@@ -0,0 +1,139 @@
1
+ require 'socket'
2
+ class ZChannel::UNIXSocket
3
+ SEP = '_$_' if respond_to? :private_constant
4
+
5
+ #
6
+ # @param [#dump,#load] serializer
7
+ # An object who implements `.dump` and `.load` methods
8
+ #
9
+ # @return [ZChannel::UNIXSocket]
10
+ #
11
+ def initialize(serializer = Marshal)
12
+ @serializer = serializer
13
+ @last_msg = nil
14
+ @reader, @writer = ::UNIXSocket.pair :STREAM
15
+ end
16
+
17
+ #
18
+ # @return [Boolean]
19
+ # Returns true when a channel is closed
20
+ #
21
+ def closed?
22
+ @reader.closed? and @writer.closed?
23
+ end
24
+
25
+ #
26
+ # Close the channel
27
+ #
28
+ # @raise [IOError]
29
+ # When a channel is already closed
30
+ #
31
+ # @return [Boolean]
32
+ # Returns true on success
33
+ #
34
+ def close
35
+ if closed?
36
+ raise IOError, 'closed channel'
37
+ else
38
+ @reader.close
39
+ @writer.close
40
+ true
41
+ end
42
+ end
43
+
44
+ #
45
+ # @raise [IOError]
46
+ # (see #send!)
47
+ #
48
+ # @param [Object] object
49
+ # An object to add to a channel
50
+ #
51
+ def send(object)
52
+ send!(object, nil)
53
+ end
54
+
55
+ #
56
+ # @param
57
+ # (see ZChannel::UNIXSocket#send)
58
+ #
59
+ # @param [Fixnum] timeout
60
+ # Number of seconds to wait before raising an exception
61
+ #
62
+ # @raise [IOError]
63
+ # When channel is closed
64
+ #
65
+ # @raise [ZChannel::TimeoutError]
66
+ # When a write doesn't finish within the timeout
67
+ #
68
+ def send!(object, timeout = 0.1)
69
+ if @writer.closed?
70
+ raise IOError, 'closed channel'
71
+ end
72
+ _, writable, _ = IO.select nil, [@writer], nil, timeout
73
+ if writable
74
+ msg = @serializer.dump(object)
75
+ writable[0].syswrite "#{msg}#{SEP}"
76
+ else
77
+ raise ZChannel::TimeoutError, "timeout, waited #{timeout} seconds"
78
+ end
79
+ end
80
+
81
+ #
82
+ # Perform a blocking read
83
+ #
84
+ # @raise
85
+ # (see ZChannel::UNIXSocket#recv)
86
+ #
87
+ # @return [Object]
88
+ #
89
+ def recv
90
+ recv!(nil)
91
+ end
92
+
93
+ #
94
+ # Perform a read with a timeout
95
+ #
96
+ # @param [Fixnum] timeout
97
+ # Number of seconds to wait before raising an exception
98
+ #
99
+ # @raise [IOError]
100
+ # When channel is closed
101
+ #
102
+ # @raise [ZChannel::TimeoutError]
103
+ # When a read doesn't finish within the timeout
104
+ #
105
+ # @return [Object]
106
+ #
107
+ def recv!(timeout = 0.1)
108
+ if @reader.closed?
109
+ raise IOError, 'closed channel'
110
+ end
111
+ readable, _ = IO.select [@reader], nil, nil, timeout
112
+ if readable
113
+ msg = readable[0].readline(SEP).chomp SEP
114
+ @last_msg = @serializer.load msg
115
+ else
116
+ raise ZChannel::TimeoutError, "timeout, waited #{timeout} seconds"
117
+ end
118
+ end
119
+
120
+ #
121
+ # @return [Object]
122
+ #
123
+ def last_msg
124
+ @last_msg = recv while readable?
125
+ @last_msg
126
+ end
127
+
128
+ #
129
+ # @return [Boolean]
130
+ #
131
+ def readable?
132
+ if closed?
133
+ false
134
+ else
135
+ readable, _ = IO.select [@reader], nil, nil, 0
136
+ !! readable
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,3 @@
1
+ module ZChannel
2
+ VERSION = "0.1.0"
3
+ end
data/lib/zchannel.rb ADDED
@@ -0,0 +1,15 @@
1
+ module ZChannel
2
+ TimeoutError = Class.new(StandardError)
3
+ require_relative "zchannel/unix_socket"
4
+
5
+ #
6
+ # @param
7
+ # (see UNIXSocket#initialize).
8
+ #
9
+ # @return
10
+ # (see UNIXSocket#initialize)
11
+ #
12
+ def self.unix(serializer = Marshal)
13
+ UNIXSocket.new(serializer)
14
+ end
15
+ end
data/test/setup.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ require 'test/unit'
3
+ Bundler.require :default, :test
@@ -0,0 +1,94 @@
1
+ require_relative 'setup'
2
+ class ZChannelTest < Test::Unit::TestCase
3
+ def setup
4
+ @chan = ZChannel.unix Object.const_get(ENV["SERIALIZER"] || "Marshal")
5
+ end
6
+
7
+ def teardown
8
+ @chan.close unless @chan.closed?
9
+ end
10
+
11
+ def test_blocking_recv
12
+ assert_raises Timeout::Error do
13
+ Timeout.timeout(1) { @chan.recv }
14
+ end
15
+ end
16
+
17
+ def test_timeout_on_recv
18
+ assert_raises ZChannel::TimeoutError do
19
+ @chan.recv! 1
20
+ end
21
+ end
22
+
23
+ def test_last_msg_after_read
24
+ @chan.send [42]
25
+ @chan.recv
26
+ assert_equal [42], @chan.last_msg
27
+ end
28
+
29
+ def test_fork
30
+ pid = fork do
31
+ @chan.send [42]
32
+ end
33
+ Process.wait pid
34
+ assert_equal [42], @chan.recv
35
+ end
36
+
37
+ def test_last_msg
38
+ @chan.send %w(a)
39
+ @chan.send %w(b)
40
+ assert_equal %w(b), @chan.last_msg
41
+ end
42
+
43
+ def test_last_msg_cache
44
+ @chan.send %w(a)
45
+ 2.times { assert_equal %w(a), @chan.last_msg }
46
+ @chan.close
47
+ assert_equal %w(a), @chan.last_msg
48
+ end
49
+
50
+ def test_bust_last_msg_cache
51
+ @chan.send %w(a)
52
+ assert_equal %w(a), @chan.last_msg
53
+ @chan.send %w(b)
54
+ 2.times { assert_equal %w(b), @chan.last_msg }
55
+ end
56
+
57
+ def test_send_on_closed_channel
58
+ @chan.close
59
+ assert_raises IOError do
60
+ @chan.send %w(a)
61
+ end
62
+ end
63
+
64
+ def test_recv_on_closed_channel
65
+ @chan.close
66
+ assert_raises IOError do
67
+ @chan.recv
68
+ end
69
+ end
70
+
71
+ def test_queued_messages
72
+ @chan.send %w(a)
73
+ @chan.send %w(b)
74
+ assert_equal %w(a), @chan.recv
75
+ assert_equal %w(b), @chan.recv
76
+ end
77
+
78
+ def test_readable_on_populated_channel
79
+ @chan.send %w(a)
80
+ @chan.send %w(b)
81
+ assert @chan.readable?
82
+ end
83
+
84
+ def test_readable_on_empty_channel
85
+ @chan.send %w(42)
86
+ @chan.recv # discard
87
+ refute @chan.readable?
88
+ end
89
+
90
+ def test_readable_on_closed_channel
91
+ @chan.close
92
+ refute @chan.readable?
93
+ end
94
+ end
data/zchannel.gemspec ADDED
@@ -0,0 +1,13 @@
1
+ Kernel.require './lib/zchannel/version'
2
+ Gem::Specification.new do |gem|
3
+ gem.name = "zchannel"
4
+ gem.version = ZChannel::VERSION
5
+ gem.authors = ["jazzonmymind"]
6
+ gem.email = ["robert@jazzonmymind.xyz"]
7
+ gem.description = "Provides a high level and easy to use API for sending objects between Ruby processes"
8
+ gem.summary = gem.description
9
+ gem.homepage = "https://github.com/jazzonmymind/zchannel.rb"
10
+ gem.licenses = ["Nonstandard"]
11
+ gem.files = `git ls-files`.split($/)
12
+ gem.require_paths = ["lib"]
13
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zchannel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - jazzonmymind
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Provides a high level and easy to use API for sending objects between
14
+ Ruby processes
15
+ email:
16
+ - robert@jazzonmymind.xyz
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitattributes"
22
+ - ".gitignore"
23
+ - ".travis.yml"
24
+ - ".yardopts"
25
+ - Gemfile
26
+ - README.md
27
+ - Rakefile
28
+ - lib/zchannel.rb
29
+ - lib/zchannel/unix_socket.rb
30
+ - lib/zchannel/version.rb
31
+ - test/setup.rb
32
+ - test/zchannel_test.rb
33
+ - zchannel.gemspec
34
+ homepage: https://github.com/jazzonmymind/zchannel.rb
35
+ licenses:
36
+ - Nonstandard
37
+ metadata: {}
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 2.5.1
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Provides a high level and easy to use API for sending objects between Ruby
58
+ processes
59
+ test_files: []
60
+ has_rdoc: