legionio 1.6.41 → 1.6.42

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: 7edcbf61a2a48b3302257e76bf2e39c5d7e8ebfe2f871518a33369e960121620
4
- data.tar.gz: f79f0aa5cefe9898d587660e0c86e57ed83d62a46125223aba1e53845f8646f5
3
+ metadata.gz: 57f30aa272e7d11d9d59754a4092686c31b8224438c3e754db778ec6bed46b89
4
+ data.tar.gz: 169950365e0ddc408ae7f497d05870b416502dc069fef6dc7843da1fa049049e
5
5
  SHA512:
6
- metadata.gz: 5086d7e1723b3a65236314f333a87dbbc7391dc86d72a4f530c4788013a8222e2c9e4528fd023ab85313ae9800fa1670a99cdfee31af5eee1ab349642eee2e84
7
- data.tar.gz: 78fccfab7bb20fe009ffc106a656353c82bd2760a580e54b51888b5a172a4807233bc79e259a5169e3d6ed747557cac68cbb14354b7c884bb82f5d1fc4d49c23
6
+ metadata.gz: 7ae7156ccfac8ef9eed39b528bf455008a220874903d74364a4fe79095a8a74ed3e4ab74ab8f4345c448ad76df8fa59ead5e7fd6e42b5493eb7eb34f56bf4fde
7
+ data.tar.gz: 3d4bbec7574202d679b7dabe9470f31de350580d917d9c31f264d7fb29c46524726fc52279750a64c16ee40c1ba1f4c9543ac0df5d720d3512abd769e9bf9b06
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.6.42] - 2026-03-31
6
+
7
+ ### Fixed
8
+ - `Every` and `Poll` actors now guard against overlapping executions using `Concurrent::AtomicBoolean` — if the previous tick is still running when the next interval fires, the new tick is skipped with a debug log instead of stacking up concurrent executions
9
+
5
10
  ## [1.6.41] - 2026-03-30
6
11
 
7
12
  ### Fixed
@@ -17,12 +17,19 @@ module Legion
17
17
  define_dsl_accessor :run_now, default: false
18
18
 
19
19
  def initialize(**_opts)
20
+ @executing = Concurrent::AtomicBoolean.new(false)
20
21
  @timer = Concurrent::TimerTask.new(execution_interval: time, run_now: run_now?) do
21
- log.debug "[Every] tick: #{self.class}" if defined?(log)
22
- begin
23
- skip_or_run { use_runner? ? runner : manual }
24
- rescue StandardError => e
25
- log.log_exception(e, payload_summary: "[Every] tick failed for #{self.class}", component_type: :actor) if defined?(log)
22
+ if @executing.make_true
23
+ begin
24
+ log.debug "[Every] tick: #{self.class}" if defined?(log)
25
+ skip_or_run { use_runner? ? runner : manual }
26
+ rescue StandardError => e
27
+ log.log_exception(e, payload_summary: "[Every] tick failed for #{self.class}", component_type: :actor) if defined?(log)
28
+ ensure
29
+ @executing.make_false
30
+ end
31
+ elsif defined?(log)
32
+ log.debug "[Every] skipped (previous still running): #{self.class}"
26
33
  end
27
34
  end
28
35
 
@@ -21,10 +21,19 @@ module Legion
21
21
  def initialize
22
22
  log.debug "Starting timer for #{self.class} with #{{ execution_interval: time, run_now: run_now?,
23
23
  check_subtask: check_subtask? }}"
24
+ @executing = Concurrent::AtomicBoolean.new(false)
24
25
  @timer = Concurrent::TimerTask.new(execution_interval: time, run_now: run_now?) do
25
- skip_or_run { poll_cycle }
26
- rescue StandardError => e
27
- Legion::Logging.log_exception(e, level: :fatal, component_type: :actor)
26
+ if @executing.make_true
27
+ begin
28
+ skip_or_run { poll_cycle }
29
+ rescue StandardError => e
30
+ Legion::Logging.log_exception(e, level: :fatal, component_type: :actor)
31
+ ensure
32
+ @executing.make_false
33
+ end
34
+ else
35
+ Legion::Logging.debug "[Poll] skipped (previous still running): #{self.class}"
36
+ end
28
37
  end
29
38
  @timer.execute
30
39
  rescue StandardError => e
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.6.41'
4
+ VERSION = '1.6.42'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legionio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.41
4
+ version: 1.6.42
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity