Skip to content
/ gorman Public

A Goroutine Management and Monitoring library

Notifications You must be signed in to change notification settings

Morebec/gorman

Repository files navigation

Gorman

Gorman is a lightweight Go package for managing and monitoring the execution of goroutines.

It provides two core concepts:

  • Goroutine: Struct wrapping a goroutine and allowing to control its execution using Start/Stop semantics.
  • Manager: Allows controlling multiple Goroutines at once and managing their lifecycle as a group.

The Manager can be helpful to create Goroutine supervisors with a HTTP or CLI implementation to start and stop specific Goroutines.

Installation

To install Gorman, use go get:

go get -u github.com/morebec/gorman

Usage

Manager

To use Gorman, you first need to import it in your Go project:

import "github.com/morebec/gorman"

Next, you can create a new instance of a Manager:

man := gorman.NewManager(gorman.Options{
    Logger: slog.New(tint.Options{
        Level:      slog.LevelDebug,
        TimeFormat: time.TimeOnly,
    }.NewHandler(os.Stdout)),
})

Registering a Goroutine

You can then register a new Goroutine with the manager:

man.Add("MyGoroutine", func(ctx context.Context) error {
    // Goroutine logic goes here
	select {
	case <-ctx.Done():
            return nil
    }
}, gorman.NeverRestart())

The last parameter allows specifying the restart policy of the Goroutine. Out of the box the following Restart Policies are implemented:

  • NeverRestart(): Never restarts the Goroutine once it has stopped.
  • AlwaysRestart(): Always restarts the Goroutine.
  • RestartOnError(): Restart the Goroutine when it stops with an error.
  • RestartPolicyFunc: Allows specifying the restart logic using a function.

See the RestartPolicy interface for more information.

Running the Manager

The Run method, allows running the manager and starting all the goroutines that were added to it:

man.Run(context.Background())

This method will run until the context is canceled, or the Shutdown method is called.

Stopping a Goroutine

To stop a running Goroutine, you can call Stop:

err := manager.Stop("MyGoroutine")
if err != nil {
    // handle error
}

Note: For goroutines to be stoppable they should correctly listen to the ctx.Done() channel. Go routines will also stop whenever they return.

Starting a Goroutine

It is possible to start a goroutine that was previously stopped using the Start method:

err := man.Start(context.Background(), "mygoroutine")

Getting the current state of goroutines

The manager exposes the Status method which returns a slice of GoroutineState which represents the current state of Goroutines.

Goroutine

Goroutines are the building blocks of Gorman and wrap the execution of a go routine to allow start/stop semantics. They can be used independently of the manager to control specific goroutines in isolation.

Creating a Goroutine

g := gorman.NewGoroutine("name", func (ctx context.Context) error {
	// Perform work here.
})

Starting a Goroutine

g.Start(context.Background())

Stopping a Goroutine

The Stop method will cancel the goroutine's context and will wait for it to be stopped.

err := g.Stop()

Alternatively a goroutine can be stopped through its context.

ctx, cancel := context.WithCancel(context.Background())
g.Start(ctx)
cancel()

Listening to Goroutine events

Goroutines have an internal broadcasting system that allows subscribers to listen to Goroutine events such as GoroutineStartedEvent and GoroutineEndedEvent.

Here's an example:

g := gorman.NewGoroutine("mygoroutine", func(ctx context.Context) error {
	// do something
	return nil
})
eventChan := g.Listen()

g.Start(context.Background())

for event := range eventChan {
	switch event.(type) {
	case gorman.GoroutineStartedEvent:
		fmt.Printf("Goroutine %s started\n", g.State.Name)
	case gorman.GoroutineStoppedEvent:
		e := event.(GoroutineStoppedEvent)
		if e.Error != nil {
			fmt.Printf("Goroutine %s stopped with error: %s\n", event.Name, event.Error.Error())
		} else {
			fmt.Printf("Goroutine %s stopped\n", event.Name)
		}
	}
}

g.Unlisten(eventChan)

This mechanism can be useful to react to a goroutine's execution. For instance the Manager uses this mechanism to monitor the lifecycle of the Goroutines.

Note: Every call to the Listen() method will return a new channel. When done with using the channel, it should be released using the Unlisten method.

Examples

For more usage examples, check the examples directory.

License

Gorman is released under the MIT License.

About

A Goroutine Management and Monitoring library

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages