component

package
v0.0.0-...-89aa834 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2024 License: MIT Imports: 12 Imported by: 14

Documentation

Overview

Package component provides a flexible and extensible component system for building modular applications. It defines interfaces and structures for creating, managing, and controlling the lifecycle of components within an application.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Register

func Register(name string, creator func() Component)

Register makes a component creator available by the provided name. It panics if Register is called twice with the same name or if creator is nil.

func RegisterFuncs

func RegisterFuncs(name string, funcs lifecycle.Funcs)

RegisterFuncs registers a component creator with lifecycle functions.

Types

type BaseComponent

type BaseComponent[T any] struct {
	// contains filtered or unexported fields
}

BaseComponent provides a basic implementation of the Component interface.

Example

Example test to demonstrate usage of the component package

package main

import (
	"context"
	"errors"
	"fmt"
	"log/slog"

	"github.com/gopherd/core/component"
	"github.com/gopherd/core/typing"
)

// mockComponent is a mock implementation of the Component interface for testing
type mockComponent struct {
	component.BaseComponent[mockOptions]
	initCalled     bool
	uninitCalled   bool
	startCalled    bool
	shutdownCalled bool

	initError     bool
	startError    bool
	shutdownError bool
	uninitError   bool
}

type mockOptions struct {
	Value string
}

func (m *mockComponent) Init(ctx context.Context) error {
	m.initCalled = true
	if m.initError {
		return errors.New("mock init error")
	}
	return nil
}

func (m *mockComponent) Uninit(ctx context.Context) error {
	m.uninitCalled = true
	if m.uninitError {
		return errors.New("mock uninit error")
	}
	return nil
}

func (m *mockComponent) Start(ctx context.Context) error {
	m.startCalled = true
	if m.startError {
		return errors.New("mock start error")
	}
	return nil
}

func (m *mockComponent) Shutdown(ctx context.Context) error {
	m.shutdownCalled = true
	if m.shutdownError {
		return errors.New("mock shutdown error")
	}
	return nil
}

// mockContainer is a mock implementation of the Container interface for testing
type mockContainer struct {
	components map[string]component.Component
	logger     *slog.Logger
}

func newMockContainer() *mockContainer {
	return &mockContainer{
		components: make(map[string]component.Component),
		logger:     slog.Default(),
	}
}

func (c *mockContainer) GetComponent(uuid string) component.Component {
	return c.components[uuid]
}

func (c *mockContainer) Logger() *slog.Logger {
	return c.logger
}

func main() {
	// Create a mock component
	mc := &mockComponent{}

	// Setup the component
	container := newMockContainer()
	config := component.Config{
		Name:    "ExampleComponent",
		UUID:    "example-uuid",
		Options: typing.NewRawObject(`{"Value":"example"}`),
	}

	err := mc.Setup(container, &config, false)
	if err != nil {
		fmt.Printf("Failed to setup component: %v\n", err)
		return
	}

	// Use the component
	fmt.Println(mc.String())
	fmt.Println(mc.Options().Value)

}
Output:

ExampleComponent#example-uuid
example

func (*BaseComponent) Init

func (c *BaseComponent) Init(ctx context.Context) error

Init implements the Component Init method.

func (*BaseComponent) Logger

func (c *BaseComponent) Logger() *slog.Logger

Logger implements the Component Logger method.

func (*BaseComponent[T]) Options

func (c *BaseComponent[T]) Options() *T

Options returns a pointer to the component's options.

func (*BaseComponent[T]) Setup

func (c *BaseComponent[T]) Setup(container Container, config *Config, rewrite bool) error

Setup implements the Component Setup method.

func (*BaseComponent) Shutdown

func (c *BaseComponent) Shutdown(ctx context.Context) error

Shutdown implements the Component Shutdown method.

func (*BaseComponent) Start

func (c *BaseComponent) Start(ctx context.Context) error

Start implements the Component Start method.

func (*BaseComponent) String

func (c *BaseComponent) String() string

String implements the fmt.Stringer interface.

func (*BaseComponent) Uninit

func (c *BaseComponent) Uninit(ctx context.Context) error

Uninit implements the Component Uninit method.

