integration

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package integration adapts caller-owned startup and shutdown hooks into the service lifecycle without owning their implementations or providers.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrInvalidConfig = errors.New("invalid service integration configuration")

ErrInvalidConfig identifies invalid integration configuration.

Functions

func New

func New(name string, hooks Hooks, options ...Option) (service.Component, error)

New adapts hooks into one ordered service component. A hook error is returned unchanged for errors.Is and errors.As policy and is not logged automatically.

Example
package main

import (
	"context"
	"fmt"

	"github.com/faustbrian/go-service/integration"
)

func main() {
	component, err := integration.New("configuration", integration.Hooks{
		Start: func(context.Context) error {
			fmt.Println("load and validate configuration")

			return nil
		},
	})
	if err != nil {
		panic(err)
	}
	if err := component.Start(context.Background()); err != nil {
		panic(err)
	}
}
Output:
load and validate configuration
Example (QueueAndScheduler)
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/faustbrian/go-service"
	"github.com/faustbrian/go-service/integration"
)

func main() {
	queue, err := integration.New("queue", integration.Hooks{
		Start: func(context.Context) error {
			fmt.Println("start queue")

			return nil
		},
		Stop: func(context.Context) error {
			fmt.Println("release queue")

			return nil
		},
	})
	if err != nil {
		panic(err)
	}
	scheduler, err := integration.New("scheduler", integration.Hooks{
		Start: func(context.Context) error {
			fmt.Println("start scheduler")

			return nil
		},
		Stop: func(context.Context) error {
			fmt.Println("drain scheduler")

			return nil
		},
	})
	if err != nil {
		panic(err)
	}
	runtime, err := service.New(service.Config{
		Components: []service.Component{queue, scheduler},
	})
	if err != nil {
		panic(err)
	}
	if err := runtime.Start(context.Background()); err != nil {
		panic(err)
	}
	if err := runtime.Go("scheduler", func(ctx context.Context) error {
		<-ctx.Done()

		return nil
	}); err != nil {
		panic(err)
	}
	shutdownContext, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := runtime.Shutdown(shutdownContext); err != nil {
		panic(err)
	}
}
Output:
start queue
start scheduler
drain scheduler
release queue

Types

type ConfigError

type ConfigError struct {
	// Field identifies the rejected configuration path.
	Field string
	// Reason describes why Field was rejected.
	Reason string
}

ConfigError identifies one invalid integration field.

func (*ConfigError) Error

func (err *ConfigError) Error() string

Error implements error.

func (*ConfigError) Unwrap

func (err *ConfigError) Unwrap() error

Unwrap makes ConfigError inspectable with errors.Is.

type Hook

type Hook func(context.Context) error

Hook is caller-owned lifecycle work.

type Hooks

type Hooks struct {
	// CloseAdmission synchronously stops new work before accepted work drains.
	// It must be idempotent and return promptly. Nil is a valid no-op.
	CloseAdmission func() error
	// Start performs caller-owned startup work. Nil is a valid no-op.
	Start Hook
	// Stop reverses a successful Start. Nil is a valid no-op.
	Stop Hook
}

Hooks contains optional caller-owned startup and shutdown functions.

type Option

type Option func(*config) error

Option configures an integration component.

func WithSlog

func WithSlog(logger *slog.Logger, attributes ...slog.Attr) Option

WithSlog reports hook lifecycle status through a caller-owned logger. The logger handler is never closed, replaced, or otherwise owned by this package.

Example
package main

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

	"github.com/faustbrian/go-service/integration"
)

func main() {
	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		ReplaceAttr: func(_ []string, attribute slog.Attr) slog.Attr {
			if attribute.Key == slog.TimeKey {
				return slog.Attr{}
			}

			return attribute
		},
	}))
	component, err := integration.New(
		"telemetry",
		integration.Hooks{
			Start: func(context.Context) error {
				fmt.Println("register caller-owned provider")

				return nil
			},
		},
		integration.WithSlog(logger, slog.Duration("timeout", time.Second)),
	)
	if err != nil {
		panic(err)
	}
	if err := component.Start(context.Background()); err != nil {
		panic(err)
	}
}
Output:
level=INFO msg="integration starting" component=telemetry timeout=1s
register caller-owned provider
level=INFO msg="integration started" component=telemetry timeout=1s

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL