Getting Started
This guide explains how to get started with async-service to create and run services in Ruby.
Installation
Add the gem to your project:
$ bundle add async-service
Core Concepts
async-service has several core concepts:
- A 
class Async::Service::Genericwhich represents the base class for implementing services. - A 
class Async::Service::Configurationwhich manages service configurations and environments. - A 
class Async::Service::Controllerwhich handles starting, stopping, and managing services. 
Usage
Services are long-running processes that can be managed as a group. Each service extends Async::Service::Generic and implements a setup method that defines how the service runs.
Basic Service
Create a simple service that runs continuously:
#!/usr/bin/env async-service
require 'async/service'
class HelloService < Async::Service::Generic
	def setup(container)
		super
		
		container.run(count: 1, restart: true) do |instance|
			instance.ready!
			
			while true
				puts "Hello World!"
				sleep 1
			end
		end
	end
end
service "hello" do
	service_class HelloService
end
Make the file executable and run it:
$ chmod +x hello_service.rb
$ ./hello_service.rb
Service Configuration
Services can be configured with custom properties:
service "web-server" do
	service_class WebServerService
	port 3000
	host "localhost"
end
In your service implementation, you can access these values through the environment and evaluator:
class WebServerService < Async::Service::Generic
	def setup(container)
		super
		
		container.run(count: 1, restart: true) do |instance|
			# Access the configuration for the service:
			evaluator = self.environment.evaluator
			port = evaluator.port
			host = evaluator.host
			
			puts "Starting web server on #{host}:#{port}"
			instance.ready!
			
			# Your web server implementation here
		end
	end
end
Multiple Services
You can define multiple services in a single configuration file:
#!/usr/bin/env async-service
require 'async/service'
class WebService < Async::Service::Generic
	def setup(container)
		super
		
		container.run(count: 1, restart: true) do |instance|
			instance.ready!
			puts "Web service starting..."
			# Web server implementation
		end
	end
end
class WorkerService < Async::Service::Generic
	def setup(container)
		super
		
		container.run(count: 2, restart: true) do |instance|
			instance.ready!
			puts "Worker #{instance.name} starting..."
			# Background job processing
		end
	end
end
service "web" do
	service_class WebService
	port 3000
	host "localhost"
end
service "worker" do
	service_class WorkerService
end
Programmatic Usage
You can also create and run services programmatically:
require 'async/service'
configuration = Async::Service::Configuration.build do
	service "my-service" do
		service_class MyService
	end
end
Async::Service::Controller.run(configuration)
Accessing Configuration Values
Services have access to their configuration through the environment and evaluator:
class ConfigurableService < Async::Service::Generic
	def setup(container)
		super
		
		container.run(count: 1, restart: true) do |instance|
			# Clone the evaluator for thread safety
			evaluator = self.environment.evaluator
			database_url = evaluator.database_url
			max_connections = evaluator.max_connections
			debug_mode = evaluator.debug_mode
			
			puts "Database URL: #{database_url}"
			puts "Max connections: #{max_connections}"
			puts "Debug mode: #{debug_mode}"
			
			instance.ready!
			
			# Your service implementation using these values
		end
	end
end
service "configurable" do
	service_class ConfigurableService
	database_url "postgresql://localhost/myapp"
	max_connections 10
	debug_mode true
end
The evaluator is a memoized instance of the service's configuration, allowing for efficient access to configuration values throughout the service's lifecycle.