crono_trigger 0.7.0 → 0.8.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 +4 -4
- data/.github/workflows/rspec.yml +3 -0
- data/.gitignore +3 -0
- data/gemfiles/{activerecord-50.gemfile → activerecord-61.gemfile} +1 -1
- data/gemfiles/{activerecord-51.gemfile → activerecord-70.gemfile} +1 -1
- data/gemfiles/{activerecord-52.gemfile → activerecord-71.gemfile} +1 -1
- data/lib/crono_trigger/models/worker.rb +6 -1
- data/lib/crono_trigger/polling_thread.rb +7 -1
- data/lib/crono_trigger/schedulable.rb +7 -2
- data/lib/crono_trigger/version.rb +1 -1
- data/lib/crono_trigger/worker.rb +27 -1
- metadata +6 -7
- data/.travis.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 734da2ad0480e79b440d8ef73f9b83fb88f13e6f6510513340c62b70c3750c39
|
4
|
+
data.tar.gz: b338b9c86a9fdf01d0ba739fa9f53c9536393cec05d7fe5c8943fe05782ad7b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e73b97cece87a4b887e4cec1c5cbd153cc9ad51c3de1956c38ef2a5000fa74c0d3e52c07401c0aa033f0921852a2f6be85533aea050d425dc220c591681a210
|
7
|
+
data.tar.gz: dfbec13afaa581a544b50481fa54509ace24de39f8ecb6d99788e508bd680da1e5afd89abeb0cde7be8ad8db3c7c4b56ae67dbdf0bd087775eaeed62b92d8cac
|
data/.github/workflows/rspec.yml
CHANGED
@@ -12,6 +12,9 @@ jobs:
|
|
12
12
|
strategy:
|
13
13
|
matrix:
|
14
14
|
ruby-version: ['2.7', '3.0', '3.1']
|
15
|
+
gemfile: ["Gemfile", "gemfiles/activerecord-61.gemfile", "gemfiles/activerecord-70.gemfile", "gemfiles/activerecord-71.gemfile"]
|
16
|
+
env:
|
17
|
+
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
15
18
|
|
16
19
|
steps:
|
17
20
|
- uses: actions/checkout@v2
|
data/.gitignore
CHANGED
@@ -8,7 +8,12 @@ module CronoTrigger
|
|
8
8
|
ALIVE_THRESHOLD = CronoTrigger::Worker::HEARTBEAT_INTERVAL * 5
|
9
9
|
|
10
10
|
enum executor_status: {running: "running", quiet: "quiet", shuttingdown: "shuttingdown", shutdown: "shutdown"}
|
11
|
-
|
11
|
+
|
12
|
+
if ActiveRecord.version >= Gem::Version.new("7.1.0")
|
13
|
+
serialize :polling_model_names, coder: JSON
|
14
|
+
else
|
15
|
+
serialize :polling_model_names, JSON
|
16
|
+
end
|
12
17
|
|
13
18
|
scope :alive_workers, proc { where(arel_table[:last_heartbeated_at].gteq(Time.current - ALIVE_THRESHOLD)) }
|
14
19
|
end
|
@@ -10,6 +10,7 @@ module CronoTrigger
|
|
10
10
|
end
|
11
11
|
@execution_counter = execution_counter
|
12
12
|
@quiet = Concurrent::AtomicBoolean.new(false)
|
13
|
+
@worker_count = 1
|
13
14
|
end
|
14
15
|
|
15
16
|
def run
|
@@ -58,7 +59,7 @@ module CronoTrigger
|
|
58
59
|
maybe_has_next = true
|
59
60
|
while maybe_has_next && !@stop_flag.set?
|
60
61
|
records, maybe_has_next = model.connection_pool.with_connection do
|
61
|
-
model.executables_with_lock(limit: CronoTrigger.config.fetch_records || CronoTrigger.config.executor_thread * 3)
|
62
|
+
model.executables_with_lock(limit: CronoTrigger.config.fetch_records || CronoTrigger.config.executor_thread * 3, worker_count: @worker_count)
|
62
63
|
end
|
63
64
|
|
64
65
|
records.each do |record|
|
@@ -74,6 +75,11 @@ module CronoTrigger
|
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
78
|
+
def worker_count=(n)
|
79
|
+
raise ArgumentError, "worker_count must be greater than 0" if n <= 0
|
80
|
+
@worker_count = n
|
81
|
+
end
|
82
|
+
|
77
83
|
private
|
78
84
|
|
79
85
|
def process_record(record)
|
@@ -63,8 +63,11 @@ module CronoTrigger
|
|
63
63
|
end
|
64
64
|
|
65
65
|
module ClassMethods
|
66
|
-
def executables_with_lock(limit: CronoTrigger.config.executor_thread * 3)
|
67
|
-
|
66
|
+
def executables_with_lock(limit: CronoTrigger.config.executor_thread * 3, worker_count: 1)
|
67
|
+
# Fetch more than `limit` records because other workers might have acquired the lock
|
68
|
+
# and this method might not be able to return enough records for the executor to
|
69
|
+
# make the best use of the CPU.
|
70
|
+
ids = executables(limit: limit * worker_count).pluck(:id)
|
68
71
|
maybe_has_next = !ids.empty?
|
69
72
|
records = []
|
70
73
|
ids.each do |id|
|
@@ -75,6 +78,8 @@ module CronoTrigger
|
|
75
78
|
records << r
|
76
79
|
end
|
77
80
|
end
|
81
|
+
|
82
|
+
return [records, maybe_has_next] if records.size == limit
|
78
83
|
end
|
79
84
|
[records, maybe_has_next]
|
80
85
|
end
|
data/lib/crono_trigger/worker.rb
CHANGED
@@ -7,6 +7,7 @@ module CronoTrigger
|
|
7
7
|
HEARTBEAT_INTERVAL = 60
|
8
8
|
SIGNAL_FETCH_INTERVAL = 10
|
9
9
|
MONITOR_INTERVAL = 20
|
10
|
+
WORKER_COUNT_UPDATE_INTERVAL = 60
|
10
11
|
EXECUTOR_SHUTDOWN_TIMELIMIT = 300
|
11
12
|
OTHER_THREAD_SHUTDOWN_TIMELIMIT = 120
|
12
13
|
attr_reader :polling_threads
|
@@ -37,6 +38,7 @@ module CronoTrigger
|
|
37
38
|
@heartbeat_thread = run_heartbeat_thread
|
38
39
|
@signal_fetcn_thread = run_signal_fetch_thread
|
39
40
|
@monitor_thread = run_monitor_thread
|
41
|
+
@worker_count_updater_thread = run_worker_count_updater_thread
|
40
42
|
|
41
43
|
polling_thread_count = CronoTrigger.config.polling_thread || [@model_names.size, Concurrent.processor_count].min
|
42
44
|
# Assign local variable for Signal handling
|
@@ -58,6 +60,7 @@ module CronoTrigger
|
|
58
60
|
@executor.wait_for_termination(EXECUTOR_SHUTDOWN_TIMELIMIT)
|
59
61
|
@heartbeat_thread.join(OTHER_THREAD_SHUTDOWN_TIMELIMIT)
|
60
62
|
@signal_fetcn_thread.join(OTHER_THREAD_SHUTDOWN_TIMELIMIT)
|
63
|
+
@worker_count_updater_thread.join(OTHER_THREAD_SHUTDOWN_TIMELIMIT)
|
61
64
|
|
62
65
|
unregister
|
63
66
|
end
|
@@ -104,6 +107,15 @@ module CronoTrigger
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
110
|
+
def run_worker_count_updater_thread
|
111
|
+
update_worker_count
|
112
|
+
Thread.start do
|
113
|
+
until @stop_flag.wait_for_set(WORKER_COUNT_UPDATE_INTERVAL)
|
114
|
+
update_worker_count
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
107
119
|
def heartbeat
|
108
120
|
CronoTrigger::Models::Worker.connection_pool.with_connection do
|
109
121
|
begin
|
@@ -162,7 +174,7 @@ module CronoTrigger
|
|
162
174
|
return unless ActiveSupport::Notifications.notifier.listening?(CronoTrigger::Events::MONITOR)
|
163
175
|
|
164
176
|
CronoTrigger::Models::Worker.connection_pool.with_connection do
|
165
|
-
if
|
177
|
+
if workers_processing_same_models.order(:worker_id).limit(1).pluck(:worker_id).first != @crono_trigger_worker_id
|
166
178
|
# Return immediately to avoid redundant instruments
|
167
179
|
return
|
168
180
|
end
|
@@ -189,5 +201,19 @@ module CronoTrigger
|
|
189
201
|
rescue => ex
|
190
202
|
CronoTrigger::GlobalExceptionHandler.handle_global_exception(ex)
|
191
203
|
end
|
204
|
+
|
205
|
+
def update_worker_count
|
206
|
+
CronoTrigger::Models::Worker.connection_pool.with_connection do
|
207
|
+
worker_count = workers_processing_same_models.count
|
208
|
+
return if worker_count.zero?
|
209
|
+
@polling_threads.each { |th| th.worker_count = worker_count }
|
210
|
+
end
|
211
|
+
rescue => ex
|
212
|
+
CronoTrigger::GlobalExceptionHandler.handle_global_exception(ex)
|
213
|
+
end
|
214
|
+
|
215
|
+
def workers_processing_same_models
|
216
|
+
CronoTrigger.workers.where("polling_model_names = ?", @model_names.to_json)
|
217
|
+
end
|
192
218
|
end
|
193
219
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crono_trigger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joker1007
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chrono
|
@@ -247,7 +247,6 @@ files:
|
|
247
247
|
- ".github/workflows/rspec.yml"
|
248
248
|
- ".gitignore"
|
249
249
|
- ".rspec"
|
250
|
-
- ".travis.yml"
|
251
250
|
- Gemfile
|
252
251
|
- LICENSE.txt
|
253
252
|
- README.md
|
@@ -257,9 +256,9 @@ files:
|
|
257
256
|
- crono_trigger.gemspec
|
258
257
|
- exe/crono_trigger
|
259
258
|
- exe/crono_trigger-web
|
260
|
-
- gemfiles/activerecord-
|
261
|
-
- gemfiles/activerecord-
|
262
|
-
- gemfiles/activerecord-
|
259
|
+
- gemfiles/activerecord-61.gemfile
|
260
|
+
- gemfiles/activerecord-70.gemfile
|
261
|
+
- gemfiles/activerecord-71.gemfile
|
263
262
|
- lib/crono_trigger.rb
|
264
263
|
- lib/crono_trigger/cli.rb
|
265
264
|
- lib/crono_trigger/events.rb
|
@@ -341,7 +340,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
341
340
|
- !ruby/object:Gem::Version
|
342
341
|
version: '0'
|
343
342
|
requirements: []
|
344
|
-
rubygems_version: 3.
|
343
|
+
rubygems_version: 3.5.3
|
345
344
|
signing_key:
|
346
345
|
specification_version: 4
|
347
346
|
summary: In Service Asynchronous Job Scheduler for Rails
|
data/.travis.yml
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
cache: bundler
|
4
|
-
rvm:
|
5
|
-
- 2.7.0
|
6
|
-
- 2.6.3
|
7
|
-
gemfile:
|
8
|
-
- gemfiles/activerecord-52.gemfile
|
9
|
-
before_install:
|
10
|
-
- gem i bundler
|
11
|
-
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
|
12
|
-
services:
|
13
|
-
- mysql
|
14
|
-
env:
|
15
|
-
- DB=sqlite
|
16
|
-
- DB=mysql MYSQL_RESTART_COMMAND="sudo service mysql restart"
|
17
|
-
- NO_TIMESTAMP=false
|
18
|
-
- NO_TIMESTAMP=true
|