queue-bus 0.10.0 → 0.13.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 +4 -4
- data/CHANGELOG.md +27 -0
- data/README.mdown +25 -3
- data/lib/queue-bus.rb +2 -1
- data/lib/queue_bus/application.rb +35 -8
- data/lib/queue_bus/config.rb +22 -1
- data/lib/queue_bus/dispatch.rb +39 -0
- data/lib/queue_bus/publishing.rb +1 -0
- data/lib/queue_bus/version.rb +1 -1
- data/spec/config_spec.rb +35 -0
- data/spec/dispatch_spec.rb +146 -0
- data/spec/publish_spec.rb +22 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5383fd5290386ad57b383532a59406032e960ee344dc218db4c6c2e83a8fc8df
|
4
|
+
data.tar.gz: 6e695fc97a76265c6fa98984278e517b5e21dc7142c7d7b9ff646e02e52af5ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a238383614d2505facac1c2003d8b55cff3d3c68c1bd0a136ce5444cbae92377df9fd9316feb912180bc2a9272f30257dcc028c345178cc56c18f6c9fee8aa5
|
7
|
+
data.tar.gz: 507b3514db5c2290e4c2cedf60d77cfed61f8fc9b4b0ae1c647de40350fdd52342144b4bdba32ad94fc5f734fd4413d80f7517ff083ebda0d8f1b28984c28421
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.13.1]
|
10
|
+
|
11
|
+
### Fixes
|
12
|
+
|
13
|
+
- Allows matching on 0 via the `on_heartbeat` subscription
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Allows matching on `wday` via the `on_heartbeat` subscription
|
18
|
+
|
19
|
+
## [0.13.0]
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
- Adds `Dispatch#on_heartbeat` which is a helper function for specifying heartbeat subscriptions.
|
24
|
+
|
25
|
+
## [0.12.0]
|
26
|
+
|
27
|
+
### Changed
|
28
|
+
- Pipelines fetching all queue subscriptions when using `QueueBus::Application.all`
|
29
|
+
|
30
|
+
## [0.11.0]
|
31
|
+
|
32
|
+
### Added
|
33
|
+
|
34
|
+
- Adds `QueueBus.in_context` method. Useful when working with a multithreaded environment to add a description for all events published within this scope.
|
35
|
+
|
9
36
|
## [0.10.0]
|
10
37
|
|
11
38
|
### Added
|
data/README.mdown
CHANGED
@@ -63,6 +63,16 @@ QueueBus.dispatch("app_b") do
|
|
63
63
|
subscribe "my_key", { "user_id" => :present, "page" => "homepage"} do
|
64
64
|
Mixpanel.homepage_action!(attributes["action"])
|
65
65
|
end
|
66
|
+
|
67
|
+
# You may also declare a subscription to heartbeat events. This is a helper function
|
68
|
+
# that works along with subscribe to make scheduling regular events easier.
|
69
|
+
#
|
70
|
+
# minute_interval: Executes every n minutes
|
71
|
+
# hour_interval: Executes every n hours
|
72
|
+
# minute: Executes on this minute
|
73
|
+
# hour: Executes on this hour
|
74
|
+
on_heartbeat "my_heartbeat_event", minute_interval: 5 do |attributes|
|
75
|
+
end
|
66
76
|
end
|
67
77
|
```
|
68
78
|
|
@@ -141,13 +151,16 @@ event to the appropriate code block.
|
|
141
151
|
You can also say `QueueBus.local_mode = :suppress` to turn off publishing altogether.
|
142
152
|
This can be helpful inside some sort of migration, for example.
|
143
153
|
|
144
|
-
#### Thread Safe
|
154
|
+
#### Thread Safe Options
|
145
155
|
|
146
156
|
**!! This is important if you are using workers that utilize multiple threads, such as Sidekiq !!**
|
147
157
|
|
148
158
|
The above setting is global to the ruby process and modifying it will impact all threads that are
|
149
159
|
currently using QueueBus. If you want to isolate a thread or block of code from QueueBus, you can
|
150
|
-
use the
|
160
|
+
use the methods `with_local_mode` or `in_context`:
|
161
|
+
|
162
|
+
|
163
|
+
With local mode
|
151
164
|
|
152
165
|
```ruby
|
153
166
|
QueueBus.with_local_mode(:suppress) do
|
@@ -155,7 +168,16 @@ QueueBus.with_local_mode(:suppress) do
|
|
155
168
|
end
|
156
169
|
```
|
157
170
|
|
158
|
-
|
171
|
+
In context
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
QueueBus.in_context('some_context') do
|
175
|
+
# Context attribute will be set for all events published within this scope.
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
|
180
|
+
The previous values will be restored after the block exits.
|
159
181
|
|
160
182
|
### TODO
|
161
183
|
|
data/lib/queue-bus.rb
CHANGED
@@ -43,7 +43,8 @@ module QueueBus
|
|
43
43
|
:hostname=, :hostname,
|
44
44
|
:adapter=, :adapter, :has_adapter?,
|
45
45
|
:incoming_queue=, :incoming_queue,
|
46
|
-
:redis, :worker_middleware_stack
|
46
|
+
:redis, :worker_middleware_stack,
|
47
|
+
:context=, :context, :in_context
|
47
48
|
|
48
49
|
def_delegators :_dispatchers, :dispatch, :dispatchers, :dispatcher_by_key, :dispatcher_execute
|
49
50
|
|
@@ -7,7 +7,22 @@ module QueueBus
|
|
7
7
|
class << self
|
8
8
|
def all
|
9
9
|
# note the names arent the same as we started with
|
10
|
-
::QueueBus.redis
|
10
|
+
::QueueBus.redis do |redis|
|
11
|
+
app_keys = redis.smembers(app_list_key)
|
12
|
+
apps = app_keys.collect { |val| new(val) }
|
13
|
+
|
14
|
+
hashes = redis.pipelined do
|
15
|
+
apps.each do |app|
|
16
|
+
redis.hgetall(app.redis_key)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
apps.zip(hashes).each do |app, hash|
|
21
|
+
app._hydrate_redis_hash(hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
apps
|
25
|
+
end
|
11
26
|
end
|
12
27
|
end
|
13
28
|
|
@@ -90,6 +105,10 @@ module QueueBus
|
|
90
105
|
out
|
91
106
|
end
|
92
107
|
|
108
|
+
def _hydrate_redis_hash(hash)
|
109
|
+
@raw_redis_hash = hash
|
110
|
+
end
|
111
|
+
|
93
112
|
protected
|
94
113
|
|
95
114
|
def self.normalize(val)
|
@@ -114,16 +133,24 @@ module QueueBus
|
|
114
133
|
|
115
134
|
def read_redis_hash
|
116
135
|
out = {}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
out[key] = val
|
123
|
-
end
|
136
|
+
raw_redis_hash.each do |key, val|
|
137
|
+
begin
|
138
|
+
out[key] = ::QueueBus::Util.decode(val)
|
139
|
+
rescue ::QueueBus::Util::DecodeException
|
140
|
+
out[key] = val
|
124
141
|
end
|
125
142
|
end
|
126
143
|
out
|
127
144
|
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def raw_redis_hash
|
149
|
+
return @raw_redis_hash if @raw_redis_hash
|
150
|
+
|
151
|
+
::QueueBus.redis do |redis|
|
152
|
+
redis.hgetall(redis_key)
|
153
|
+
end
|
154
|
+
end
|
128
155
|
end
|
129
156
|
end
|
data/lib/queue_bus/config.rb
CHANGED
@@ -9,7 +9,7 @@ module QueueBus
|
|
9
9
|
attr_accessor :default_queue, :hostname, :incoming_queue, :logger
|
10
10
|
|
11
11
|
attr_reader :worker_middleware_stack
|
12
|
-
attr_writer :local_mode
|
12
|
+
attr_writer :local_mode, :context
|
13
13
|
|
14
14
|
def initialize
|
15
15
|
@worker_middleware_stack = QueueBus::Middleware::Stack.new
|
@@ -24,6 +24,7 @@ module QueueBus
|
|
24
24
|
Wrap = Struct.new(:value)
|
25
25
|
|
26
26
|
LOCAL_MODE_VAR = :queue_bus_local_mode
|
27
|
+
CONTEXT_VAR = :queue_bus_context
|
27
28
|
|
28
29
|
# Returns the current local mode of QueueBus
|
29
30
|
def local_mode
|
@@ -34,6 +35,15 @@ module QueueBus
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
38
|
+
# Returns the current context of QueueBus
|
39
|
+
def context
|
40
|
+
if Thread.current.thread_variable_get(CONTEXT_VAR).is_a?(Wrap)
|
41
|
+
Thread.current.thread_variable_get(CONTEXT_VAR).value
|
42
|
+
else
|
43
|
+
@context
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
37
47
|
# Overrides the current local mode for the duration of a block. This is a threadsafe
|
38
48
|
# implementation. After, the global setting will be resumed.
|
39
49
|
#
|
@@ -46,6 +56,17 @@ module QueueBus
|
|
46
56
|
Thread.current.thread_variable_set(LOCAL_MODE_VAR, previous)
|
47
57
|
end
|
48
58
|
|
59
|
+
# Overrides the current bus context (if any) for the duration of a block, adding a
|
60
|
+
# `bus_context` attribute set to this value for all events published in this scope.
|
61
|
+
# This is a threadsafe implementation. After, the global setting will be resumed.
|
62
|
+
def in_context(context)
|
63
|
+
previous = Thread.current.thread_variable_get(CONTEXT_VAR)
|
64
|
+
Thread.current.thread_variable_set(CONTEXT_VAR, Wrap.new(context))
|
65
|
+
yield if block_given?
|
66
|
+
ensure
|
67
|
+
Thread.current.thread_variable_set(CONTEXT_VAR, previous)
|
68
|
+
end
|
69
|
+
|
49
70
|
def adapter=(val)
|
50
71
|
raise "Adapter already set to #{@adapter_instance.class.name}" if has_adapter?
|
51
72
|
|
data/lib/queue_bus/dispatch.rb
CHANGED
@@ -16,6 +16,45 @@ module QueueBus
|
|
16
16
|
@subscriptions.size
|
17
17
|
end
|
18
18
|
|
19
|
+
def on_heartbeat(key, minute: nil, hour: nil, wday: nil, minute_interval: nil, hour_interval: nil, &block) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/ParameterLists, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/LineLength
|
20
|
+
if minute_interval && !minute_interval.positive?
|
21
|
+
raise ArgumentError, 'minute_interval must be a positive integer'
|
22
|
+
end
|
23
|
+
|
24
|
+
if hour_interval && !hour_interval.positive?
|
25
|
+
raise ArgumentError, 'hour_interval must be a positive integer'
|
26
|
+
end
|
27
|
+
|
28
|
+
matcher = { bus_event_type: :heartbeat_minutes }
|
29
|
+
|
30
|
+
if minute
|
31
|
+
raise ArgumentError, 'minute must not be negative' if minute.negative?
|
32
|
+
|
33
|
+
matcher['minute'] = minute
|
34
|
+
end
|
35
|
+
|
36
|
+
if hour
|
37
|
+
raise ArgumentError, 'hour must not be negative' if hour.negative?
|
38
|
+
|
39
|
+
matcher['hour'] = hour
|
40
|
+
end
|
41
|
+
|
42
|
+
if wday
|
43
|
+
raise ArgumentError, 'wday must not be negative' if wday.negative?
|
44
|
+
|
45
|
+
matcher['wday'] = wday
|
46
|
+
end
|
47
|
+
|
48
|
+
subscribe(key, matcher) do |event|
|
49
|
+
if (minute_interval.nil? || (event['minute'] % minute_interval).zero?) &&
|
50
|
+
(hour_interval.nil? || (event['hour'] % hour_interval).zero?)
|
51
|
+
|
52
|
+
# Yield the block passed in.
|
53
|
+
block.call
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
19
58
|
def subscribe(key, matcher_hash = nil, &block)
|
20
59
|
dispatch_event('default', key, matcher_hash, block)
|
21
60
|
end
|
data/lib/queue_bus/publishing.rb
CHANGED
@@ -30,6 +30,7 @@ module QueueBus
|
|
30
30
|
bus_attr = { 'bus_published_at' => Time.now.to_i, 'bus_event_type' => event_type }
|
31
31
|
bus_attr['bus_id'] = "#{Time.now.to_i}-#{generate_uuid}"
|
32
32
|
bus_attr['bus_app_hostname'] = ::QueueBus.hostname
|
33
|
+
bus_attr['bus_context'] = ::QueueBus.context unless ::QueueBus.context.nil?
|
33
34
|
if defined?(I18n) && I18n.respond_to?(:locale) && I18n.locale
|
34
35
|
bus_attr['bus_locale'] = I18n.locale.to_s
|
35
36
|
end
|
data/lib/queue_bus/version.rb
CHANGED
data/spec/config_spec.rb
CHANGED
@@ -61,6 +61,41 @@ describe 'QueueBus config' do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
describe '#in_context' do
|
65
|
+
it 'sets the context on the thread' do
|
66
|
+
QueueBus.in_context(:batch_processing) do
|
67
|
+
expect(QueueBus.context).to eq(:batch_processing)
|
68
|
+
Thread.new { expect(QueueBus.context).to eq nil }.join
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'supports nesting' do
|
73
|
+
QueueBus.in_context(:batch_processing) do
|
74
|
+
expect(QueueBus.context).to eq :batch_processing
|
75
|
+
QueueBus.in_context(:processing) do
|
76
|
+
expect(QueueBus.context).to eq :processing
|
77
|
+
end
|
78
|
+
expect(QueueBus.context).to eq :batch_processing
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'respects an override of nil' do
|
83
|
+
QueueBus.context = :batch_processing
|
84
|
+
QueueBus.in_context(nil) do
|
85
|
+
expect(QueueBus.context).to eq nil
|
86
|
+
end
|
87
|
+
QueueBus.context = :batch_processing
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'resets to the original context after the block' do
|
91
|
+
expect(QueueBus.context).to eq nil
|
92
|
+
QueueBus.in_context(:batch_processing) do
|
93
|
+
expect(QueueBus.context).to eq :batch_processing
|
94
|
+
end
|
95
|
+
expect(QueueBus.context).to eq nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
64
99
|
it 'sets the hostname' do
|
65
100
|
expect(QueueBus.hostname).not_to eq(nil)
|
66
101
|
QueueBus.hostname = 'whatever'
|
data/spec/dispatch_spec.rb
CHANGED
@@ -28,6 +28,152 @@ module QueueBus
|
|
28
28
|
end.not_to raise_error
|
29
29
|
end
|
30
30
|
|
31
|
+
describe '#on_heartbeat' do
|
32
|
+
let(:dispatch) { Dispatch.new('heartbeat') }
|
33
|
+
let(:event) { { bus_event_type: :heartbeat_minutes } }
|
34
|
+
let(:event_name) { 'my-event' }
|
35
|
+
|
36
|
+
context 'when not declaring anything' do
|
37
|
+
before do
|
38
|
+
dispatch.on_heartbeat event_name do |_event|
|
39
|
+
Runner2.run({})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'runs on every heart beat' do
|
44
|
+
(0..24).each do |hour|
|
45
|
+
(0..60).each do |minute|
|
46
|
+
expect do
|
47
|
+
dispatch.execute(
|
48
|
+
event_name, event.merge('hour' => hour, 'minute' => minute)
|
49
|
+
)
|
50
|
+
end.to change(Runner2, :value).by(1)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when running on hour 8' do
|
57
|
+
before do
|
58
|
+
dispatch.on_heartbeat event_name, hour: 8 do |_event|
|
59
|
+
Runner2.run({})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'subscribes to hour 8' do
|
64
|
+
expect(dispatch.subscriptions.all.first.matcher.filters)
|
65
|
+
.to eq('bus_event_type' => 'heartbeat_minutes', 'hour' => '8')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when running on minute 4' do
|
70
|
+
before do
|
71
|
+
dispatch.on_heartbeat event_name, minute: 4 do |_event|
|
72
|
+
Runner2.run({})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'subscribes to minute 4' do
|
77
|
+
expect(dispatch.subscriptions.all.first.matcher.filters)
|
78
|
+
.to eq('bus_event_type' => 'heartbeat_minutes', 'minute' => '4')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when running on minute 4 and hour 8' do
|
83
|
+
before do
|
84
|
+
dispatch.on_heartbeat event_name, hour: 8, minute: 4 do |_event|
|
85
|
+
Runner2.run({})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'subscribes to minute 4 and hour 8' do
|
90
|
+
expect(dispatch.subscriptions.all.first.matcher.filters)
|
91
|
+
.to eq('bus_event_type' => 'heartbeat_minutes', 'minute' => '4', 'hour' => '8')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when running on wday 2' do
|
96
|
+
before do
|
97
|
+
dispatch.on_heartbeat event_name, wday: 2 do |_event|
|
98
|
+
Runner2.run({})
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'subscribes to wday 2' do
|
103
|
+
expect(dispatch.subscriptions.all.first.matcher.filters)
|
104
|
+
.to eq('bus_event_type' => 'heartbeat_minutes', 'wday' => '2')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when declaring minute intervals' do
|
109
|
+
before do
|
110
|
+
dispatch.on_heartbeat event_name, minute_interval: 5 do |_event|
|
111
|
+
Runner2.run({})
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'runs the runner when the minute buzzes (modulos to 5)' do
|
116
|
+
(0..60).each do |minute|
|
117
|
+
if minute % 5 == 0
|
118
|
+
expect { dispatch.execute(event_name, event.merge('minute' => minute)) }
|
119
|
+
.to change(Runner2, :value).by(1)
|
120
|
+
else
|
121
|
+
expect { dispatch.execute(event_name, event.merge('minute' => minute)) }
|
122
|
+
.not_to change(Runner2, :value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when declaring hour intervals' do
|
129
|
+
before do
|
130
|
+
dispatch.on_heartbeat event_name, hour_interval: 3 do |_event|
|
131
|
+
Runner2.run({})
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'runs the runner when the hour fizzes (modulos to 3)' do
|
136
|
+
(0..60).each do |hour|
|
137
|
+
if hour % 3 == 0
|
138
|
+
expect { dispatch.execute(event_name, event.merge('hour' => hour)) }
|
139
|
+
.to change(Runner2, :value).by(1)
|
140
|
+
else
|
141
|
+
expect { dispatch.execute(event_name, event.merge('hour' => hour)) }
|
142
|
+
.not_to change(Runner2, :value)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'when declaring hour and minute intervals' do
|
149
|
+
before do
|
150
|
+
dispatch.on_heartbeat event_name, minute_interval: 5, hour_interval: 3 do |_event|
|
151
|
+
Runner2.run({})
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'runs the runner when the time fizzbuzzes (modulos to 3 and 5)' do
|
156
|
+
(0..24).each do |hour|
|
157
|
+
(0..60).each do |minute|
|
158
|
+
if hour % 3 == 0 && minute % 5 == 0
|
159
|
+
expect do
|
160
|
+
dispatch.execute(
|
161
|
+
event_name, event.merge('hour' => hour, 'minute' => minute)
|
162
|
+
)
|
163
|
+
end.to change(Runner2, :value).by(1)
|
164
|
+
else
|
165
|
+
expect do
|
166
|
+
dispatch.execute(
|
167
|
+
event_name, event.merge('hour' => hour, 'minute' => minute)
|
168
|
+
)
|
169
|
+
end.not_to change(Runner2, :value)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
31
177
|
describe 'Top Level' do
|
32
178
|
before(:each) do
|
33
179
|
QueueBus.dispatch('testit') do
|
data/spec/publish_spec.rb
CHANGED
@@ -71,6 +71,28 @@ describe 'Publishing an event' do
|
|
71
71
|
expect(myval).to eq(1)
|
72
72
|
end
|
73
73
|
|
74
|
+
it 'should add context metadata if wrapping publisher with in_context' do
|
75
|
+
expect(QueueBus.context).to be_nil
|
76
|
+
|
77
|
+
bus_context = 'batch_processing'
|
78
|
+
hash = { :one => 1, 'two' => 'here', 'bus_id' => 'app-given' }
|
79
|
+
|
80
|
+
event_name = 'event_name'
|
81
|
+
|
82
|
+
QueueBus.in_context(:batch_processing) do
|
83
|
+
QueueBus.publish(event_name, hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
|
87
|
+
hash = JSON.parse(val)
|
88
|
+
|
89
|
+
att = JSON.parse(hash['args'].first)
|
90
|
+
expect(att['bus_context']).to eq(bus_context)
|
91
|
+
|
92
|
+
expect(QueueBus.context).to be_nil
|
93
|
+
|
94
|
+
end
|
95
|
+
|
74
96
|
it 'should set the timezone and locale if available' do
|
75
97
|
expect(defined?(I18n)).to be_nil
|
76
98
|
expect(Time.respond_to?(:zone)).to eq(false)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: queue-bus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Leonard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|