Skip to content

Inject factory functions#41

Merged
zhulik merged 5 commits intomainfrom
inject-factory-functions
Sep 28, 2025
Merged

Inject factory functions#41
zhulik merged 5 commits intomainfrom
inject-factory-functions

Conversation

@zhulik
Copy link
Owner

@zhulik zhulik commented Sep 28, 2025

Now instead invoking factory services manually with pal.Invoke, you can inject factory functions. They are safe to use from Init() methods as pal can figure out the correct initialization order.
Example:

package main

import (
        "context"
        "log/slog"
        "os"
        "testing"
        "time"

        "github.com/zhulik/pal"
        "github.com/zhulik/pal/inspect"
)

type Heartbeater interface {
        Heartbeat(ctx context.Context)
}

type heartbeater struct {
}

func (h *heartbeater) Init(ctx context.Context) error {
        h.Logger.InfoContext(ctx, "Heartbeater initialized")
        return nil
}

func (h *heartbeater) Heartbeat(ctx context.Context) {
        h.Logger.InfoContext(ctx, "Heartbeat")
}

type mainRunner struct {
        Logger            *slog.Logger
        CreateHeartbeater func(ctx context.Context, count int) (Heartbeater, error) // <-- Injected factory function

        heartbeater Heartbeater
}

func (m *mainRunner) Init(ctx context.Context) error {
        m.Logger.InfoContext(ctx, "MainRunner initialized")

        heartbeater, err := m.CreateHeartbeater(ctx, 0)
        if err != nil {
                return err
        }
        m.heartbeater = heartbeater

        return nil
}

func (m *mainRunner) Run(ctx context.Context) error {
        for {
                select {
                case <-ctx.Done():
                        return ctx.Err()
                case <-time.After(time.Second):
                        m.heartbeater.Heartbeat(ctx)
                }
        }
}

func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
        slog.SetDefault(logger)

        err := pal.New(
                pal.Provide(&mainRunner{}),
                inspect.Provide(),
                pal.ProvideFactory1[Heartbeater](func(_ context.Context, count int) (*heartbeater, error) {
                        return &heartbeater{count: count}, nil
                }),
        ).
                InjectSlog().
                InitTimeout(time.Second).
                HealthCheckTimeout(time.Second).
                ShutdownTimeout(time.Second).
                Run(t.Context())
        if err != nil {
                panic(err)
        }
}

@zhulik zhulik merged commit 01abb84 into main Sep 28, 2025
3 checks passed
@zhulik zhulik deleted the inject-factory-functions branch September 28, 2025 15:05
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.

1 participant