Skip to content

Commit c7597d9

Browse files
committed
Fix null services.
1 parent 1715f61 commit c7597d9

File tree

8 files changed

+122
-37
lines changed

8 files changed

+122
-37
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Async
2+
module Service
3+
module GoodInterface
4+
def good_method
5+
:good
6+
end
7+
end
8+
end
9+
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
require 'async/service/generic'
2+
3+
module Async
4+
module Service
5+
class SleepService < Async::Service::Generic
6+
def setup(container)
7+
super
8+
9+
container.run(count: 1, restart: true) do |instance|
10+
# Use log level:
11+
Console.logger.level = @environment.evaluator.log_level
12+
13+
if container.statistics.failed?
14+
Console.debug(self, "Child process restarted #{container.statistics.restarts} times.")
15+
else
16+
Console.debug(self, "Child process started.")
17+
end
18+
19+
instance.ready!
20+
21+
while true
22+
sleep 1
23+
24+
Console.debug(self, "Work")
25+
26+
if rand < 0.1
27+
Console.debug(self, "Should exit...")
28+
sleep 0.5
29+
exit(1)
30+
end
31+
end
32+
end
33+
end
34+
end
35+
end
36+
end

lib/async/service/configuration.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ def services(implementing: nil)
5151
return to_enum(:services, implementing: implementing) unless block_given?
5252

5353
@environments.each do |environment|
54-
next if implementing and environment.implements?(implementing)
55-
56-
yield Generic.wrap(environment)
54+
if implementing.nil? or environment.implements?(implementing)
55+
if service = Generic.wrap(environment)
56+
yield service
57+
end
58+
end
5759
end
5860
end
5961

lib/async/service/generic.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ module Service
1212
class Generic
1313
# Convert the given environment into a service if possible.
1414
# @parameter environment [Build::Environment] The environment to use to construct the service.
15+
# @returns [Generic | Nil] The constructed service if the environment specifies a service class.
1516
def self.wrap(environment)
1617
evaluator = environment.evaluator
1718

18-
if service_class = evaluator.service_class || self
19-
return service_class.new(environment, evaluator)
19+
if evaluator.key?(:service_class)
20+
if service_class = evaluator.service_class
21+
return service_class.new(environment, evaluator)
22+
end
2023
end
2124
end
2225

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env async-service
2+
# frozen_string_literal: trueb
3+
4+
# Released under the MIT License.
5+
# Copyright, 2025, by Samuel Williams.
6+
7+
require "async/service/good_interface"
8+
require "async/service/sleep_service"
9+
10+
# A service without a service class, e.g. a no-op.
11+
service "good-service" do
12+
include Async::Service::GoodInterface
13+
14+
service_class Async::Service::SleepService
15+
end
16+
17+
service "not-so-good-service" do
18+
service_class Async::Service::SleepService
19+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env async-service
2+
# frozen_string_literal: trueb
3+
4+
# Released under the MIT License.
5+
# Copyright, 2025, by Samuel Williams.
6+
7+
# A service without a service class, e.g. a no-op.
8+
service "null" do
9+
end

test/async/service/.configurations/sleep.rb

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,15 @@
88
log_level :info
99
end
1010

11-
# A test service:
12-
class SleepService < Async::Service::Generic
13-
def setup(container)
14-
super
15-
16-
container.run(count: 1, restart: true) do |instance|
17-
# Use log level:
18-
Console.logger.level = @environment.evaluator.log_level
19-
20-
if container.statistics.failed?
21-
Console.debug(self, "Child process restarted #{container.statistics.restarts} times.")
22-
else
23-
Console.debug(self, "Child process started.")
24-
end
25-
26-
instance.ready!
27-
28-
while true
29-
sleep 1
30-
31-
Console.debug(self, "Work")
32-
33-
if rand < 0.1
34-
Console.debug(self, "Should exit...")
35-
sleep 0.5
36-
exit(1)
37-
end
38-
end
39-
end
40-
end
41-
end
11+
require "async/service/sleep_service"
4212

4313
service "sleep" do
4414
include LogLevel
4515

4616
authority {self.name}
4717
middleware {Object.new}
4818

49-
service_class SleepService
19+
service_class Async::Service::SleepService
5020
end
5121

5222
# A 2nd service:

test/async/service/configuration.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Copyright, 2024, by Samuel Williams.
55

66
require 'async/service/configuration'
7+
require "async/service/good_interface"
78

89
describe Async::Service::Configuration do
910
with '.build' do
@@ -29,6 +30,42 @@
2930
end
3031
end
3132

33+
with "null serice configuration file" do
34+
let(:configuration_path) {File.join(__dir__, '.configurations', 'null.rb')}
35+
36+
let(:configuration) do
37+
subject.new.tap do |configuration|
38+
configuration.load_file(configuration_path)
39+
end
40+
end
41+
42+
it 'can load configuration' do
43+
expect(configuration).not.to be(:empty?)
44+
45+
environment = configuration.environments.first
46+
evaluator = environment.evaluator
47+
expect(evaluator.name).to be == 'null'
48+
49+
expect(configuration.services.to_a).to be(:empty?)
50+
end
51+
end
52+
53+
with "implementing service configuration file" do
54+
let(:configuration_path) {File.join(__dir__, '.configurations', 'implementing.rb')}
55+
56+
let(:configuration) do
57+
subject.new.tap do |configuration|
58+
configuration.load_file(configuration_path)
59+
end
60+
end
61+
62+
it "can select services by implementing module" do
63+
expect(configuration).not.to be(:empty?)
64+
65+
expect(configuration.services(implementing: Async::Service::GoodInterface).to_a).not.to be(:empty?)
66+
end
67+
end
68+
3269
with 'sleep service configuration file' do
3370
let(:configuration_path) {File.join(__dir__, '.configurations', 'sleep.rb')}
3471
let(:configuration_root) {File.join(File.realpath(__dir__), '.configurations')}

0 commit comments

Comments
 (0)