gobs

package module
v1.6.2 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2024 License: MIT Imports: 14 Imported by: 20

README

Go Bootstrap (GoBs)

Golang dependencies injection framework to manage life-cycle and scope of instances of an application at runtime.

Documentation website at gobs.xarest.com

Code convention

All components have their own dependencies and life-cycle

  • Initialization
  • Setup/Configuration
  • Start/Run
  • Stop

If you want to add this life-cycle setting for a instances, please implement gobs.IServiceInit

type D struct {
	B *B
	C *C
}

var _ gobs.IServiceInit = (*D)(nil)

func (d *SD) Init(ctx context.Context) (*gobs.ServiceLifeCycle, error) {
	return &gobs.ServiceLifeCycle{
		Deps: gobs.Dependencies{new(B), new(C)},
		common.StatusSetup: true,
	}, nil
}

var _ gobs.IServiceSetup = (*D)(nil)

func (d *D) Setup(ctx context.Context, deps gobs.Dependencies) error {
	if err := deps.Assign(&s.s2, &s.s3); err != nil {
		fmt.Println("Failed to assign dependencies", err)
		return err
	}
	return nil
}

then put this instance to the main thread at init step. All other components required this instance will find this instance with the same manner.

ctx := context.BackGround()
sm := gobs.NewBootstrap()
bs.AddDefault(&D{})
bs.StartBootstrap(ctx)

With dependencies:

  • B -> A
  • C -> A, B
  • D -> B, C

Output log will be

Service test_test.D is added with status Uninitialized
Service test_test.B is added with status Uninitialized
Service test_test.C is added with status Uninitialized
Service test_test.A is added with status Uninitialized
EXECUTE Init WITH 4 SERVICES
Service test_test.A Init successfully
Service test_test.B Init successfully
Service test_test.C Init successfully
Service test_test.D Init successfully
EXECUTE Setup WITH 4 SERVICES
Service test_test.A Setup successfully
Service test_test.B Setup successfully
Service test_test.C Setup successfully
Service test_test.D Setup successfully
EXECUTE Start WITH 4 SERVICES
Service test_test.A Start successfully
Service test_test.B Start successfully
Service test_test.C Start successfully
Service test_test.D Start successfully
EXECUTE Stop WITH 4 SERVICES
Service test_test.D Stop successfully
Service test_test.C Stop successfully
Service test_test.B Stop successfully
Service test_test.A Stop successfully

Documentation

Index

Constants

View Source
const DEFAULT_MAX_CONCURRENT = -1

Variables

View Source
var DefaultConfig = Config{
	NumOfConcurrencies: DEFAULT_MAX_CONCURRENT,
}

Functions

func GetService added in v1.5.6

func GetService[T IService](bs *Bootstrap, service T, key string) (*T, bool)

GetService returns the service instance with the provided original instance or key. If the service is not found, it returns nil. Key or instance can be nil or empty but not both. If both are provided, the key will be preferred.

Example:

a := bs.GetService(nil, "abc") // Return instance of service which has key "abc"
a := bs.GetService(&A{}, "") // Return instance of service type A which has default key which is path of struct A

Types

type Bootstrap

type Bootstrap struct {
	*logger.Logger
	// contains filtered or unexported fields
}

func NewBootstrap

func NewBootstrap(configs ...Config) *Bootstrap

NewBootstrap creates a new Bootstrap instance using the provided configurations. If no configuration options are passed, it applies the DefaultConfig

func (*Bootstrap) Add

func (bs *Bootstrap) Add(s IService, status common.ServiceStatus, key string) error

Add method is used to add a service instance to the bootstrap. The service instance must implement IService interface. The status of the service instance can be any value from common.ServiceStatus. It is helpful but not recommend to setup service instance before adding to the bootstrap.

func (*Bootstrap) AddDefault

func (bs *Bootstrap) AddDefault(s IService, args ...string) error

AddDefault is wrapper for Add method with default key and status of the service instance. If key is not provided, it will use the default key which is the path of the service instance. If the service is already added, no duplicate instances for a key are allowed. If the service instance is added with no key and no path (nearly impossible), it will return an error

Example:

bs.AddDefault(new(A)) // Add service instance A with default key which is path of struct A
bs.AddDefault(new(A), "abc") // Add another service instance A with key "abc".

func (*Bootstrap) AddMany added in v1.5.6

func (bs *Bootstrap) AddMany(services ...IService) error

func (*Bootstrap) AddOrPanic

func (bs *Bootstrap) AddOrPanic(s IService, args ...string)

Same with AddDefault but panic if error

func (*Bootstrap) Deinit

func (bs *Bootstrap) Deinit(ctx context.Context)

func (*Bootstrap) Init

func (bs *Bootstrap) Init(ctx context.Context) error

Init method is used to initialize all services in the bootstrap. It must be called before Setup to build dependencies between services. All Init(...) method of services implemented IService interface will be called. Those methods in services will be called in sequence.

func (*Bootstrap) Interrupt

func (bs *Bootstrap) Interrupt(ctx context.Context, reason int)

Interrupt method is used to notify all services to stopo their processes. If a service are waiting for other services to finish, it will be interrupted and stop waiting. If a service are running, it will continute to run until it finishes.

For example: router are waiting for success of database connection, if interrupt is called, router will stop waiting for database connection and return without setting up. if router are running, it will continue to serve requests until OnStop(...) was called to safely shutdown router.

func (*Bootstrap) Setup

func (bs *Bootstrap) Setup(ctx context.Context) error

Setup method is used to setup all services in the bootstrap. It must be called before Start(...) method. Results of setup process (internnally) will be used in Start(...) method. Make sure that the Init(...) method is fisnished before calling this method. Otherwise, it will interrupt the Init(...) process and return an error as Init(...) method is not finished.

func (*Bootstrap) Start

func (bs *Bootstrap) Start(ctx context.Context) error

Start method is used to start all services in the bootstrap. It must be called after Setup(...) method. Results of setup process (internnally) will be used in Start(...) method. Make sure that the Setup(...) method is fisnished before calling this method. Otherwise, it will interrupt the Setup(...) process and return an error as Setup(...) method is not finished. If service instances use Start() method as container for holding pending states that OnStart function cannot return, it won't be marked as started. If you set other services depended on pending services, make sure that the pending service has it own goroutine to handle the pending states and OnStart function must return. It's not recommended to use Start() method for this purpose.

func (*Bootstrap) StartBootstrap

func (bs *Bootstrap) StartBootstrap(ctx context.Context, signals ...os.Signal)

func (*Bootstrap) Stop

func (bs *Bootstrap) Stop(ctx context.Context) error

Stop method is used to stop all services which have been setup successfully. This method will try to interrupt all pending states of services in Start(...) method and wait for them to finish. Before invoking OnStop method. Stop method is the must-have method to call before the application is terminated. Its flows are inverted of Setup(...) method. If service B depends on services A, service A will be stopped after service B is stopped.

type Config

type Config struct {
	NumOfConcurrencies int
	Logger             logger.LogFnc
	EnableLogDetail    bool
}

type CustomService

type CustomService struct {
	Service  IService
	Name     string
	Instance IService
}

type Dependencies

type Dependencies []IService

func (Dependencies) Assign

func (d Dependencies) Assign(pTargets ...IService) error

type IService

type IService any

type IServiceInit added in v1.5.6

type IServiceInit interface {
	// Entry point to connect service intances with the others. This method will be called at the beginning of the bootstrap process
	// to build up the dependencies between services. This method will setup `s *Service` lifecycle.
	//
	// Example:
	//
	// func (d *D) Init(ctx context.Context, s *gobs.Service) error {
	// 	s.Deps = []gobs.IService{&B{}, &C{}} // Define dependencies here
	// 	s.OnSetup = func(ctx context.Context, deps []gobs.IService, extraDeps []gobs.CustomService) error {
	// 		// After B & C finish setting up, this callback will be called
	// 		d.B = deps[0].(*B)
	// 		d.C = deps[1].(*C)
	// 		// Other custom setup/configration go here
	// 		return nil
	// 	}
	// 	s.AsyncMode[common.StatusSetup] = true // This line will make OnSetup method be called in concurrent context without blocking others.
	// 	return nil
	// }
	Init(ctx context.Context) (*ServiceLifeCycle, error)
}

type IServiceSetup

type IServiceSetup interface {
	Setup(ctx context.Context, deps ...IService) error
}

Without configuration of OnSetup at Init(...), this method will be called when main process invokes bootstrap.Setup(...).

type IServiceStart

type IServiceStart interface {
	Start(ctx context.Context) error
}

Start method will be called when the main context invokes the bootstrap.Start(...) method and OnStart method is not configured at Init(...).

type IServiceStartServer added in v1.6.1

type IServiceStartServer interface {
	StartServer(ctx context.Context, onReady func(err error)) error
}

type IServiceStop

type IServiceStop interface {
	Stop(ctx context.Context) error
}

Stop method will be called when the main context invokes the bootstrap.Stop(...) method and OnStop method is not configured at Init(...).

type Service

type Service struct {
	ServiceLifeCycle
	*logger.Logger
	// contains filtered or unexported fields
}

func NewService

func NewService(s any, name string, status common.ServiceStatus, log *logger.Logger) *Service

func (*Service) DependOn

func (sb *Service) DependOn(ss common.ServiceStatus) []types.ITask

func (*Service) Followers

func (sb *Service) Followers(ss common.ServiceStatus) []types.ITask

func (*Service) IsRunAsync

func (sb *Service) IsRunAsync(ss common.ServiceStatus) bool

func (*Service) Name

func (sb *Service) Name() string

func (*Service) Run

func (sb *Service) Run(ctx context.Context, ss common.ServiceStatus) (err error)

func (*Service) UpdateDependencies

func (sb *Service) UpdateDependencies(dep *Service)

type ServiceLifeCycle

type ServiceLifeCycle struct {
	OnInterrupt func(errno int)

	// deprecated: Define func () Setup(ctx context.Context, deps Dependencies) error instead of OnSetup.
	// OnSetup is a callback function that will be called when the main context invokes the bootstrap.Setup(...) method.
	// This method is used to assign the dependencies instances which has setup successfully from gobs to the service instance.
	// The `deps` parameter is a list of dependencies that the service instance depends on. The `extraDeps` parameter is a list of
	// custom dependencies in case service don't share dependencies with the others.
	AfterInit func(ctx context.Context, deps ...IService) error

	// Deps is a list of dependencies that the service instance depends on. This list is just a reference to the type struct.
	// Gobs will automatically look up the existing instances or create new instances based on the type struct.
	// Then set dependencies to the service instance after Init(...) method returns nil.
	Deps Dependencies

	// ExtraDeps is a list of custom dependencies that the service instance depends on.
	// It provides more information about the instance that the service instance depends on.
	//
	// Example:
	//
	// func (d *D) Init(ctx context.Context, s *gobs.Service) error {
	// 	s.ExtraDeps = []gobs.CustomService{
	// 		{&B{}, "", instanceB}, // D depends on instanceB, type struct B{} with key is default
	// 		{&C{}, "C1", nil}, // D depends on an instance C which has key is C1 in gobs
	// 	}
	// }
	ExtraDeps []CustomService

	// AsyncMode is a map of service status and boolean value. If the value is true, the service instance will be run in parallel goroutine context.
	// Otherwise, the service instance will be run in sequential context.
	AsyncMode map[common.ServiceStatus]bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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