crono_trigger 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d0ca54718a635b6c32268bcb6ed480683d038923eb5f62cda38e91e3d43356a
4
- data.tar.gz: aa5d62ef5ecf4003391485e7392bc6493035a50ce73ca852fc4fa26619b17b2d
3
+ metadata.gz: 734da2ad0480e79b440d8ef73f9b83fb88f13e6f6510513340c62b70c3750c39
4
+ data.tar.gz: b338b9c86a9fdf01d0ba739fa9f53c9536393cec05d7fe5c8943fe05782ad7b4
5
5
  SHA512:
6
- metadata.gz: 54ed50aac9d11ae950e1cad9651a8a4c27a5a07f169eb2c92c8f2c761420f9e6ed2a5b83965df91e7e14e67128ee6a0698f5a6a9d5d6566946b8544f8795dcb0
7
- data.tar.gz: 10422746cbf88079591790766fd4e58f9152787e7a9ead6a0f94dbbd286cfc4caab8f69c6547716143db6584c7d6ab5e571435013d17f2ed1e833f77502d745d
6
+ metadata.gz: 6e73b97cece87a4b887e4cec1c5cbd153cc9ad51c3de1956c38ef2a5000fa74c0d3e52c07401c0aa033f0921852a2f6be85533aea050d425dc220c591681a210
7
+ data.tar.gz: dfbec13afaa581a544b50481fa54509ace24de39f8ecb6d99788e508bd680da1e5afd89abeb0cde7be8ad8db3c7c4b56ae67dbdf0bd087775eaeed62b92d8cac
@@ -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
@@ -18,3 +18,6 @@ spec/dummy/db/*.sqlite3
18
18
  spec/dummy/db/*.sqlite3-journal
19
19
  spec/dummy/log/*.log
20
20
  spec/dummy/tmp/
21
+ spec/testdb.sqlite3*
22
+
23
+ .gem_rbs_collection
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "activerecord", "~> 5.0.0"
3
+ gem "activerecord", "~> 6.1.0"
4
4
 
5
5
  gemspec :path => "../"
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "activerecord", "~> 5.1.0"
3
+ gem "activerecord", "~> 7.0.0"
4
4
 
5
5
  gemspec :path => "../"
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "activerecord", "~> 5.2.0"
3
+ gem "activerecord", "~> 7.1.0"
4
4
 
5
5
  gemspec :path => "../"
@@ -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
- serialize :polling_model_names, JSON
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
- ids = executables(limit: limit).pluck(:id)
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
@@ -1,3 +1,3 @@
1
1
  module CronoTrigger
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -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 CronoTrigger.workers.where("polling_model_names = ?", @model_names.to_json).order(:worker_id).limit(1).pluck(:worker_id).first != @crono_trigger_worker_id
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.7.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: 2023-06-07 00:00:00.000000000 Z
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-50.gemfile
261
- - gemfiles/activerecord-51.gemfile
262
- - gemfiles/activerecord-52.gemfile
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.4.10
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