symphony 0.12.3 → 0.14.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,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'loggability'
5
5
  require 'symphony' unless defined?( Symphony )
@@ -1,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'set'
5
5
  require 'sysexits'
@@ -7,7 +7,7 @@ require 'pluggability'
7
7
  require 'loggability'
8
8
 
9
9
  require 'msgpack'
10
- require 'yajl'
10
+ require 'json'
11
11
  require 'yaml'
12
12
 
13
13
  require 'symphony' unless defined?( Symphony )
@@ -47,6 +47,15 @@ class Symphony::Task
47
47
  plugin_prefixes 'symphony/tasks'
48
48
 
49
49
 
50
+ @queue = nil
51
+ @acknowledge = true
52
+ @routing_keys = Set.new
53
+ @prefetch = 10
54
+ @persistent = false
55
+ @always_rebind = false
56
+ @queue_type = nil
57
+
58
+
50
59
  ### Create a new Task object and listen for work. Exits with the code returned
51
60
  ### by #start when it's done.
52
61
  def self::run( exit_on_idle=false )
@@ -79,11 +88,15 @@ class Symphony::Task
79
88
  def self::inherited( subclass )
80
89
  super
81
90
 
91
+ subclass.instance_variable_set( :@queue, nil )
92
+ subclass.instance_variable_set( :@queue_type, nil )
93
+ subclass.instance_variable_set( :@always_rebind, false )
82
94
  subclass.instance_variable_set( :@routing_keys, Set.new )
83
95
  subclass.instance_variable_set( :@acknowledge, true )
84
96
  subclass.instance_variable_set( :@work_model, :longlived )
85
97
  subclass.instance_variable_set( :@prefetch, 10 )
86
98
  subclass.instance_variable_set( :@timeout_action, :reject )
99
+ subclass.instance_variable_set( :@timeout, nil )
87
100
  subclass.instance_variable_set( :@persistent, false )
88
101
  subclass.instance_variable_set( :@idle_timeout, DEFAULT_IDLE_TIMEOUT )
89
102
  end
@@ -132,6 +145,16 @@ class Symphony::Task
132
145
  end
133
146
 
134
147
 
148
+ ### Specify an x-queue-type for the underlying queue
149
+ def self::queue_type( type=nil )
150
+ if type
151
+ @queue_type = type
152
+ end
153
+
154
+ return @queue_type
155
+ end
156
+
157
+
135
158
  ### Set up one or more topic key patterns to use when binding the Task's queue
136
159
  ### to the exchange.
137
160
  def self::subscribe_to( *routing_keys )
@@ -438,7 +461,7 @@ class Symphony::Task
438
461
  when 'application/x-msgpack'
439
462
  MessagePack.unpack( payload )
440
463
  when 'application/json', 'text/javascript'
441
- Yajl::Parser.parse( payload )
464
+ JSON.parse( payload )
442
465
  when 'application/x-yaml', 'text/x-yaml'
443
466
  YAML.load( payload )
444
467
  else
@@ -1,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'set'
5
5
  require 'pluggability'
@@ -1,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'set'
5
5
  require 'symphony/task_group' unless defined?( Symphony::TaskGroup )
@@ -35,8 +35,9 @@ class Symphony::TaskGroup::LongLived < Symphony::TaskGroup
35
35
  return [ pid ]
36
36
  end
37
37
 
38
- @queue ||= self.get_message_counting_queue
39
-
38
+ return nil
39
+ rescue Timeout::Error => err
40
+ self.log.warn "%p while adjusting workers: %s" % [ err.class, err.message ]
40
41
  return nil
41
42
  end
42
43
 
@@ -44,11 +45,10 @@ class Symphony::TaskGroup::LongLived < Symphony::TaskGroup
44
45
  ### Return +true+ if the task group should scale up by one.
45
46
  def needs_a_worker?
46
47
  return true if self.workers.empty?
47
- return false unless @queue
48
-
48
+ queue = self.get_message_counting_queue or return false
49
49
 
50
50
  # Calculate the number of workers across the whole broker
51
- if ( cc = @queue.consumer_count ) >= self.max_workers
51
+ if ( cc = queue.consumer_count ) >= self.max_workers
52
52
  self.log.debug "%p: Already at max workers (%d)" % [ self.task_class, self.max_workers ]
53
53
  return false
54
54
  else
@@ -62,9 +62,10 @@ class Symphony::TaskGroup::LongLived < Symphony::TaskGroup
62
62
 
63
63
  ### Add the current number of workers to the samples.
64
64
  def sample_queue_status
65
- return unless @queue
65
+ return if self.workers.empty?
66
66
 
67
- count = @queue.message_count
67
+ queue = self.get_message_counting_queue or return
68
+ count = queue.message_count
68
69
  self.add_sample( count )
69
70
  end
70
71
 
@@ -82,11 +83,20 @@ class Symphony::TaskGroup::LongLived < Symphony::TaskGroup
82
83
  ### Get a queue for counting the number of messages in the queue for this
83
84
  ### worker.
84
85
  def get_message_counting_queue
85
- channel = Symphony::Queue.amqp_channel
86
- queue = channel.queue( self.task_class.queue_name, passive: true, prefetch: 0 )
86
+ @queue ||= begin
87
+ self.log.debug "Creating the message-counting queue."
88
+ channel = Symphony::Queue.amqp_channel
89
+ channel.queue( self.task_class.queue_name, passive: true, prefetch: 0 )
90
+ end
91
+
92
+ unless @queue.channel.open?
93
+ self.log.info "Message-counting queue's channel was closed: resetting."
94
+ Symphony::Queue.reset
95
+ @queue = nil
96
+ end
87
97
 
88
- return queue
89
- rescue Bunny::NotFound => err
98
+ return @queue
99
+ rescue Bunny::NotFound, Bunny::ChannelAlreadyClosed
90
100
  self.log.info "Child hasn't created the queue yet; deferring"
91
101
  Symphony::Queue.reset
92
102
 
@@ -1,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
 
4
4
  require 'symphony/task_group' unless defined?( Symphony::TaskGroup )
5
5
 
@@ -48,6 +48,10 @@ module Symphony::SpecHelpers
48
48
  def initialize
49
49
  @queue = nil
50
50
  @exchange = nil
51
+ @open = true
52
+ end
53
+ def open?
54
+ return @open
51
55
  end
52
56
  def queue( name, opts={} )
53
57
  return @queue ||= DummySession::Queue.new( self )
@@ -60,7 +64,9 @@ module Symphony::SpecHelpers
60
64
  def number
61
65
  return 1
62
66
  end
63
- def close; end
67
+ def close
68
+ @open = false
69
+ end
64
70
  end
65
71
 
66
72
  class Exchange
@@ -86,14 +92,24 @@ end
86
92
 
87
93
  ### Mock with RSpec
88
94
  RSpec.configure do |config|
89
- config.run_all_when_everything_filtered = true
90
- config.filter_run :focus
91
- config.order = 'random'
92
- config.expect_with( :rspec )
93
- config.mock_with( :rspec ) do |mock|
94
- mock.syntax = :expect
95
+ config.expect_with :rspec do |expectations|
96
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
97
+ expectations.syntax = :expect
98
+ end
99
+
100
+ config.mock_with :rspec do |mocks|
101
+ mocks.verify_partial_doubles = true
95
102
  end
96
103
 
104
+ config.run_all_when_everything_filtered = true
105
+ config.filter_run_when_matching :focus
106
+ config.order = :random
107
+ config.example_status_persistence_file_path = 'spec/.state'
108
+ config.disable_monkey_patching!
109
+ config.warnings = true
110
+ config.profile_examples = 5
111
+
112
+
97
113
  config.include( Loggability::SpecHelpers )
98
114
  config.include( Symphony::SpecHelpers )
99
115
  end
@@ -1,5 +1,5 @@
1
1
  # -*- ruby -*-
2
- #encoding: utf-8
2
+ # frozen_string_literal: true
3
3
  # vim: set noet nosta sw=4 ts=4 :
4
4
 
5
5
 
@@ -19,7 +19,7 @@ class Test3Task < Symphony::Task
19
19
  end
20
20
 
21
21
 
22
- describe Symphony::Daemon do
22
+ RSpec.describe Symphony::Daemon do
23
23
 
24
24
  before( :all ) do
25
25
  @pids = ( 200..65534 ).cycle
@@ -5,12 +5,16 @@ require_relative '../helpers'
5
5
  require 'symphony/mixins'
6
6
 
7
7
 
8
- describe Symphony, 'mixins' do
8
+ RSpec.describe Symphony, 'mixins' do
9
9
 
10
10
  describe Symphony::MethodUtilities, 'used to extend a class' do
11
11
 
12
12
  let!( :extended_class ) do
13
- klass = Class.new
13
+ klass = Class.new do
14
+ def initialize
15
+ @foo = nil
16
+ end
17
+ end
14
18
  klass.extend( Symphony::MethodUtilities )
15
19
  klass
16
20
  end
@@ -4,7 +4,7 @@ require_relative '../helpers'
4
4
 
