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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +49 -36
  4. data/LICENSE.md +1 -1
  5. data/README.md +9 -4
  6. data/RELEASES.md +2 -0
  7. data/VERSION +1 -1
  8. data/bin/skein +1 -1
  9. data/examples/echo +66 -0
  10. data/examples/echo-server +77 -0
  11. data/lib/skein/adapter.rb +3 -0
  12. data/lib/skein/client/publisher.rb +10 -2
  13. data/lib/skein/client/rpc.rb +78 -19
  14. data/lib/skein/client/subscriber.rb +27 -4
  15. data/lib/skein/client/worker.rb +221 -63
  16. data/lib/skein/client.rb +20 -11
  17. data/lib/skein/config.rb +3 -1
  18. data/lib/skein/connected.rb +88 -17
  19. data/lib/skein/context.rb +5 -2
  20. data/lib/skein/handler/async.rb +6 -2
  21. data/lib/skein/handler.rb +131 -20
  22. data/lib/skein/rabbitmq.rb +1 -0
  23. data/lib/skein/timeout_queue.rb +43 -0
  24. data/lib/skein.rb +18 -2
  25. data/skein.gemspec +21 -24
  26. data/test/helper.rb +29 -0
  27. data/test/unit/test_skein_client.rb +4 -1
  28. data/test/unit/test_skein_client_publisher.rb +1 -1
  29. data/test/unit/test_skein_client_rpc.rb +37 -0
  30. data/test/unit/test_skein_client_subscriber.rb +29 -12
  31. data/test/unit/test_skein_client_worker.rb +22 -9
  32. data/test/unit/test_skein_connected.rb +21 -0
  33. data/test/unit/test_skein_rpc_timeout.rb +19 -0
  34. data/test/unit/test_skein_worker.rb +4 -0
  35. metadata +41 -16
  36. data/lib/skein/rpc/base.rb +0 -23
  37. data/lib/skein/rpc/error.rb +0 -34
  38. data/lib/skein/rpc/notification.rb +0 -2
  39. data/lib/skein/rpc/request.rb +0 -62
  40. data/lib/skein/rpc/response.rb +0 -38
  41. data/lib/skein/rpc.rb +0 -24
  42. data/test/unit/test_skein_rpc_error.rb +0 -10
  43. data/test/unit/test_skein_rpc_request.rb +0 -93
@@ -9,9 +9,12 @@ class TestSkeinClient < Test::Unit::TestCase
9
9
  client = Skein::Client.new
10
10
 
11
11
  assert client.context
12
+ assert_false client.connection_shared?
13
+
14
+ client&.close
12
15
 
13
16
  ensure
14
- client and client.close
17
+ client&.close
15
18
  end
16
19
  end
17
20
  end
@@ -5,6 +5,6 @@ class TestSkeinPublisher < Test::Unit::TestCase
5
5
  publisher = Skein::Client::Publisher.new('test_name')
6
6
 
7
7
  ensure
8
- publisher and publisher.close
8
+ publisher and publisher.close(delete_queue: true)
9
9
  end
10
10
  end
@@ -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 = Thread.new do
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
- while (!subscribing)
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
- thread.join
49
+ wait_for { received }
33
50
 
34
- assert_equal({ "data" => true }, received)
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 = Skein::Client::Worker.new('test_rpc')
15
- handler = Skein::Handler.for(worker)
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
- handler.handle(JSON.dump(message)) do |response_json, error|
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
- handler.handle(JSON.dump(message)) do |response_json, error|
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
- 'result' => nil,
51
- 'error' => '[TestSkeinClientWorker::ErrorGenerator::CustomError] Example 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.3.7
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: 2017-03-20 00:00:00.000000000 Z
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: '0'
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/test_skein_rpc_error.rb
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
- rubyforge_project:
148
- rubygems_version: 2.5.2
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: []
@@ -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
@@ -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
@@ -1,2 +0,0 @@
1
- class Skein::RPC::Notification < Skein::RPC::Base
2
- end
@@ -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