Skip to content

release: config-first bootstrap (0.25.0)#70

Merged
tgiachi merged 11 commits into
mainfrom
develop
Jul 6, 2026
Merged

release: config-first bootstrap (0.25.0)#70
tgiachi merged 11 commits into
mainfrom
develop

Conversation

@tgiachi

@tgiachi tgiachi commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes develop to main:

  • Config-first bootstrap (PR feat(config): config-first bootstrap with eager section binding #69): standalone DI-free SquidStdConfig loaded eagerly, sections bind at registration, OnConfigLoaded hooks apply once, no startup Loads, explicit reload via IConfigManagerService.Load(), four documented configuration levels, explicit-config parameters on 11 registrations, SquidStdOptions.Logger, RegisterLuaEngine.

Behavior notes (0.x minor)

  • Config file read at Create, written (when missing) at StartAsync.
  • Sections resolvable immediately after registration.

Test plan

tgiachi added 11 commits July 6, 2026 13:51
DI-free eager YAML loader with bind-on-demand cached sections, env
substitution at bind time, section tracking for Compose/Save, and an
explicit Reload. First step of the config-first bootstrap refactor.
…gisterConfigSection

When a SquidStdConfig is present in the container the section binds
immediately at registration time; a pre-registered config instance skips
the section entirely (explicit configuration wins). The legacy deferred
registry remains as fallback until the bootstrap swap completes.
The bootstrap builds (or receives) a SquidStdConfig eagerly; sections bind
at registration, OnConfigLoaded hooks apply once before the logger is
configured, the default file is written at StartAsync, and ConfigManagerService
becomes a thin adapter whose Load() is an explicit reload that rebinds sections
and re-fires the hooks. The double startup Load and its Replace-clobbering are
gone. SquidStdOptions.Logger provides code-only logger configuration.
Return types of Create(SquidStdConfig, SquidStdOptions[, IContainer])
overloads changed from ISquidStdBootstrap to SquidStdBootstrap for
consistency with the four sibling Create overloads.

Added StartAsync remarks documenting config file persistence: "When the
configuration file does not exist it is written after the configuration
hooks have run, so the file reflects the effective startup configuration."

Added RegisterConfigServices(string, string) remarks warning about fresh
instance replacement: "Registers a fresh SquidStdConfig: do not call this
on a container that already has one (the previous instance and its tracked
sections would be replaced)."
RegisterEventLoop, RegisterSchedulerServices, RegisterTimerWheelService,
RegisterJobSystemService, RegisterMetricsCollectionService,
RegisterSecretServices and RegisterHealthChecksService accept an optional
config instance that bypasses the YAML section entirely.
… and storage

AddWorkers, AddWorkerManager and AddConsoleCommands accept an optional
config instance; AddFileStorage is standardized on the same pattern
(eager section bind, no eager default Keep). An explicit timer wheel
pump config now survives the worker manager's auto-registration thanks
to the section guard.
…onfig-first

RegisterConfigSection's containerless fallback now registers defaults
directly, the ConfigRegistrationData registry is removed, and the
configuration guide, bootstrap lifecycle and scheduler docs describe the
eager config-first flow with its four configuration levels.
One call registers the LuaEngineConfig instance and the Lua script
engine service, replacing the manual RegisterInstance plus
RegisterStdService pair. Sample and docs updated.
…ontract

Load() no longer claims to create the file, ConfigureLogging() no longer
claims to load, the reload section states that held references stay
stale until re-resolved, the env-substitution promise is scoped to
SquidStd built-in sections, and a test fixture moves inside its test
class per the one-type-per-file convention.
feat(config): config-first bootstrap with eager section binding

[Fact]
public void RegisterLuaEngine_NullConfig_Throws()
=> Assert.Throws<ArgumentNullException>(() => new Container().RegisterLuaEngine(null!));
{
var fileName = Path.HasExtension(configName) ? configName : $"{configName}.yaml";

return Path.Combine(configDirectory, fileName);
public void RegisterConfigSection_WithSquidStdConfig_BindsImmediately()
{
using var root = new TempDirectory();
File.WriteAllText(Path.Combine(root.Path, "app.yaml"), "eager:\n Name: fromfile\n");
public void RegisterConfigSection_ExplicitInstanceAlreadyRegistered_IsSkipped()
{
using var root = new TempDirectory();
File.WriteAllText(Path.Combine(root.Path, "app.yaml"), "eager:\n Name: fromfile\n");

private static SquidStdConfig CreateWithYaml(TempDirectory root, string yaml)
{
File.WriteAllText(Path.Combine(root.Path, "app.yaml"), yaml);
@tgiachi
tgiachi merged commit 2dd43b1 into main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants