skein 0.3.7 → 0.8.1
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.
- checksums.yaml +5 -5
- data/Gemfile +4 -1
- data/Gemfile.lock +49 -36
- data/LICENSE.md +1 -1
- data/README.md +9 -4
- data/RELEASES.md +2 -0
- data/VERSION +1 -1
- data/bin/skein +1 -1
- data/examples/echo +66 -0
- data/examples/echo-server +77 -0
- data/lib/skein/adapter.rb +3 -0
- data/lib/skein/client/publisher.rb +10 -2
- data/lib/skein/client/rpc.rb +78 -19
- data/lib/skein/client/subscriber.rb +27 -4
- data/lib/skein/client/worker.rb +221 -63
- data/lib/skein/client.rb +20 -11
- data/lib/skein/config.rb +3 -1
- data/lib/skein/connected.rb +88 -17
- data/lib/skein/context.rb +5 -2
- data/lib/skein/handler/async.rb +6 -2
- data/lib/skein/handler.rb +131 -20
- data/lib/skein/rabbitmq.rb +1 -0
- data/lib/skein/timeout_queue.rb +43 -0
- data/lib/skein.rb +18 -2
- data/skein.gemspec +21 -24
- data/test/helper.rb +29 -0
- data/test/unit/test_skein_client.rb +4 -1
- data/test/unit/test_skein_client_publisher.rb +1 -1
- data/test/unit/test_skein_client_rpc.rb +37 -0
- data/test/unit/test_skein_client_subscriber.rb +29 -12
- data/test/unit/test_skein_client_worker.rb +22 -9
- data/test/unit/test_skein_connected.rb +21 -0
- data/test/unit/test_skein_rpc_timeout.rb +19 -0
- data/test/unit/test_skein_worker.rb +4 -0
- metadata +41 -16
- data/lib/skein/rpc/base.rb +0 -23
- data/lib/skein/rpc/error.rb +0 -34
- data/lib/skein/rpc/notification.rb +0 -2
- data/lib/skein/rpc/request.rb +0 -62
- data/lib/skein/rpc/response.rb +0 -38
- data/lib/skein/rpc.rb +0 -24
- data/test/unit/test_skein_rpc_error.rb +0 -10
- data/test/unit/test_skein_rpc_request.rb +0 -93
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
class ExampleWorker < Skein::Client::Worker
|
4
|
+
def echo(*args)
|
5
|
+
args
|
6
|
+
end
|
7
|
+
|
8
|
+
def pops_exception
|
9
|
+
invalid_code!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestSkeinPublisher < Test::Unit::TestCase
|
14
|
+
def setup
|
15
|
+
@test_queue = 'rpc_test_q'
|
16
|
+
|
17
|
+
@rpc = Skein::Client::RPC.new('', routing_key: @test_queue)
|
18
|
+
@worker = ExampleWorker.new(@test_queue)
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
@rpc and @rpc.close
|
23
|
+
@worker and @worker.close
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_can_echo
|
27
|
+
result = @rpc.echo('example')
|
28
|
+
|
29
|
+
assert_equal %w[ example ], result
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_can_handle_exceptions
|
33
|
+
assert_raise_kind_of(NoMethodError) do
|
34
|
+
@rpc.pops_exception
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,6 +1,29 @@
|
|
1
1
|
require_relative '../helper'
|
2
2
|
|
3
3
|
class TestSkeinClientSubscriber < Test::Unit::TestCase
|
4
|
+
def test_immediate_close
|
5
|
+
client = Skein::Client.new
|
6
|
+
|
7
|
+
received = nil
|
8
|
+
|
9
|
+
subscriber = client.subscriber('test', '*.*')
|
10
|
+
subscribing = false
|
11
|
+
|
12
|
+
thread = in_thread do
|
13
|
+
subscribing = true
|
14
|
+
|
15
|
+
subscriber.listen do |payload|
|
16
|
+
received = payload
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
wait_for { subscribing }
|
21
|
+
|
22
|
+
ensure
|
23
|
+
subscriber and subscriber.close(delete_queue: true)
|
24
|
+
client and client.close
|
25
|
+
end
|
26
|
+
|
4
27
|
def test_cycle
|
5
28
|
client = Skein::Client.new
|
6
29
|
|
@@ -11,31 +34,25 @@ class TestSkeinClientSubscriber < Test::Unit::TestCase
|
|
11
34
|
subscriber = client.subscriber('test', '*.*')
|
12
35
|
subscribing = false
|
13
36
|
|
14
|
-
thread =
|
15
|
-
Thread.abort_on_exception = true
|
16
|
-
|
37
|
+
thread = in_thread do
|
17
38
|
subscribing = true
|
18
39
|
|
19
40
|
subscriber.listen do |payload|
|
20
41
|
received = payload
|
21
|
-
|
22
|
-
Thread.exit
|
23
42
|
end
|
24
43
|
end
|
25
44
|
|
26
|
-
|
27
|
-
# Spin-lock to wait for the subscriber to come online
|
28
|
-
end
|
45
|
+
wait_for { subscribing }
|
29
46
|
|
30
47
|
publisher.publish!({ data: true }, 'test.notification')
|
31
48
|
|
32
|
-
|
49
|
+
wait_for { received }
|
33
50
|
|
34
|
-
assert_equal({
|
51
|
+
assert_equal({ 'data' => true }, received)
|
35
52
|
|
36
53
|
ensure
|
37
|
-
publisher and publisher.close
|
38
|
-
subscriber and subscriber.close
|
54
|
+
publisher and publisher.close(delete_queue: true)
|
55
|
+
subscriber and subscriber.close(delete_queue: true)
|
39
56
|
client and client.close
|
40
57
|
end
|
41
58
|
end
|
@@ -11,8 +11,8 @@ class TestSkeinClientWorker < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_example
|
14
|
-
worker =
|
15
|
-
handler =
|
14
|
+
worker = ErrorGenerator.new('test_rpc')
|
15
|
+
handler = worker.send(:handler)
|
16
16
|
|
17
17
|
message = {
|
18
18
|
method: 'ident',
|
@@ -20,12 +20,15 @@ class TestSkeinClientWorker < Test::Unit::TestCase
|
|
20
20
|
id: '43d8352c-4907-4c32-9c81-fc34e91a3884'
|
21
21
|
}
|
22
22
|
|
23
|
-
|
23
|
+
metrics = worker.send(:metrics_tracker)
|
24
|
+
state = worker.send(:state_tracker)
|
25
|
+
|
26
|
+
handler.handle(JSON.dump(message), metrics, state) do |response_json, error|
|
24
27
|
response = JSON.load(response_json)
|
25
28
|
|
26
29
|
expected = {
|
30
|
+
'jsonrpc' => '2.0',
|
27
31
|
'result' => worker.ident,
|
28
|
-
'error' => nil,
|
29
32
|
'id' => message[:id]
|
30
33
|
}
|
31
34
|
|
@@ -33,7 +36,7 @@ class TestSkeinClientWorker < Test::Unit::TestCase
|
|
33
36
|
end
|
34
37
|
|
35
38
|
ensure
|
36
|
-
worker and worker.close
|
39
|
+
worker and worker.close(delete_queue: true)
|
37
40
|
end
|
38
41
|
|
39
42
|
def test_throws_exception
|
@@ -45,17 +48,27 @@ class TestSkeinClientWorker < Test::Unit::TestCase
|
|
45
48
|
id: '29fe8a40-fccf-43c6-ba48-818598c66e6f'
|
46
49
|
}
|
47
50
|
|
48
|
-
|
51
|
+
metrics = worker.send(:metrics_tracker)
|
52
|
+
state = worker.send(:state_tracker)
|
53
|
+
|
54
|
+
handler.handle(JSON.dump(message), metrics, state) do |response_json, error|
|
49
55
|
expected = {
|
50
|
-
'
|
51
|
-
'error' =>
|
56
|
+
'jsonrpc' => '2.0',
|
57
|
+
'error' => {
|
58
|
+
'code' => -32063,
|
59
|
+
'message' => '[TestSkeinClientWorker::ErrorGenerator::CustomError] Example error!'
|
60
|
+
},
|
52
61
|
'id' => message[:id]
|
53
62
|
}
|
54
63
|
|
55
64
|
assert_equal(expected.to_json, response_json)
|
65
|
+
|
66
|
+
assert_equal(1, metrics[:failed])
|
67
|
+
assert_equal(1, metrics[:errors][:exception])
|
68
|
+
assert(metrics[:time] >= 0, 'Time (%.3f) should be positive' % metrics[:time])
|
56
69
|
end
|
57
70
|
|
58
71
|
ensure
|
59
|
-
worker and worker.close
|
72
|
+
worker and worker.close(delete_queue: true)
|
60
73
|
end
|
61
74
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
class TestSkeinConnected < Test::Unit::TestCase
|
4
|
+
def test_construct_with_defaults
|
5
|
+
connected = Skein::Connected.new
|
6
|
+
|
7
|
+
assert connected
|
8
|
+
|
9
|
+
assert connected.context
|
10
|
+
assert connected.ident
|
11
|
+
assert connected.connection
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_construct_with_ident
|
15
|
+
ident = ('test-%s' % SecureRandom.uuid).freeze
|
16
|
+
connected = Skein::Connected.new(ident: ident)
|
17
|
+
|
18
|
+
assert connected
|
19
|
+
assert_equal ident, connected.ident
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
class TestSkeinRpcTimeout< Test::Unit::TestCase
|
4
|
+
def test_low_timeout
|
5
|
+
assert_raise Skein::TimeoutException do
|
6
|
+
client = Skein::Client.new
|
7
|
+
|
8
|
+
result = client.rpc('', routing_key: "test", timeout: 0.1).test
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_short_timeout
|
13
|
+
assert_raise Skein::TimeoutException do
|
14
|
+
client = Skein::Client.new
|
15
|
+
|
16
|
+
result = client.rpc('', routing_key: "test", timeout: 2).test
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -19,6 +19,8 @@ class TestSkeinWorker < Test::Unit::TestCase
|
|
19
19
|
assert_equal false, worker.async?
|
20
20
|
|
21
21
|
ensure
|
22
|
+
worker and worker.close(delete_queue: true)
|
23
|
+
|
22
24
|
client and client.close
|
23
25
|
end
|
24
26
|
|
@@ -33,6 +35,8 @@ class TestSkeinWorker < Test::Unit::TestCase
|
|
33
35
|
assert_equal true, worker.initialized
|
34
36
|
|
35
37
|
ensure
|
38
|
+
worker and worker.close(delete_queue: true)
|
39
|
+
|
36
40
|
client and client.close
|
37
41
|
end
|
38
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skein
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Tadman
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: birling
|
@@ -16,9 +16,37 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bunny
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: march_hare
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
22
50
|
version_requirements: !ruby/object:Gem::Requirement
|
23
51
|
requirements:
|
24
52
|
- - ">="
|
@@ -86,6 +114,8 @@ files:
|
|
86
114
|
- bin/skein
|
87
115
|
- config/.gitignore
|
88
116
|
- config/skein.yml.example
|
117
|
+
- examples/echo
|
118
|
+
- examples/echo-server
|
89
119
|
- lib/skein.rb
|
90
120
|
- lib/skein/adapter.rb
|
91
121
|
- lib/skein/client.rb
|
@@ -101,27 +131,23 @@ files:
|
|
101
131
|
- lib/skein/handler/threaded.rb
|
102
132
|
- lib/skein/rabbitmq.rb
|
103
133
|
- lib/skein/reporter.rb
|
104
|
-
- lib/skein/rpc.rb
|
105
|
-
- lib/skein/rpc/base.rb
|
106
|
-
- lib/skein/rpc/error.rb
|
107
|
-
- lib/skein/rpc/notification.rb
|
108
|
-
- lib/skein/rpc/request.rb
|
109
|
-
- lib/skein/rpc/response.rb
|
110
134
|
- lib/skein/support.rb
|
135
|
+
- lib/skein/timeout_queue.rb
|
111
136
|
- skein.gemspec
|
112
137
|
- test/data/sample_config.yml
|
113
138
|
- test/helper.rb
|
114
139
|
- test/script/em_example
|
115
140
|
- test/unit/test_skein_client.rb
|
116
141
|
- test/unit/test_skein_client_publisher.rb
|
142
|
+
- test/unit/test_skein_client_rpc.rb
|
117
143
|
- test/unit/test_skein_client_subscriber.rb
|
118
144
|
- test/unit/test_skein_client_worker.rb
|
119
145
|
- test/unit/test_skein_config.rb
|
146
|
+
- test/unit/test_skein_connected.rb
|
120
147
|
- test/unit/test_skein_context.rb
|
121
148
|
- test/unit/test_skein_rabbitmq.rb
|
122
149
|
- test/unit/test_skein_reporter.rb
|
123
|
-
- test/unit/
|
124
|
-
- test/unit/test_skein_rpc_request.rb
|
150
|
+
- test/unit/test_skein_rpc_timeout.rb
|
125
151
|
- test/unit/test_skein_support.rb
|
126
152
|
- test/unit/test_skein_worker.rb
|
127
153
|
- tmp/.gitignore
|
@@ -129,7 +155,7 @@ homepage: http://github.com/postageapp/skein
|
|
129
155
|
licenses:
|
130
156
|
- MIT
|
131
157
|
metadata: {}
|
132
|
-
post_install_message:
|
158
|
+
post_install_message:
|
133
159
|
rdoc_options: []
|
134
160
|
require_paths:
|
135
161
|
- lib
|
@@ -144,9 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
170
|
- !ruby/object:Gem::Version
|
145
171
|
version: '0'
|
146
172
|
requirements: []
|
147
|
-
|
148
|
-
|
149
|
-
signing_key:
|
173
|
+
rubygems_version: 3.2.15
|
174
|
+
signing_key:
|
150
175
|
specification_version: 4
|
151
176
|
summary: RabbitMQ RPC/PubSub Library
|
152
177
|
test_files: []
|
data/lib/skein/rpc/base.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
class Skein::RPC::Base
|
4
|
-
# == Exceptions ===========================================================
|
5
|
-
|
6
|
-
# == Properties ===========================================================
|
7
|
-
|
8
|
-
attr_accessor :id
|
9
|
-
|
10
|
-
# == Instance Methods =====================================================
|
11
|
-
|
12
|
-
def to_h
|
13
|
-
{
|
14
|
-
id: self.id
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_json
|
19
|
-
JSON.dump(
|
20
|
-
self.to_h
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
data/lib/skein/rpc/error.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
class Skein::RPC::Error < Skein::RPC::Base
|
2
|
-
# == Properties ===========================================================
|
3
|
-
|
4
|
-
attr_accessor :error
|
5
|
-
|
6
|
-
# == Instance Methods =====================================================
|
7
|
-
|
8
|
-
def initialize(content = nil)
|
9
|
-
case (content)
|
10
|
-
when String
|
11
|
-
self.error = content
|
12
|
-
when Hash
|
13
|
-
self.assign_from_hash!(content)
|
14
|
-
when nil
|
15
|
-
# Defaults
|
16
|
-
else
|
17
|
-
raise Skein::RPC::Exception, 'Invalid type: %s' % content.class
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.to_h
|
22
|
-
{
|
23
|
-
result: nil,
|
24
|
-
error: self.error,
|
25
|
-
id: self.id
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
protected
|
30
|
-
def assign_from_hash!(hash)
|
31
|
-
self.error = hash[:error]
|
32
|
-
self.id = hash[:id]
|
33
|
-
end
|
34
|
-
end
|
data/lib/skein/rpc/request.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
class Skein::RPC::Request < Skein::RPC::Base
|
2
|
-
# == Properties ===========================================================
|
3
|
-
|
4
|
-
attr_accessor :method
|
5
|
-
attr_accessor :params
|
6
|
-
|
7
|
-
# == Instance Methods =====================================================
|
8
|
-
|
9
|
-
def initialize(content = nil)
|
10
|
-
case (content)
|
11
|
-
when String
|
12
|
-
data = Skein::Support.symbolize_keys(JSON.load(content))
|
13
|
-
|
14
|
-
assign_from_hash!(data)
|
15
|
-
when Hash
|
16
|
-
assign_from_hash!(content)
|
17
|
-
when nil
|
18
|
-
self.id = SecureRandom.uuid
|
19
|
-
else
|
20
|
-
raise Skein::RPC::InvalidPayload, 'Invalid payload type: %s' % content.class
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_h
|
25
|
-
{
|
26
|
-
method: self.method,
|
27
|
-
params: self.params,
|
28
|
-
id: self.id
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def response(result: nil, error: nil)
|
33
|
-
if (result)
|
34
|
-
Skein::RPC::Response.new(
|
35
|
-
result: result,
|
36
|
-
id: self.id
|
37
|
-
)
|
38
|
-
elsif (error)
|
39
|
-
Skein::RPC::Error.new(
|
40
|
-
error: error,
|
41
|
-
id: self.id
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
def assign_from_hash!(hash)
|
48
|
-
self.method = hash[:method]
|
49
|
-
self.params = Skein::Support.arrayify(hash[:params])
|
50
|
-
self.id = hash[:id]
|
51
|
-
|
52
|
-
case (self.method)
|
53
|
-
when String
|
54
|
-
unless (self.method.match(/\A\w+\z/))
|
55
|
-
e = Skein::RPC::InvalidMethod.new('%s is not a valid RPC method name.' % self.method.inspect)
|
56
|
-
e.request = self
|
57
|
-
|
58
|
-
raise e
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|