type BaseComponentWithRefs

type BaseComponentWithRefs[T, R any] struct {
	BaseComponent[T]
	// contains filtered or unexported fields
}

BaseComponentWithRefs provides a basic implementation of the Component interface with references.

func (*BaseComponentWithRefs) Init

func (c *BaseComponentWithRefs) Init(ctx context.Context) error

Init implements the Component Init method.

func (*BaseComponentWithRefs) Logger

func (c *BaseComponentWithRefs) Logger() *slog.Logger

Logger implements the Component Logger method.

func (*BaseComponentWithRefs[T, R]) Refs

func (c *BaseComponentWithRefs[T, R]) Refs() *R

Refs returns a pointer to the component's references.

func (*BaseComponentWithRefs[T, R]) Setup

func (c *BaseComponentWithRefs[T, R]) Setup(container Container, config *Config, rewrite bool) error

Setup implements the Component Setup method.

func (*BaseComponentWithRefs) Shutdown

func (c *BaseComponentWithRefs) Shutdown(ctx context.Context) error

Shutdown implements the Component Shutdown method.

func (*BaseComponentWithRefs) Start

func (c *BaseComponentWithRefs) Start(ctx context.Context) error

Start implements the Component Start method.

func (*BaseComponentWithRefs) String

func (c *BaseComponentWithRefs) String() string

String implements the fmt.Stringer interface.

func (*BaseComponentWithRefs) Uninit

func (c *BaseComponentWithRefs) Uninit(ctx context.Context) error

Uninit implements the Component Uninit method.

type Component

type Component interface {
	lifecycle.Lifecycle
	fmt.Stringer

	// Setup sets up the component with the given container and configuration.
	// If rewrite is true, the component should rewrite the configuration.
	Setup(c Container, cfg *Config, rewrite bool) error

	// Logger returns the logger instance for the component.
	// Logger must be guranteed to return a non-nil logger instance after Setup is called.
	Logger() *slog.Logger
}

Component defines the interface for a generic logic component.

func Create

func Create(name string) (Component, error)

Create creates a new component by its name.

type Config

type Config struct {
	// Name is the component name. It's required.
	Name string

	// UUID is the unique identifier for the component. It can be empty.
	UUID string `json:",omitempty"`

	// Refs is the references to other components.
	Refs typing.RawObject `json:",omitempty"`

	// Options is the configuration options for the component.
	Options typing.RawObject `json:",omitempty"`

	// TemplateUUID determines if the UUID should be templated.
	// If not set, the default value is determined by the service.
	TemplateUUID *typing.Bool `json:",omitempty"`

	// TemplateRefs determines if the Refs should be templated.
	// If not set, the default value is determined by the service.
	TemplateRefs *typing.Bool `json:",omitempty"`

	// TemplateOptions determines if the Options should be templated.
	// If not set, the default value is determined by the service.
	TemplateOptions *typing.Bool `json:",omitempty"`
}

Config defines the configuration structure for creating a component.

type Container

type Container interface {
	// GetComponent returns a component by its UUID.
	GetComponent(uuid string) Component

	// Logger returns the logger instance for the container.
	Logger() *slog.Logger
}

Container represents a generic container that can hold components.

type Group

type Group struct {
	// contains filtered or unexported fields
}

Group manages a group of components.

Example
package main

import (
	"context"
	"errors"
	"fmt"
	"log/slog"

	"github.com/gopherd/core/component"
)

// mockComponent is a mock implementation of the Component interface for testing
type mockComponent struct {
	component.BaseComponent[mockOptions]
	initCalled     bool
	uninitCalled   bool
	startCalled    bool
	shutdownCalled bool

	initError     bool
	startError    bool
	shutdownError bool
	uninitError   bool
}

type mockOptions struct {
	Value string
}

func (m *mockComponent) Init(ctx context.Context) error {
	m.initCalled = true
	if m.initError {
		return errors.New("mock init error")
	}
	return nil
}

func (m *mockComponent) Uninit(ctx context.Context) error {
	m.uninitCalled = true
	if m.uninitError {
		return errors.New("mock uninit error")
	}
	return nil
}

