rxd

package module
v0.9.6 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2023 License: Apache-2.0 Imports: 12 Imported by: 0

README

RxDaemon

codecov

A simple (alpha) reactive services daemon

Example Service Template


// Define a service struct if you wish to use receiver methods for your Init, Idle, Run, Stop methods
// Though you only need to implement the methods you want to customize if they need to do something.
type SimpleService struct{}

// Run is where you want the main logic of your service to run
// when things have been initialized and are ready, this runs the heart of your service.
func (s *SimpleService) Run(c *rxd.ServiceContext) rxd.ServiceResponse {

	c.Log.Info("has entered the run state")

	timer := time.NewTimer(5 * time.Second)
	defer timer.Stop()

  // NOTE: For any stage function that has any blocking calls or has to do any waiting.
  // You will ALWAYS want to use the pattern below, 'default' may be used in place
  // of the timer.C case if you dont need an interval timer.
  // But you should ALWAYS watch for a shutdown signal so daemon/manager can shutdown 
  // the services properly and you can have the chance to gracefully stop your service
  // before its killed off or to prevent leaks.
	for {
		select {
		case <-c.ShutdownSignal():
			// ALWAYS watch for shutdown signal
			return rxd.NewResponse(nil, rxd.ExitState)

		case <-timer.C:
			// When 5 seconds has elapsed, log hello, then end the service.
			c.Log.Info("hello")
			return rxd.NewResponse(nil, rxd.StopState)
		}

	}
}

func (s *SimpleService) Init(c *rxd.ServiceContext) rxd.ServiceResponse {
	return rxd.NewResponse(nil, rxd.IdleState)
}

func (s *SimpleService) Idle(c *rxd.ServiceContext) rxd.ServiceResponse {
	return rxd.NewResponse(nil, rxd.RunState)
}

func (s *SimpleService) Stop(c *rxd.ServiceContext) rxd.ServiceResponse {
	return rxd.NewResponse(nil, rxd.ExitState)
}

// SimpleService must meet Service interface or line below errors.
var _ rxd.Service = &SimpleService{}
Example Daemon Entrypoint with Custom Logger
// Custom Logger use a struct that implements Debug, Info, Error to meet the Logging interface.
type MyLogger struct{}

func (ml *MyLogger) Debug(v ...any) {
	fmt.Printf("[DBG] %s", v...)
}

func (ml *MyLogger) Debugf(format string, v ...any) {
	fmt.Printf("[DBG] %s", fmt.Sprintf(format, v...))
}

func (ml *MyLogger) Info(v ...any) {
	fmt.Printf("[INF] %s", v...)
}

func (ml *MyLogger) Infof(format string, v ...any) {
	fmt.Printf("[INF] %s", fmt.Sprintf(format, v...))
}

func (ml *MyLogger) Warn(v ...any) {
	fmt.Printf("[WRN] %s", v...)
}

func (ml *MyLogger) Warnf(format string, v ...any) {
	fmt.Printf("[WRN] %s", v...)
}

func (ml *MyLogger) Error(v ...any) {
	fmt.Printf("[ERR] %s", v...)
}

func (ml *MyLogger) Errorf(format string, v ...any) {
	fmt.Printf("[ERR] %s", fmt.Sprintf(format, v...))
}

// Example entrypoint
func main() {
	// We create an instance of our service
	simpleService := NewSimpleService()
  // RunUntilStoppedPolicy is the default, could alternatively just use rxd.NewServiceOpts()
	svcOpts := rxd.NewServiceOpts(rxd.UsingRunPolicy(rxd.RunUntilStoppedPolicy))
	// We create an instance of our ServiceConfig
	simpleRxdService := rxd.NewService("SimpleService", simpleService, svcOpts)

	// We pass 1 or more potentially long-running services to NewDaemon to run.
	daemon := rxd.NewDaemon(simpleRxdService)

	// since MyLogger meets the Logging interface we can allow the daemon to use it.
	logger := &MyLogger{}
	daemon.SetCustomLogger(logger)

	err := daemon.Start() // Blocks main thread
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	log.Println("successfully stopped daemon")
}

Documentation

Index

Constants

View Source
const (
	InternalServiceStates = "_rxd.states"
)
View Source
const (
	NoFlags = 0
)

Variables

This section is empty.

Functions

func NewDaemon

func NewDaemon(services ...*ServiceContext) *daemon

NewDaemon creates and return an instance of the reactive daemon

func NewServiceOpts

func NewServiceOpts(options ...ServiceOption) *serviceOpts

NewServiceOpts will apply all options in the order given and return the final options back.

Types

type Level

type Level string

Level is a representation of the logging level to be used.

var (
	// Debug to log debug and higher
	Debug Level = "debug"
	// Info to log info and higher
	Info Level = "info"
	// Error to log only error and higher
	Error Level = "error"
)

type LogMessage

type LogMessage struct {
	Message string
	Level   Level
}

func NewLog

func NewLog(message string, level Level) LogMessage

NewLog creates a new instance of a LogMessage from a string and level.

type LogSeverity

type LogSeverity int

LogSeverity is a typed int that represents the severity of the logging levels.

const (
	// LevelAll will show all severity levels
	LevelAll LogSeverity = 0
	// LevelDebug will show all severity levels at Debug and above: Debug, Info, Error
	LevelDebug LogSeverity = 1
	// LevelInfo will show all severity levels at Info and above: Info, Error
	LevelInfo LogSeverity = 2
	// LevelWarn will show all severity levels at Warn and above: Warn, Error
	LevelWarn LogSeverity = 3

	// LevelError will show all severity levels at Error and above: Error
	LevelError LogSeverity = 4

	// LevelOff will not show any logs, logging will be off
	LevelOff LogSeverity = 6
)

