Search documentation

Find a page in the Andurel docs.

Dependency Injection

Andurel applications use Fx for dependency injection and process lifecycle. Framework packages expose ordinary constructors; Fx belongs to the generated application in cmd/app, cmd/queue, and cmd/ssr.

Composition roots

Each process builds its own graph. Load validated environment before Fx, then provide only the collaborators that process should own:

 1if err := config.LoadEnvironment(); err != nil {
 2    fmt.Fprintln(os.Stderr, err)
 3    os.Exit(1)
 4}
 5
 6app := fx.New(
 7    fx.Provide(func() context.Context { return ctx }),
 8    config.Module,
 9    databaseModule,
10    queueInsertModule,
11    models.Module,
12    controllers.Module,
13    cookies.Module,
14    router.Module,
15    fx.Invoke(startServer),
16)

Constructors return concrete types or small interfaces (storage.Connection, storage.InsertQueue, *inertia.Renderer, *kiks.Jar). Do not hide dependencies in Echo request context.

Publish the pool as both the interface and the concrete type when lifecycle needs Close:

1var databaseModule = fx.Module(
2    "database",
3    fx.Provide(fx.Annotate(
4        newDatabase,
5        fx.As(new(storage.Connection)),
6        fx.As(fx.Self()),
7    )),
8)

Application packages register focused modules. Generated models look like:

1var Module = fx.Module(
2    "models",
3    fx.Provide(
4        NewUsers,
5        NewTokens,
6        NewProducts,
7    ),
8)

Lifecycle

Register start/stop hooks for resources that must clean up: database pools, queue processors, SSR runtimes, and HTTP servers. A failed ping or constructor error should prevent process start.

1lc.Append(fx.Hook{
2    OnStart: func(ctx context.Context) error {
3        return db.Health(ctx)
4    },
5    OnStop: func(ctx context.Context) error {
6        return db.Close()
7    },
8})

Web needs HTTP and queue insertion. Queue needs a River processor and workers, but not the Echo server. Keep provider sets distinct so a process cannot accidentally acquire a capability it should not own.

Replacing implementations

Prefer the smallest public interface at the composition root. Tests can provide fake email senders or in-memory collaborators without rewriting controllers. Package updates should not silently introduce new environment contracts; environment mapping stays in application config/.

See Configuration, Request Lifecycle, and Framework Packages.