func (m *mockComponent) Start(ctx context.Context) error {
	m.startCalled = true
	if m.startError {
		return errors.New("mock start error")
	}
	return nil
}

func (m *mockComponent) Shutdown(ctx context.Context) error {
	m.shutdownCalled = true
	if m.shutdownError {
		return errors.New("mock shutdown error")
	}
	return nil
}

// mockContainer is a mock implementation of the Container interface for testing
type mockContainer struct {
	components map[string]component.Component
	logger     *slog.Logger
}

func newMockContainer() *mockContainer {
	return &mockContainer{
		components: make(map[string]component.Component),
		logger:     slog.Default(),
	}
}

func (c *mockContainer) GetComponent(uuid string) component.Component {
	return c.components[uuid]
}

func (c *mockContainer) Logger() *slog.Logger {
	return c.logger
}

func main() {
	// Create a new group
	group := component.NewGroup()

	// Create and add components to the group
	for i := 0; i < 3; i++ {
		mc := &mockComponent{}
		uuid := fmt.Sprintf("example-uuid-%d", i)
		container := newMockContainer()
		_ = mc.Setup(container, &component.Config{Name: fmt.Sprintf("ExampleComponent-%d", i), UUID: uuid}, false)
		group.AddComponent(uuid, mc)
	}

	// Use the group to manage component lifecycle
	ctx := context.Background()
	_ = group.Init(ctx)
	_ = group.Start(ctx)

	// Simulate some work
	fmt.Println("Components are running...")

	// Shutdown and uninitialize
	_ = group.Shutdown(ctx)
	_ = group.Uninit(ctx)

	fmt.Println("All components have been shut down")

}
Output:

Components are running...
All components have been shut down

func NewGroup

func NewGroup() *Group

NewGroup creates a new Group instance.

func (*Group) AddComponent

func (g *Group) AddComponent(uuid string, com Component) Component

AddComponent adds a component to the group. It returns nil if a component with the same UUID already exists.

func (*Group) GetComponent

func (g *Group) GetComponent(uuid string) Component

GetComponent retrieves a component by its UUID.

func (*Group) Init

func (g *Group) Init(ctx context.Context) error

Init initializes all components in the group.

func (*Group) Shutdown

func (g *Group) Shutdown(ctx context.Context) error

Shutdown shuts down all components in reverse order.

func (*Group) Start

func (g *Group) Start(ctx context.Context) error

Start starts all components in the group.

func (*Group) Uninit

func (g *Group) Uninit(ctx context.Context) error

Uninit uninitializes all components in reverse order.

type OptionalReference

type OptionalReference[T any] struct {
	Reference[T]
}

OptionalReference represents an optional reference to another component. If the UUID is empty, the reference is ignored, and Component returns nil.

func OptionalRef

func OptionalRef[T any](uuid string) OptionalReference[T]

OptionalRef creates an optional reference to a component with the given UUID.

func (*OptionalReference[T]) Resolve

func (r *OptionalReference[T]) Resolve(container Container) error

Resolve resolves the reference for the component.

type Reference

type Reference[T any] struct {
	// contains filtered or unexported fields
}

Reference represents a reference to another component.

func Ref

func Ref[T any](uuid string) Reference[T]

Ref creates a reference to a component with the given UUID.

func (Reference[T]) Component

func (r Reference[T]) Component() T

Component returns the referenced component.

func (Reference[T]) MarshalJSON

func (r Reference[T]) MarshalJSON() ([]byte, error)

MarshalJSON marshals the referenced component UUID to JSON.

func (*Reference[T]) Resolve

func (r *Reference[T]) Resolve(container Container) error

Resolve resolves the reference for the component.

func (Reference[T]) UUID

func (r Reference[T]) UUID() string

UUID returns the UUID of the referenced component.

func (*Reference[T]) UnmarshalJSON

func (r *Reference[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals the referenced component UUID from JSON.

type Resolver

type Resolver interface {
	// UUID returns the UUID of the referenced component.
	UUID() string

	// Resolve resolves the reference for the component.
	Resolve(Container) error
}

Resolver resolves a reference for a component.

Jump to

Keyboard shortcuts

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