queue-bus 0.12.0 → 0.13.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 329cc0a74e428d99421a14c9b2b07e39e14ee98da5c43babceb51376d27006c6
4
- data.tar.gz: 2439e577df8ea33e2f959b49ddfc105858844080556c4431a47897667d87fa92
3
+ metadata.gz: 511b1d30315adbfe76e6fa303aaba3158d56d39bea93355a0d28c18c8b0578cb
4
+ data.tar.gz: ba55e76505d56b98a416ff60c64c2c384734cd18af332768f6631e490caf4ed5
5
5
  SHA512:
6
- metadata.gz: 2875311c4100923fc00886ac05e2b4053ec6bfff442114faa6cc6bf39698916234866f57ebcbeb09dbcaca85484ca3bb0ce88cdbf8eb5640f6ca3b46d88a5a23
7
- data.tar.gz: f7d88adffc92f2635b1068f47c68238787b55eea86d4302bc2579a40bc2c3ff4ce145d62688a7584a2b48fa31b03951b993757a0e3b65eb71a1b3a4715aeb741
6
+ metadata.gz: b0f0d47e2be417d33b1f396043fd604ff936d9a1f258550b725673b4a9649d6e6153edaca77a064996ab3f0c43b59849ab04a66c49f3afb4f2d058a7c788f1e3
7
+ data.tar.gz: 941c73b6e35945a181651bb03746fff2022947fe89102daebd76f72e211150dfd2382ebd41bbd35857b1c5b9a2f099389b25392ba8e0c210615b624ef5898fb0
data/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.13.0]
10
+
11
+ ### Added
12
+
13
+ - Adds `Dispatch#on_heartbeat` which is a helper function for specifying heartbeat subscriptions.
14
+
9
15
  ## [0.12.0]
10
16
 
11
17
  ### Changed
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
 
@@ -16,6 +16,39 @@ module QueueBus
16
16
  @subscriptions.size
17
17
  end
18
18
 
19
+ def on_heartbeat(key, minute: nil, hour: nil, minute_interval: nil, hour_interval: nil, &block) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/ParameterLists, Metrics/CyclomaticComplexity, Metrics/AbcSize
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 be a positive integer' unless minute.positive?
32
+
33
+ matcher['minute'] = minute
34
+ end
35
+
36
+ if hour
37
+ raise ArgumentError, 'hour must be a positive integer' unless hour.positive?
38
+
39
+ matcher['hour'] = hour
40
+ end
41
+
42
+ subscribe(key, matcher) do |event|
43
+ if (minute_interval.nil? || (event['minute'] % minute_interval).zero?) &&
44
+ (hour_interval.nil? || (event['hour'] % hour_interval).zero?)
45
+
46
+ # Yield the block passed in.
47
+ block.call
48
+ end
49
+ end
50
+ end
51
+
19
52
  def subscribe(key, matcher_hash = nil, &block)
20
53
  dispatch_event('default', key, matcher_hash, block)
21
54
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QueueBus
4
- VERSION = '0.12.0'
4
+ VERSION = '0.13.0'
5
5
  end
@@ -28,6 +28,137 @@ 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).to eq('bus_event_type' => 'heartbeat_minutes', 'hour' => '8')
65
+ end
66
+ end
67
+
68
+ context 'when running on minute 4' do
69
+ before do
70
+ dispatch.on_heartbeat event_name, minute: 4 do |_event|
71
+ Runner2.run({})
72
+ end
73
+ end
74
+
75
+ it 'subscribes to minute 4' do
76
+ expect(dispatch.subscriptions.all.first.matcher.filters).to eq('bus_event_type' => 'heartbeat_minutes', 'minute' => '4')
77
+ end
78
+ end
79
+
80
+ context 'when running on minute 4 and hour 8' do
81
+ before do
82
+ dispatch.on_heartbeat event_name, hour: 8, minute: 4 do |_event|
83
+ Runner2.run({})
84
+ end
85
+ end
86
+
87
+ it 'subscribes to minute 4 and hour 8' do
88
+ expect(dispatch.subscriptions.all.first.matcher.filters)
89
+ .to eq('bus_event_type' => 'heartbeat_minutes', 'minute' => '4', 'hour' => '8')
90
+ end
91
+ end
92
+
93
+ context 'when declaring minute intervals' do
94
+ before do
95
+ dispatch.on_heartbeat event_name, minute_interval: 5 do |_event|
96
+ Runner2.run({})
97
+ end
98
+ end
99
+
100
+ it 'runs the runner when the minute buzzes (modulos to 5)' do
101
+ (0..60).each do |minute|
102
+ if minute % 5 == 0
103
+ expect { dispatch.execute(event_name, event.merge('minute' => minute)) }
104
+ .to change(Runner2, :value).by(1)
105
+ else
106
+ expect { dispatch.execute(event_name, event.merge('minute' => minute)) }
107
+ .not_to change(Runner2, :value)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ context 'when declaring hour intervals' do
114
+ before do
115
+ dispatch.on_heartbeat event_name, hour_interval: 3 do |_event|
116
+ Runner2.run({})
117
+ end
118
+ end
119
+
120
+ it 'runs the runner when the hour fizzes (modulos to 3)' do
121
+ (0..60).each do |hour|
122
+ if hour % 3 == 0
123
+ expect { dispatch.execute(event_name, event.merge('hour' => hour)) }
124
+ .to change(Runner2, :value).by(1)
125
+ else
126
+ expect { dispatch.execute(event_name, event.merge('hour' => hour)) }
127
+ .not_to change(Runner2, :value)
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'when declaring hour and minute intervals' do
134
+ before do
135
+ dispatch.on_heartbeat event_name, minute_interval: 5, hour_interval: 3 do |_event|
136
+ Runner2.run({})
137
+ end
138
+ end
139
+
140
+ it 'runs the runner when the time fizzbuzzes (modulos to 3 and 5)' do
141
+ (0..24).each do |hour|
142
+ (0..60).each do |minute|
143
+ if hour % 3 == 0 && minute % 5 == 0
144
+ expect do
145
+ dispatch.execute(
146
+ event_name, event.merge('hour' => hour, 'minute' => minute)
147
+ )
148
+ end.to change(Runner2, :value).by(1)
149
+ else
150
+ expect do
151
+ dispatch.execute(
152
+ event_name, event.merge('hour' => hour, 'minute' => minute)
153
+ )
154
+ end.not_to change(Runner2, :value)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+
31
162
  describe 'Top Level' do
32
163
  before(:each) do
33
164
  QueueBus.dispatch('testit') do
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.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Leonard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-16 00:00:00.000000000 Z
11
+ date: 2021-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json