5
5
  require 'symphony/queue'
6
6
 
7
- describe Symphony::Queue do
7
+ RSpec.describe Symphony::Queue do
8
8
 
9
9
 
10
10
  before( :each ) do
@@ -128,7 +128,33 @@ describe Symphony::Queue do
128
128
  expect( new_channel ).to receive( :prefetch ).
129
129
  with( Symphony::Queue::DEFAULT_PREFETCH )
130
130
  expect( new_channel ).to receive( :queue ).
131
- with( queue.name, auto_delete: true ).
131
+ with( queue.name, auto_delete: true, arguments: {} ).
132
+ and_return( amqp_queue )
133
+ expect( amqp_queue ).to receive( :bind ).
134
+ with( described_class.amqp_exchange, routing_key: 'floppy.rabbit.#' )
135
+
136
+ expect( queue.create_amqp_queue ).to be( amqp_queue )
137
+ end
138
+
139
+
140
+ it "can declare the queue's x-queue-type" do
141
+ testing_task_class.subscribe_to( 'floppy.rabbit.#' )
142
+ testing_task_class.queue_type( 'classic' )
143
+ expect( described_class.amqp_channel ).to receive( :queue ).
144
+ with( queue.name, passive: true ).
145
+ and_raise( Bunny::NotFound.new("no such queue", described_class.amqp_channel, true) )
146
+ expect( described_class.amqp_channel ).to receive( :open? ).
147
+ and_return( false )
148
+
149
+ # Channel is reset after queue creation fails
150
+ new_channel = double( "New AMQP channel" )
151
+ amqp_queue = double( "AMQP queue" )
152
+ allow( described_class.amqp_session ).to receive( :create_channel ).
153
+ and_return( new_channel )
154
+ expect( new_channel ).to receive( :prefetch ).
155
+ with( Symphony::Queue::DEFAULT_PREFETCH )
156
+ expect( new_channel ).to receive( :queue ).
157
+ with( queue.name, auto_delete: true, arguments: { 'x-queue-type' => 'classic' } ).
132
158
  and_return( amqp_queue )
133
159
  expect( amqp_queue ).to receive( :bind ).
134
160
  with( described_class.amqp_exchange, routing_key: 'floppy.rabbit.#' )
@@ -7,7 +7,7 @@ require 'symphony'
7
7
  require 'symphony/routing'
8
8
 
9
9
 
10
- describe Symphony::Routing do
10
+ RSpec.describe Symphony::Routing do
11
11
 
12
12
  let( :task_class ) do
13
13
  Class.new( Symphony::Task ) do
@@ -5,7 +5,7 @@ require_relative '../helpers'
5
5
  require 'symphony/statistics'
6
6
 
7
7
 
8
- describe Symphony::Statistics do
8
+ RSpec.describe Symphony::Statistics do
9
9
 
10
10
 
11
11
  let( :including_class ) do
@@ -4,7 +4,7 @@ require_relative '../../helpers'
4
4
 
5
5
  require 'symphony/task_group/longlived'
6
6
 
7
- describe Symphony::TaskGroup::LongLived do
7
+ RSpec.describe Symphony::TaskGroup::LongLived do
8
8
 
9
9
  FIRST_PID = 414
10
10
 
@@ -23,6 +23,9 @@ describe Symphony::TaskGroup::LongLived do
23
23
  def self::run
24
24
  self.has_run = true
25
25
  end
26
+ def self::name
27
+ return "TestTask"
28
+ end
26
29
  end
27
30
  end
28
31
 
@@ -75,8 +78,8 @@ describe Symphony::TaskGroup::LongLived do
75
78
 
76
79
  allow( Process ).to receive( :setpgid )
77
80
 
78
- channel = double( Bunny::Channel )
79
- queue = double( Bunny::Queue )
81
+ channel = double( Bunny::Channel, open?: true )
82
+ queue = double( Bunny::Queue, channel: channel )
80
83
  expect( Symphony::Queue ).to receive( :amqp_channel ).
81
84
  and_return( channel )
82
85
  expect( channel ).to receive( :queue ).
@@ -89,7 +92,8 @@ describe Symphony::TaskGroup::LongLived do
89
92
  expect( queue ).to receive( :message_count ).and_return( *samples )
90
93
 
91
94
  start = 1414002605
92
- start.upto( start + samples.size + 1 ) do |time|
95
+ start.upto( start + samples.size ) do |time|
96
+ Loggability.logger.debug "Foom"
93
97
  Timecop.freeze( time ) do
94
98
  task_group.adjust_workers
95
99
  end
