stager

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2020 License: Apache-2.0 Imports: 1 Imported by: 27

README

Stager

Stager is a library to help write code where you are in control of start and shutdown of concurrent operations. I.e. you know when goroutines start and stop and in which order.

An example is below. pong is always shutdown first, and ping last:

package main

import (
	"context"
	"log"
	"time"

	"github.com/ash2k/stager"
)

func main() {
	defer log.Print("Exiting main")
	st := stager.New()

	ball := make(chan struct{})
	p1 := ping{
		ball: ball,
	}
	s := st.NextStage()
	s.Go(p1.run)

	p2 := pong{
		ball: ball,
	}
	s = st.NextStage()
	s.Go(p2.run)

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	err := st.Run(ctx)
	if err != nil {
		log.Fatal(err)
	}
}

type ping struct {
	ball chan struct{}
}

func (p *ping) run(ctx context.Context) error {
	log.Print("Starting ping")
	defer log.Print("Shutting down ping")
	for {
		select {
		case <-ctx.Done():
			return nil
		case <-p.ball:
		}
		select {
		case <-ctx.Done():
			return nil
		case <-time.After(time.Second):
		}
		log.Print("ping")
		select {
		case <-ctx.Done():
			return nil
		case p.ball <- struct{}{}:
		}
	}
}

type pong struct {
	ball chan struct{}
}

func (p *pong) run(ctx context.Context) error {
	log.Print("Starting pong")
	defer time.Sleep(time.Second)
	defer log.Print("Shutting down pong - sleeping 1 second")
	for {
		select {
		case <-ctx.Done():
			return nil
		case p.ball <- struct{}{}:
		}
		select {
		case <-ctx.Done():
			return nil
		case <-p.ball:
		}
		select {
		case <-ctx.Done():
			return nil
		case <-time.After(time.Second):
		}
		log.Print("pong")
	}
}

Output:

2017/06/20 13:34:33 Starting pong
2017/06/20 13:34:33 Starting ping
2017/06/20 13:34:34 ping
2017/06/20 13:34:35 pong
2017/06/20 13:34:36 ping
2017/06/20 13:34:37 pong
2017/06/20 13:34:38 Shutting down pong - sleeping 1 second
2017/06/20 13:34:38 ping
2017/06/20 13:34:39 Shutting down ping
2017/06/20 13:34:39 Exiting main

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Stage

type Stage interface {
	// Go starts f in a new goroutine attached to the Stage.
	// Stage context is passed to f as an argument. f should stop when context signals done.
	// If f returns a non-nil error, the stager starts performing shutdown.
	Go(f func(context.Context) error)
}

type Stager

type Stager interface {
	// NextStageWithContext adds a new stage to the Stager.
	NextStage() Stage
	// NextStageWithContext adds a new stage to the Stager. Provided ctxParent is used as the parent context for the
	// Stage's context.
	NextStageWithContext(ctxParent context.Context) Stage
	// Run blocks until ctx signals done or a function in a stage returns a non-nil error.
	// When it unblocks, it iterates Stages in reverse order. For each stage it cancels
	// it's context and waits for all started goroutines of that stage to finish.
	// Then it proceeds to the next stage.
	Run(ctx context.Context) error
}

func New

func New() Stager

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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