Providers
Some components can be large, stateful, or requiring specific configuration as part of their setup (such as when dealing with third party code). You can use providers to manage and register these components across several distinct lifecycle steps.
You can define your providers as individual source files in system/providers/
, for example:
# system/providers/persistence.rb
Application.register_provider(:database) do
prepare do
require "3rd_party/db"
end
start do
register(:database, 3rdParty::DB.new)
end
end
The provider’s lifecycle steps will not run until the provider is required by another component, is started directly, or when the container finalizes.
This means you can require your container and ask it to start just that one provider:
# system/application/container.rb
class Application < Dry::System::Container
configure do |config|
config.root = Pathname("/my/app")
end
end
Application.start(:database)
# and now `database` becomes available
Application["database"]
Provider lifecycle
The provider lifecycle consists of three steps, each with a distinct purpose:
prepare
- basic setup code, here you can require 3rd party code and perform basic configurationstart
- code that needs to run for a component to be usable at application's runtimestop
- code that needs to run to stop a component, ie close a database connection, clear some artifacts etc.
Here's a simple example:
# system/providers/db.rb
Application.register_provider(:database) do
prepare do
require '3rd_party/db'
register(:database, 3rdParty::DB.configure(ENV['DB_URL']))
end
start do
container[:database].establish_connection
end
stop do
container[:database].close_connection
end
end
Using other providers
You can start one provider as a dependency of another by invoking the provider’s lifecycle directly on the target
container (i.e. your application container):
# system/providers/logger.rb
Application.register_provider(:logger) do
init do
require "logger"
end
start do
register(:logger, Logger.new($stdout))
end
end
# system/providers/db.rb
Application.register_provider(:db) do
start do
target.start :logger
register(DB.new(ENV['DB_URL'], logger: target[:logger]))
end
end