diff --git a/example/go.mod b/example/go.mod index 3a4c547..9e29c22 100644 --- a/example/go.mod +++ b/example/go.mod @@ -1,3 +1,5 @@ module example go 1.22 + +require github.com/lmbek/ggservice v0.0.1 diff --git a/example/go.sum b/example/go.sum new file mode 100644 index 0000000..4142277 --- /dev/null +++ b/example/go.sum @@ -0,0 +1,2 @@ +github.com/lmbek/ggservice v0.0.1 h1:mEilAgiXFsg9vKkO29WpVo18JVa60pVU6AjnNRnP/k8= +github.com/lmbek/ggservice v0.0.1/go.mod h1:WeUwfPy3SOcZV6IH700psgyvIK1ZzYqztnbMW3EEcBk= diff --git a/example/main.go b/example/main.go index 2617dba..5cb1eb2 100644 --- a/example/main.go +++ b/example/main.go @@ -13,9 +13,23 @@ func main() { } func loadService() { - //alternative //s := new_ssg.NewService("SSG Service", 5*time.Second) - service := ggservice.New(&ggservice.Service{Name: "My Service", GracefulShutdownTime: 5 * time.Second}) - err := service.Start(start, run, forcedTimeoutStop) + // creating new service with name and graceful shutdown time duration + service := ggservice.NewService("SSG Service", 5*time.Second) + + // we can use Start, Stop and ForceShutdown on the service + + // since Start is a blocking operation we would want to put Start, Stop or ForceShutdown into a goroutine + // if we want to stop the service ourselves, otherwise we would also just wait for interrupt + go func() { + time.Sleep(1 * time.Second) + // we can also use service.Stop or service.ForceShutdown, but notice service.Start is a blocking call + // we can put service.Start in a go routine and use waitgroups etc... your choice. + //service.Stop() // waits till all operations are done (not waiting for graceful timer) + //service.ForceShutdown() // force shutdown immediately + }() + + // starting the service (please note you can choose to not implement any of these by using nil instead) + err := service.Start(start, run, forceExit) // this is a blocking call if err != nil { log.Fatal(err) } @@ -30,18 +44,12 @@ func start() error { // run loops from the application is started until it is stopped, terminated or ForceShutdown (please use with time.Sleep in between frames) func run() error { fmt.Println("start of work") - - // service will run the rest of the task if graceful shutdown timer is > 1 - time.Sleep(7 * time.Second) - // service will force shutdown if the rest of the task length - // is > 5 (or whatever graceful shutdown timer is set to) - // time.Sleep(8 * time.Second) - + time.Sleep(10 * time.Second) // note: if the graceful timer duration is below amount of work needed to be done, it will forceExit fmt.Println("end of work") return nil } -// forcedStop is being run when the application is trying to force a shutdown (non-gracefully) -func forcedTimeoutStop() { - log.Fatal(errors.New("forced stop: timeout")) +// forceExit is being run when the application is trying to force a shutdown (non-gracefully) +func forceExit() { + log.Fatalln(errors.New("forced stop: timeout")) } diff --git a/service.go b/service.go index 6f9f235..762ed8b 100644 --- a/service.go +++ b/service.go @@ -11,7 +11,7 @@ import ( // IService defines the interface for managing a service with start, stop, and force shutdown capabilities. type IService interface { - Start(startFunc func() error, runFunc func() error, forceExitFunc func()) error + Start(startFunc func() error, runFunc func() error, forceExitFunc func() error) error Stop() ForceShutdown() } @@ -41,7 +41,7 @@ func NewService(name string, gracefulShutdownTime time.Duration) IService { } // Start starts the service with custom start, run, and stop functions. -func (s *Service) Start(startFunc func() error, runFunc func() error, forceExitFunc func()) error { +func (s *Service) Start(startFunc func() error, runFunc func() error, forceExitFunc func() error) error { go s.listenForInterrupt(forceExitFunc) // Listen for interrupt signals // Execute custom start function if provided @@ -79,7 +79,7 @@ func (s *Service) ForceShutdown() { } // listenForInterrupt listens for interrupt signals and triggers shutdown. -func (s *Service) listenForInterrupt(forceExit func()) { +func (s *Service) listenForInterrupt(forceExit func() error) { osSignal := make(chan os.Signal, 1) signal.Notify(osSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) <-osSignal // Block until a signal is received @@ -95,7 +95,7 @@ func (s *Service) listenForInterrupt(forceExit func()) { // Execute custom ForceExit func if forceExit != nil { - forceExit() + _ = forceExit() // ignoring error in interrupt functionality (the error is meant for manual use only) } else { // if forceExitFunc is not implemented by the user, then run ForceShutdown (exits program with log) s.ForceShutdown() diff --git a/service_test.go b/service_test.go index 87749a4..706a05f 100644 --- a/service_test.go +++ b/service_test.go @@ -2,7 +2,7 @@ package ggservice_test import ( "fmt" - "ggservice" + "github.com/lmbek/ggservice" "log" "testing" "time" @@ -21,11 +21,12 @@ func ExampleNewService() { return nil } - ExampleForcedTimeoutStop := func() { - fmt.Println("this runs when service starts") + ExampleForceExit := func() error { + fmt.Println("this runs when service forceExits") + return nil } - err := service.Start(ExampleStart, ExampleRun, ExampleForcedTimeoutStop) + err := service.Start(ExampleStart, ExampleRun, ExampleForceExit) if err != nil { log.Fatal(err) } @@ -44,11 +45,12 @@ func ExampleNew() { return nil } - ExampleForcedTimeoutStop := func() { - fmt.Println("this runs when service starts") + ExampeForceExit := func() error { + fmt.Println("this runs when service forceExits") + return nil } - err := service.Start(ExampleStart, ExampleRun, ExampleForcedTimeoutStop) + err := service.Start(ExampleStart, ExampleRun, ExampeForceExit) if err != nil { log.Fatal(err) }