type Logger

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

func NewLogger

func NewLogger(logSeverity LogSeverity, flags int) *Logger

NewLogger returns an instance of Logger with Debug, Info and Error loggers. Each logger is configured with sane defaults. Debug output is set with env var "DEBUG"; defaults to io.Discard

func (*Logger) Debug

func (l *Logger) Debug(v ...any)

func (*Logger) Debugf

func (l *Logger) Debugf(format string, v ...any)

func (*Logger) Error

func (l *Logger) Error(v ...any)

func (*Logger) Errorf

func (l *Logger) Errorf(format string, v ...any)

func (*Logger) Info

func (l *Logger) Info(v ...any)

func (*Logger) Infof

func (l *Logger) Infof(format string, v ...any)

func (*Logger) Warn

func (l *Logger) Warn(v ...any)

func (*Logger) Warnf

func (l *Logger) Warnf(format string, v ...any)

type Logging

type Logging interface {
	Debug(v ...any)
	Info(v ...any)
	Warn(v ...any)
	Error(v ...any)

	Debugf(format string, v ...any)
	Infof(format string, v ...any)
	Warnf(format string, v ...any)
	Errorf(format string, v ...any)
}

type RunPolicy

type RunPolicy string

RunPolicy service option type representing the run policy of a given service basically controlling different ways of stopping a service like running only once when it succeeds without an error on Run

const (
	// RunUntilStoppedPolicy will continue to run the service until a StopState is returned at some point
	RunUntilStoppedPolicy RunPolicy = "until_stopped"
	// RetryUntilSuccessPolicy will continue to re-run the service as long fails happen, use for running a service once successfully
	RetryUntilSuccessPolicy RunPolicy = "retry_until_success"
	// RunOncePolicy will only allow the a single Run to take place regardless of success/failure
	RunOncePolicy RunPolicy = "run_once"
)

type ServiceContext

type ServiceContext struct {
	Name string
	Ctx  context.Context
	Log  Logging
	// contains filtered or unexported fields
}

ServiceContext all services will require a config as a *ServiceContext in their service struct. This config contains preconfigured shutdown channel,

func NewService

func NewService(name string, service Service, opts *serviceOpts) *ServiceContext

NewService creates a new service instance given a name and options.

func (*ServiceContext) AddDependentService

func (sc *ServiceContext) AddDependentService(s *ServiceContext, states ...State) error

AddDependentService adds a service that depends on the current service and the states the dependent service is interested in.

func (*ServiceContext) ChangeState

func (sc *ServiceContext) ChangeState() chan State

ChangeState returns the channel the service listens for state changes of the service it depends on defined by UsingServiceNotify option on creation of the ServiceContext.

func (*ServiceContext) IntracomPublish

func (sc *ServiceContext) IntracomPublish(topic string, message []byte)

IntracomPublish will publish the bytes message to the topic, only if there is subscribed interest.

func (*ServiceContext) IntracomSubscribe

func (sc *ServiceContext) IntracomSubscribe(topic string, id string) <-chan []byte

IntracomSubscribe subscribes this service to inter-service communication by its topic name. A channel is returned to receive published messages from another service. Standardized on slice of bytes since it allows us to easily json unmarshal into struct if needed.

func (*ServiceContext) IntracomUnsubscribe

func (sc *ServiceContext) IntracomUnsubscribe(topic string, id string)

IntracomUnsubscribe unsubscribes this service from inter-service communication by its topic name

func (*ServiceContext) ShutdownSignal

func (sc *ServiceContext) ShutdownSignal() <-chan struct{}

ShutdownSignal returns the channel the side implementing the service should use and watch to be notified when the daemon/manager are attempting to shutdown services.

type ServiceOption

type ServiceOption func(*serviceOpts)

ServiceOption are simply using an Option pattern to customize options such as restart policies, timeouts for a given service and how it should run.

func UsingDefaultLogger

func UsingDefaultLogger(severity LogSeverity, flags int) ServiceOption

UsingDefaultLogger applies new logging instance as the logger with a customized log severity level and flags to use.

func UsingLogger

func UsingLogger(logger Logging) ServiceOption

UsingLogger applies a given logger that meets the Logging interface to the ServiceOption instance

func UsingRunPolicy

func UsingRunPolicy(policy RunPolicy) ServiceOption

UsingRunPolicy applies a given policy to the ServiceOption instance

type ServiceResponse

type ServiceResponse struct {
	Error     error
	NextState State
}

ServiceResponse is used as a return response for services to use so the Manager can determine the "next state" based on return and any error that needs to be broadcasted up the logging channel

func NewResponse

func NewResponse(err error, nextState State) ServiceResponse

NewResponse will create a new ServiceResponse given an error and next state.

type State

type State string

State is used to determine the "next state" the service should enter when the current state has completed/errored returned. State should reflect different states that the interface can enter.

const (
	// InitState is in the ServiceResponse to inform manager to move us to the Init state (Initial Default).
	InitState State = "init"
	// IdleState is in the ServiceResponse to inform manager to move us to the Idle state
	IdleState State = "idle"
	// RunState is in the ServiceResponse to inform manager to move us to the Run state
	RunState State = "run"
	// StopState is in the ServiceResponse to inform manager to move us to the Stop state
	StopState State = "stop"
	// ExitState is in the ServiceResponse to inform manager to act as the final response type for Stop.
	ExitState State = "exit"
)

Directories

Path Synopsis
examples
custom_logger command
multi_service command

Jump to

Keyboard shortcuts

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