___ ___ ___ ___
/\ \ /\__\ /\ \ /\__\
/::\ \ /:/ / /::\ \ /::| |
/:/\:\ \ /:/ / /:/\:\ \ /:|:| |
/:/ \:\ \ /:/ / /:/ \:\ \ /:/|:|__|__
/:/__/_\:\__\ /:/__/ /:/__/ \:\__\ /:/ |::::\__\
\:\ /\ \/__/ \:\ \ \:\ \ \/__/ \/__/~~/:/ /
\:\ \:\__\ \:\ \ \:\ \ /:/ /
\:\/:/ / \:\ \ \:\ \ /:/ /
\::/ / \:\__\ \:\__\ /:/ /
\/__/ \/__/ \/__/ \/__/
glcm is a Go package designed to manage the complete lifecycle of goroutines, providing a structured approach to starting, stopping, and monitoring services within your Go applications.
- Service Registration: Register multiple services to be managed concurrently.
- Lifecycle Management: Control the startup and shutdown sequences of all registered services.
- Service Control: Individually start, stop, and restart services as needed.
- Hooks Integration: Define pre-run and post-run hooks for services to execute custom logic before starting or after stopping a service.
- Auto-Restart with Backoff: Automatically restart services with optional exponential backoff.
To install the package, run:
go get github.com/achu-1612/glcmHere's how to use glcm in your project:
import "github.com/achu-1612/glcm"ctx := context.Background()
runner := glcm.NewRunner(ctx, glcm.RunnerOptions{})Implement the Service interface for your service. This interface requires the following methods:
Start(Terminator): Defines the startup logic for the service.Status() string: Status returns the status of the service.Name() string: Returns the name of the service.
Example:
type MyService struct{}
func (m *MyService) Start(ctx service.Terminator) {
// Initialization logic here
// Start should be a blocking call.
// On closing of the ctx.TermCh() channel, the method should return.
// example:
for {
<-time.After(time.Second * 2)
select {
case <-ctx.TermCh():
return
default:
log.Println("service is running ", time.Now())
}
}
func (m *MyService) Name() error {
return "MyService"
}
func (m *MyService) Status() string {
return ""
}err := runner.RegisterService(&MyService{}, glcm.ServiceOptions{})
if err != nil {
// Handle error
}// BootUp boots up the runner. This will start all the registered services.
//Note: This is a blocking call. It is to be called after BootUp.
// Only a ShutDown() call will stop the runner.
// Even after all the registered services are stopped, runner would
if err := runner.BootUp(); err != nil {
log.Fatalf("Error while booting up the runner: %v", err)
}// Shutdown shuts down the runner. This will stop all the registered services.
runner.Shutdown()// StopService stops the given list of services.
runner.StopService("MyService1", "MyService2")
// StopAllServices stops all the registered/running services.
runner.StopAllServices()// RestartService restarts the given list of services.
runner.RestartService("MyService1", "MyService2")
// RestartAllServices restarts all the registered/running services.
runner.RestartAllServices()To enable auto-restart with backoff for a service, use the following options during service registration:
Note: The service will be restarted automatically only when service.WithAutoRestart() options is given while service registration and when the service exits automatically not by runner shutting it down.
err := runner.RegisterService(
&MyService{},
glcm.ServiceOptions{
AutoStart: glcm.AutoRestartOptions{
Enabled: true,
Backoff: true,
MaxRetries: 5, // Optional: Set maximum retries
BackOffExponent: 2, // Optional: Set backoff exponent
},
},
)
if err != nil {
// Handle error
}The hook package allows you to define hooks that execute before or after a service starts.
preRunHook := hook.NewHook("PreRunHook", func(args ...interface{}) error {
// Pre-run logic here
return nil
})err := runner.RegisterService(
&MyService{},
glcm.ServiceOptions{
PreHooks: []glcm.Hook{preRunHook},
PostHooks: []glcm.Hook{postRunHook},
},
)
if err != nil {
// Handle error
}glcm supports socket communication for both Windows and Linux platforms. This allows you to send commands to control the lifecycle of services.
On Windows, glcm uses named pipes for socket communication.
On Linux, glcm uses Unix domain sockets for socket communication.
The following messages can be sent to the socket to control the services:
restart <service_name>: restart the specified servicestop <service_name>: stop the specified service.restartAll <service_name>: restart all the services.stopAll <service_name>: stop all the services.list: list all the service and their current status.
echo "restartAll" | socat - UNIX-CONNECT:/tmp/glcm.sock// Example for Linux Unix domain socket communication
socketPath := "/tmp/glcm_socket"
conn, err := net.Dial("unix", socketPath)
if err != nil {
log.Fatalf("Failed to connect to socket: %v", err)
}
defer conn.Close()
_, err = conn.Write([]byte("start MyService"))
if err != nil {
log.Fatalf("Failed to send message: %v", err)
}Contributions are welcome! Please submit issues and pull requests for any improvements or bug fixes.
This project is licensed under the MIT License.
- Support for Job with scheduling.
- Support for timeout for go-routine shutdowns (if possible).
- Better error handling for the pre and post hooks for service.
- Service dependency.