Procyon|Docs
ComponentsLifecycle

Processors

Apply cross-cutting behavior before or after component initialization.

Processors wrap initialization for cross-cutting behavior. Use them for observability, validation, wrapping, or framework-level extension points.

logging_processor.go
type BeforeInitProcessor interface {
	// ProcessBeforeInit runs before the component's Init method.
	ProcessBeforeInit(ctx context.Context, name string, instance any) (any, error)
}

type LoggingInitProcessor struct{}

func (LoggingInitProcessor) ProcessBeforeInit(
	ctx context.Context,
	name string,
	instance any,
) (any, error) {
	log.Printf("initializing %s", name)
	return instance, nil
}

An after-init processor runs after the component has initialized.

after_processor.go
type AfterInitProcessor interface {
	// ProcessAfterInit runs after construction and Init have completed.
	ProcessAfterInit(ctx context.Context, name string, instance any) (any, error)
}

type ReadyProcessor struct{}

func (ReadyProcessor) ProcessAfterInit(
	ctx context.Context,
	name string,
	instance any,
) (any, error) {
	log.Printf("%s initialized", name)
	return instance, nil
}

Both processors receive the component name and instance. They can validate, wrap, or replace the instance by returning a different value. Returning an error fails startup.

Processor guidance

  • Use processors for cross-cutting behavior.
  • Keep component-specific setup inside the component's Init method.
  • Return the instance you want the container to continue using.
  • Return an error when processing should fail startup.

On this page