async-service 0.16.0 → 0.17.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: 1dc20befccfdbe1d36db11898e11a469ff64f2338a7b88942d59cb58e0e8c92f
4
- data.tar.gz: c2a09fad50e09a6188e30b213d921f832ac14706c8f23d721269e4e48cffe028
3
+ metadata.gz: 6e9258424ee834d70b309984ba6f2d0c89f87ed9b2a16ec38fb298dfafb33fcd
4
+ data.tar.gz: e91b2129702c7c8ad7f3203063d3dd526b8e6e91d322bb84388afe873cf638f0
5
5
  SHA512:
6
- metadata.gz: ef436a78425bfab299e187e37e81f6d442dd00ffbff6c3e526c94d5753395e03158219d3b92d7e3edec4a68babf277fc97448d2a18991b6ab1d79cfdd6cafb74
7
- data.tar.gz: 59468d0b53c26be506a8c4195cae58c91627352ebf09555bdcbf539d166c66d97f4c6a9ad3969fd0e8251f857cc058e4ad69e322ece8cd585b0579c0fbc44d69
6
+ metadata.gz: edc78ce3ff189ef951f19b206d02bbef4f2c121b10e24f074b6a7eab702c6ffeceb5e47c7c29d330363c7389c721b371c4584f33b9145cde42b798ec08e47237
7
+ data.tar.gz: be8a666be488d9d428339edea966834c0a7d5e935bcf330b8669f914b58661ed11deff0782b4202327951b108063992e5ac6f4fb9427beca5d6c1daaf09f440a
checksums.yaml.gz.sig CHANGED
Binary file
@@ -208,6 +208,7 @@ class WebService < Async::Service::ManagedService
208
208
  # Managed::Service automatically handles:
209
209
  # - Container setup with proper options.
210
210
  # - Health checking with process title updates.
211
+ # - Status messages during startup to prevent premature timeouts.
211
212
  # - Preloading of scripts before startup.
212
213
 
213
214
  private def format_title(evaluator, server)
@@ -222,6 +223,28 @@ class WebService < Async::Service::ManagedService
222
223
  end
223
224
  ```
224
225
 
226
+ ### Configure Timeouts for Slow-Starting Services
227
+
228
+ If your service takes a long time to start up (e.g., loading large datasets, connecting to external services), configure appropriate timeouts:
229
+
230
+ ```ruby
231
+ module WebEnvironment
232
+ include Async::Service::ManagedEnvironment
233
+
234
+ # Allow 2 minutes for startup.
235
+ def startup_timeout
236
+ 120
237
+ end
238
+
239
+ # Require health checks every 30 seconds.
240
+ def health_check_timeout
241
+ 30
242
+ end
243
+ end
244
+ ```
245
+
246
+ The `startup_timeout` ensures processes that hang during startup are detected, while `health_check_timeout` monitors processes after they've become ready. `ManagedService` automatically sends `status!` messages during startup to keep the health check clock resetting until the service is ready.
247
+
225
248
  ### Implement Meaningful Process Titles
226
249
 
227
250
  Use the `format_title` method to provide dynamic process information:
@@ -262,7 +262,9 @@ end
262
262
 
263
263
  ### Health Checking
264
264
 
265
- For services using `Async::Service::ManagedService`, health checking is handled automatically. For services extending `GenericService`, you can set up health checking manually:
265
+ For services using `Async::Service::ManagedService`, health checking is handled automatically. The service sends `status!` messages during startup to prevent premature health check timeouts, then transitions to sending `ready!` messages once the service is actually ready.
266
+
267
+ For services extending `GenericService`, you can set up health checking manually:
266
268
 
267
269
  ```ruby
268
270
  def setup(container)
@@ -270,12 +272,15 @@ def setup(container)
270
272
  health_check_timeout = container_options[:health_check_timeout]
271
273
 
272
274
  container.run(**container_options) do |instance|
275
+ # Send status updates during startup:
276
+ instance.status!("Preparing...")
273
277
  # Prepare your service.
274
278
 
275
279
  Async do
276
280
  # Start your service.
281
+ instance.status!("Starting...")
277
282
 
278
- # Set up health checking, if a timeout was specified:
283
+ # Once ready, set up health checking:
279
284
  health_checker(instance, health_check_timeout) do
280
285
  instance.name = "#{self.name}: #{current_status}"
281
286
  end
@@ -284,6 +289,30 @@ def setup(container)
284
289
  end
285
290
  ```
286
291
 
292
+ #### Startup Timeout vs Health Check Timeout
293
+
294
+ The container supports two separate timeout mechanisms:
295
+
296
+ - **`startup_timeout`**: Maximum time a process can take to become ready (call `ready!`) before being terminated. This detects processes that hang during startup and never become ready.
297
+ - **`health_check_timeout`**: Maximum time between health check messages after the process has become ready. This detects processes that stop responding after they've started.
298
+
299
+ Both timeouts use a single clock that starts when the process starts. The clock resets when the process becomes ready, transitioning from startup timeout monitoring to health check timeout monitoring.
300
+
301
+ You can configure these timeouts via `container_options`:
302
+
303
+ ```ruby
304
+ module WebEnvironment
305
+ include Async::Service::ManagedEnvironment
306
+
307
+ def container_options
308
+ super.merge(
309
+ startup_timeout: 60, # Allow up to 60 seconds for startup.
310
+ health_check_timeout: 30 # Require health checks every 30 seconds after ready.
311
+ )
312
+ end
313
+ end
314
+ ```
315
+
287
316
  Note: `Async::Service::ManagedService` automatically handles health checking, container options, and process title formatting, so you typically don't need to set this up manually.
288
317
 
289
318
  ## How They Work Together
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2024-2025, by Samuel Williams.
4
+ # Copyright, 2025-2026, by Samuel Williams.
5
5
 
6
6
  module Async
7
7
  module Service
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2025, by Samuel Williams.
4
+ # Copyright, 2025-2026, by Samuel Williams.
5
5
 
6
6
  module Async
7
7
  module Service
@@ -16,6 +16,13 @@ module Async
16
16
  nil
17
17
  end
18
18
 
19
+ # The timeout duration for the startup. Set to `nil` to disable the startup timeout.
20
+ #
21
+ # @returns [Numeric | nil] The startup timeout in seconds.
22
+ def startup_timeout
23
+ nil
24
+ end
25
+
19
26
  # The timeout duration for the health check. Set to `nil` to disable the health check.
20
27
  #
21
28
  # @returns [Numeric | nil] The health check timeout in seconds.
@@ -30,6 +37,7 @@ module Async
30
37
  {
31
38
  restart: true,
32
39
  count: self.count,
40
+ startup_timeout: self.startup_timeout,
33
41
  health_check_timeout: self.health_check_timeout,
34
42
  }.compact
35
43
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2025, by Samuel Williams.
4
+ # Copyright, 2025-2026, by Samuel Williams.
5
5
 
6
6
  require_relative "generic_service"
7
7
  require_relative "health_checker"
@@ -46,18 +46,32 @@ module Async
46
46
  rescue StandardError, LoadError => error
47
47
  Console.warn(self, "Service preload failed!", error)
48
48
  end
49
-
49
+
50
50
  # Start the service, including preloading resources.
51
51
  def start
52
52
  preload!
53
53
 
54
54
  super
55
55
  end
56
-
56
+
57
+ # Called after the service has been prepared but before it starts running.
58
+ #
59
+ # Override this method to emit metrics, logs, or perform other actions when the service preparation is complete.
60
+ #
61
+ # @parameter instance [Async::Container::Instance] The container instance.
62
+ # @parameter start_time [Async::Clock] The monotonic start time from {Async::Clock.start}.
57
63
  def emit_prepared(instance, start_time)
64
+ # Override in subclasses as needed.
58
65
  end
59
-
66
+
67
+ # Called after the service has started running.
68
+ #
69
+ # Override this method to emit metrics, logs, or perform other actions when the service begins running.
70
+ #
71
+ # @parameter instance [Async::Container::Instance] The container instance.
72
+ # @parameter start_time [Async::Clock] The monotonic start time from {Async::Clock.start}.
60
73
  def emit_running(instance, start_time)
74
+ # Override in subclasses as needed.
61
75
  end
62
76
 
63
77
  # Set up the container with health checking and process title formatting.
@@ -70,16 +84,16 @@ module Async
70
84
 
71
85
  container.run(**container_options) do |instance|
72
86
  start_time = Async::Clock.start
73
-
87
+
74
88
  Async do
75
89
  evaluator = self.environment.evaluator
76
90
 
91
+ instance.status!("Preparing...")
77
92
  evaluator.prepare!(instance)
78
-
79
93
  emit_prepared(instance, start_time)
80
-
81
- server = run(instance, evaluator)
82
94
 
95
+ instance.status!("Running...")
96
+ server = run(instance, evaluator)
83
97
  emit_running(instance, start_time)
84
98
 
85
99
  health_checker(instance) do
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Async
7
7
  module Service
8
- VERSION = "0.16.0"
8
+ VERSION = "0.17.0"
9
9
  end
10
10
  end
data/license.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2024-2025, by Samuel Williams.
3
+ Copyright, 2024-2026, by Samuel Williams.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -29,6 +29,11 @@ Please see the [project documentation](https://socketry.github.io/async-service/
29
29
 
30
30
  Please see the [project releases](https://socketry.github.io/async-service/releases/index) for all releases.
31
31
 
32
+ ### v0.17.0
33
+
34
+ - `ManagedService` now sends `status!` messages during startup to prevent premature health check timeouts for slow-starting services.
35
+ - Support for `startup_timeout` option via `container_options` to detect processes that hang during startup and never become ready.
36
+
32
37
  ### v0.16.0
33
38
 
34
39
  - Renamed `Async::Service::Generic` -\> `Async::Service::GenericService`, added compatibilty alias.
@@ -72,10 +77,6 @@ Please see the [project releases](https://socketry.github.io/async-service/relea
72
77
  - Add `Environment::Evaluator#as_json` for JSON serialization support.
73
78
  - Allow constructing a configuration with existing environments.
74
79
 
75
- ### v0.9.0
76
-
77
- - Allow providing a list of modules to include in environments.
78
-
79
80
  ## Contributing
80
81
 
81
82
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.17.0
4
+
5
+ - `ManagedService` now sends `status!` messages during startup to prevent premature health check timeouts for slow-starting services.
6
+ - Support for `startup_timeout` option via `container_options` to detect processes that hang during startup and never become ready.
7
+
3
8
  ## v0.16.0
4
9
 
5
10
  - Renamed `Async::Service::Generic` -\> `Async::Service::GenericService`, added compatibilty alias.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.16'
61
+ version: '0.28'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.16'
68
+ version: '0.28'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: string-format
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  - !ruby/object:Gem::Version
127
127
  version: '0'
128
128
  requirements: []
129
- rubygems_version: 3.6.9
129
+ rubygems_version: 4.0.3
130
130
  specification_version: 4
131
131
  summary: A service layer for Async.
132
132
  test_files: []
metadata.gz.sig CHANGED
Binary file