tina4ruby 3.11.16 → 3.11.18

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: a33bdb237a1acedfe4903a9145ded69e405e9e63403c9a8c2e548795060d2740
4
- data.tar.gz: bf61f8a4a84be8f910c9767a23437ec8fbc4820fb3eb05da3ef73657b16f2585
3
+ metadata.gz: 2aa9ce02d7a7c924ae48d78b5ed1485261b85cde643ab13501040ea5bc7145da
4
+ data.tar.gz: f97407bec1e490e48714ae6d00ee78ad211b74e50ec0f94325d92f3dbf935e43
5
5
  SHA512:
6
- metadata.gz: 1c43c2556e8b8b742a1cb1cb52e26b011b1c64b56cdfb636fbfdf569789f0c7fa0d25094a201cda3d301fc9982832acfe60c01c4221b033e58a41dc6b06e7eea
7
- data.tar.gz: 8b38f262f9a5e41f3635000b22668200127c20cfe864bc18b316758ebbefeb58c4a4022961e929b0213a3a0e1657becf2348cdbcecf79c37f3f9561f7fa3bbdc
6
+ metadata.gz: c2bfb361e4de75738221dbdfb8f7a070cf224b71d02c389b0bc62171dd6566dea13d8fb0677f119ef331295d234fb1269d4a5a6573d026302d1c9d6c1b75a8e4
7
+ data.tar.gz: ac914458d86220ae3788f9a7da1a3cd427d4b0901139b53f57e007f93103bb5d82ded233b449dcebad4ae8145624ca971e9d056d36ae103f808b66c5a67689b3
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tina4
4
+ # Periodic background task registry.
5
+ #
6
+ # Matches Python's `tina4_python.core.server.background(fn, interval)` and
7
+ # PHP's `$app->background($callback, $interval)` — a callback that runs
8
+ # periodically alongside the server lifecycle.
9
+ #
10
+ # Ruby has no asyncio event loop, so each task runs in its own thread.
11
+ # The GIL keeps it cooperative-enough for the periodic work this is meant
12
+ # for (queue draining, health checks, simulators). Errors in the callback
13
+ # are caught and logged so they don't kill the thread.
14
+ module Background
15
+ class << self
16
+ # Register a periodic callback.
17
+ #
18
+ # @param callback [#call, nil] Object responding to `call` with no args.
19
+ # @param interval [Float] Seconds between invocations (default 1.0).
20
+ # @param block [Proc] Optional block (used if callback is nil).
21
+ # @return [Hash] The registered task descriptor.
22
+ def register(callback = nil, interval: 1.0, &block)
23
+ cb = callback || block
24
+ raise ArgumentError, "background requires a callback or block" if cb.nil?
25
+ raise ArgumentError, "callback must respond to :call" unless cb.respond_to?(:call)
26
+
27
+ task = { callback: cb, interval: interval.to_f, thread: nil, running: false }
28
+ mutex.synchronize { tasks << task }
29
+ start_task(task)
30
+ task
31
+ end
32
+
33
+ # All registered task descriptors. Tests use this for introspection.
34
+ def tasks
35
+ @tasks ||= []
36
+ end
37
+
38
+ # Stop and join every running task. Called on graceful shutdown.
39
+ def stop_all(timeout: 2.0)
40
+ snapshot = mutex.synchronize { tasks.dup }
41
+ snapshot.each { |task| stop_task(task, timeout: timeout) }
42
+ mutex.synchronize { tasks.clear }
43
+ end
44
+
45
+ # Stop a single task. Used by tests that register, fire, then stop.
46
+ def stop_task(task, timeout: 2.0)
47
+ task[:running] = false
48
+ thread = task[:thread]
49
+ return unless thread
50
+
51
+ thread.join(timeout) || thread.kill
52
+ task[:thread] = nil
53
+ end
54
+
55
+ private
56
+
57
+ def mutex
58
+ @mutex ||= Mutex.new
59
+ end
60
+
61
+ def start_task(task)
62
+ task[:running] = true
63
+ task[:thread] = Thread.new do
64
+ while task[:running]
65
+ sleep task[:interval]
66
+ break unless task[:running]
67
+
68
+ begin
69
+ task[:callback].call
70
+ rescue => e
71
+ # Never let a callback error kill the thread — next interval still fires.
72
+ if defined?(Tina4::Log) && Tina4::Log.respond_to?(:error)
73
+ Tina4::Log.error("background task error: #{e.class}: #{e.message}")
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -407,7 +407,9 @@ module Tina4
407
407
  resolved = id ? error_tracker.resolve(id) : false
408
408
  json_response({ resolved: resolved, id: id })
409
409
  when ["POST", "/__dev/api/broken/clear"]
410
- error_tracker.clear_resolved
410
+ # "Clear All" button — flush every tracked error, not only the
411
+ # ones individually marked resolved. Matches PHP/Python.
412
+ error_tracker.clear_all
411
413
  json_response({ cleared: true })
412
414
  when ["GET", "/__dev/api/websockets"]
413
415
  json_response({ connections: [], count: 0 })