@@ -106,8 +110,8 @@ describe Symphony::TaskGroup::LongLived do
106
110
 
107
111
  allow( Process ).to receive( :setpgid )
108
112
 
109
- channel = double( Bunny::Channel )
110
- queue = double( Bunny::Queue )
113
+ channel = double( Bunny::Channel, open?: true )
114
+ queue = double( Bunny::Queue, channel: channel )
111
115
  expect( Symphony::Queue ).to receive( :amqp_channel ).
112
116
  and_return( channel )
113
117
  expect( channel ).to receive( :queue ).
@@ -120,7 +124,7 @@ describe Symphony::TaskGroup::LongLived do
120
124
  expect( queue ).to receive( :message_count ).and_return( *samples )
121
125
 
122
126
  start = 1414002605
123
- start.upto( start + samples.size + 1 ) do |time|
127
+ start.upto( start + samples.size ) do |time|
124
128
  Timecop.freeze( time ) do
125
129
  task_group.adjust_workers
126
130
  end
@@ -136,8 +140,8 @@ describe Symphony::TaskGroup::LongLived do
136
140
 
137
141
  allow( Process ).to receive( :setpgid )
138
142
 
139
- channel = double( Bunny::Channel )
140
- queue = double( Bunny::Queue )
143
+ channel = double( Bunny::Channel, open?: true )
144
+ queue = double( Bunny::Queue, channel: channel )
141
145
  expect( Symphony::Queue ).to receive( :amqp_channel ).
142
146
  and_return( channel )
143
147
  expect( channel ).to receive( :queue ).
@@ -150,7 +154,7 @@ describe Symphony::TaskGroup::LongLived do
150
154
  expect( queue ).to receive( :message_count ).and_return( *samples )
151
155
 
152
156
  start = 1414002605
153
- start.upto( start + samples.size + 1 ) do |time|
157
+ start.upto( start + samples.size ) do |time|
154
158
  Timecop.freeze( time ) do
155
159
  task_group.adjust_workers
156
160
  end
@@ -166,8 +170,8 @@ describe Symphony::TaskGroup::LongLived do
166
170
 
167
171
  allow( Process ).to receive( :setpgid )
168
172
 
169
- channel = double( Bunny::Channel )
170
- queue = double( Bunny::Queue )
173
+ channel = double( Bunny::Channel, open?: true )
174
+ queue = double( Bunny::Queue, channel: channel )
171
175
  expect( Symphony::Queue ).to receive( :amqp_channel ).
172
176
  and_return( channel )
173
177
  expect( channel ).to receive( :queue ).
@@ -178,7 +182,7 @@ describe Symphony::TaskGroup::LongLived do
178
182
  expect( queue ).to receive( :message_count ).and_return( *samples )
179
183
 
180
184
  start = 1414002605
181
- start.upto( start + samples.size + 1 ) do |time|
185
+ start.upto( start + samples.size ) do |time|
182
186
  Timecop.freeze( time ) do
183
187
  task_group.adjust_workers
184
188
  end
@@ -194,8 +198,8 @@ describe Symphony::TaskGroup::LongLived do
194
198
 
195
199
  allow( Process ).to receive( :setpgid )
196
200
 
197
- channel = double( Bunny::Channel )
198
- queue = double( Bunny::Queue )
201
+ channel = double( Bunny::Channel, open?: true )
202
+ queue = double( Bunny::Queue, channel: channel )
199
203
  expect( Symphony::Queue ).to receive( :amqp_channel ).
200
204
  and_return( channel )
201
205
  expect( channel ).to receive( :queue ).
@@ -208,7 +212,7 @@ describe Symphony::TaskGroup::LongLived do
208
212
  expect( queue ).to receive( :message_count ).and_return( *samples )
209
213
 
210
214
  start = 1414002605
211
- start.upto( start + samples.size + 1 ) do |time|
215
+ start.upto( start + samples.size ) do |time|
212
216
  Timecop.freeze( time ) do
213
217
  task_group.adjust_workers
214
218
  end
@@ -5,7 +5,7 @@ require_relative '../../helpers'
5
5
  require 'symphony/task_group/oneshot'
6
6
 
7
7
 
8
- describe Symphony::TaskGroup::Oneshot do
8
+ RSpec.describe Symphony::TaskGroup::Oneshot do
9
9
 
10
10
  let( :task ) do
11
11
  Class.new( Symphony::Task ) do
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../helpers'
4
4
 
5
- describe Symphony::TaskGroup do
5
+ RSpec.describe Symphony::TaskGroup do
6
6
 
7
7
  let( :task ) do
8
8
  Class.new( Symphony::Task ) do