8000 GitHub - pubgo/breaker: 🚧 Flexible mechanism to make execution flow interruptible.
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

pubgo/breaker

 
 

Repository files navigation

🚧 breaker

Flexible mechanism to make execution flow interruptible.

Build Documentation Quality Template Coverage Awesome

💡 Idea

The breaker carries a cancellation signal to interrupt an action execution.

interrupter := breaker.Multiplex(
	breaker.BreakByContext(context.WithTimeout(req.Context(), time.Minute)),
	breaker.BreakByDeadline(NewYear),
	breaker.BreakBySignal(os.Interrupt),
)
defer interrupter.Close()

<-interrupter.Done() // wait context cancellation, timeout or interrupt signal

Full description of the idea is available here.

🏆 Motivation

I have to make retry package:

if err := retry.Retry(breaker.BreakByTimeout(time.Minute), action); err != nil {
	log.Fatal(err)
}

and semaphore package:

if err := semaphore.Acquire(breaker.BreakByTimeout(time.Minute), 5); err != nil {
	log.Fatal(err)
}

more consistent and reliable.

🤼‍♂️ How to

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"

	"github.com/kamilsk/breaker"
)

var NewYear = time.Time{}.AddDate(time.Now().Year(), 0, 0)

func Handle(rw http.ResponseWriter, req *http.Request) {
	ctx, cancel := context.WithCancel(req.Context())
	defer cancel()

	deadline, _ := time.ParseDuration(req.Header.Get("X-Timeout"))
	interrupter := breaker.Multiplex(
		breaker.BreakByContext(context.WithTimeout(ctx, deadline)),
		breaker.BreakByDeadline(NewYear),
		breaker.BreakBySignal(os.Interrupt),
	)
	defer interrupter.Close()

	buf, work := bytes.NewBuffer(nil), Work(ctx, struct{}{})
	for {
		select {
		case b, ok := <-work:
			if !ok {
				rw.WriteHeader(http.StatusOK)
				io.Copy(rw, buf)
				return
			}
			buf.WriteByte(b)
		case <-interrupter.Done():
			rw.WriteHeader(http.StatusPartialContent)
			rw.Header().Set("Content-Range", fmt.Sprintf("bytes=0-%d", buf.Len()))
			io.Copy(rw, buf)
			return
		}
	}
}

func Work(ctx context.Context, _ struct{}) <-chan byte {
	outcome := make(chan byte, 1)

	go func() { ... }()

	return outcome
}

🧩 Integration

The library uses SemVer for versioning, and it is not BC-safe through major releases. You can use go modules to manage its version.

$ go get github.com/kamilsk/breaker@latest

made with ❤️ for everyone

About

🚧 Flexible mechanism to make execution flow interruptible.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 87.8%
  • Makefile 12.2%
0