srvc

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2025 License: Apache-2.0 Imports: 7 Imported by: 3

README

Go Reference codecov main

Simple, Safe, and Modular Service Runner

srvc library provides a simple but powerful interface with zero external dependencies for running service modules.

Use Case

Normally Go services are composed of multiple "modules" which each run in their own goroutine such as http server, signal listener, kafka consumer, ticker, etc. These modules should remain alive throughout the lifecycle of the whole service, and if one goes down, graceful exit should be executed to avoid "zombie" services. srvc takes care of all this via a simple module interface.

List of ready made modules can be found under github.com/go-srvc/mods

Usage

Main package
package main

import (
	"fmt"
	"net/http"

	"github.com/go-srvc/mods/httpmod"
	"github.com/go-srvc/mods/logmod"
	"github.com/go-srvc/mods/metermod"
	"github.com/go-srvc/mods/sigmod"
	"github.com/go-srvc/mods/sqlxmod"
	"github.com/go-srvc/mods/tracemod"
	"github.com/go-srvc/srvc"
)

func main() {
	db := sqlxmod.New()
	srvc.RunAndExit(
		logmod.New(),
		sigmod.New(),
		tracemod.New(),
		metermod.New(),
		db,
		httpmod.New(
			httpmod.WithAddr(":8080"),
			httpmod.WithHandler(handler(db)),
		),
	)
}

func handler(db *sqlxmod.DB) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if err := db.DB().PingContext(r.Context()); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		fmt.Fprint(w, "OK")
	})
}
Implementing custom modules
package main

import "github.com/go-srvc/srvc"

func main() {
	srvc.RunAndExit(&MyMod{})
}

type MyMod struct {
	done chan struct{}
}

func (m *MyMod) Init() error {
	m.done = make(chan struct{})
	return nil
}

// Run should block until the module is stopped.
// If you don't have a blocking operation, you can use done channel to block.
func (m *MyMod) Run() error {
	<-m.done
	return nil
}

func (m *MyMod) Stop() error {
	defer close(m.done)
	return nil
}

func (m *MyMod) ID() string { return "MyMod" }

Acknowledgements

This library is something I have found myself writing over and over again in every project I been part of. One of the iterations can be found under https://github.com/elisasre/go-common.

Documentation

Overview

Package srvc provides simple but powerful Run functionality on top of Module abstraction. Ready made modules can be found under: github.com/go-srvc/mods.

Index

Constants

View Source
const ErrModulePanic = ErrStr("module recovered from panic")

Variables

View Source
var JoinErrors = errors.Join

JoinErrors allows overwriting the default errors.JoinErrors function used by srvc package. This can be useful for custom multi error formatting.

Functions

func Run

func Run(modules ...Module) error

Run will run all given modules using following control flow:

  1. Exec Init() for each module in order. If any Init() returns error the Init loop is stopped and Stop() will be called for already initialized modules in reverse order.
  2. Exec Run() for each module in own goroutine so order isn't guaranteed.
  3. Wait for any Run() function to return nil or an error and move to Stop loop.
  4. Exec Stop() for modules in reverse order.
  5. Wait for all Run() goroutines to return.
  6. Return all errors or nil

Possible panics inside modules are captured to allow graceful shutdown of other modules. Captured panics are converted into errors and ErrPanic is returned.

func RunAndExit

func RunAndExit(modules ...Module)

RunAndExit is convenience wrapper for Run that calls os.Exit with code 1 in case of an error. The common use case is to srvc.RunAndExit from main function and let the srvc handle the rest.

package main

import "github.com/go-srvc/srvc"

func main() {
	srvc.RunAndExit(
	// Add your modules here
	)
}

Types

type ErrGroup

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

ErrGroup is a goroutine group that waits for all goroutines to finish and collects errors.

func (*ErrGroup) Go

func (eg *ErrGroup) Go(f func() error)

Go runs the given function in a goroutine.

func (*ErrGroup) Wait

func (eg *ErrGroup) Wait() error

Wait waits for all goroutines to finish and returns all errors that occurred.

type ErrStr

type ErrStr string

ErrStr adds Error method to string type.

func (ErrStr) Error

func (e ErrStr) Error() string

type Module

type Module interface {
	// ID should return identifier for logging purposes.
	ID() string
	// Init allows synchronous initialization of module.
	Init() error
	// Run should start the module and block until stop is called or error occurs.
	Run() error
	// Stop allows synchronous cleanup of module should make Run() return eventually.
	// If Init was called then Stop is guaranteed to be called as part of cleanup.
	Stop() error
}

Jump to

Keyboard shortcuts

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