Thanks to visit codestin.com
Credit goes to pkg.go.dev

run

package module
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Dec 5, 2025 License: BSD-2-Clause Imports: 14 Imported by: 38

README

Run

Go Reference Go Report Card

A Go library for parallel function execution with different error handling strategies and utilities.

Features

  • Parallel Execution: Run multiple functions concurrently with various error handling strategies
  • Error Handling: Choose from different error handling approaches (fail-fast, collect all, etc.)
  • Retry Logic: Built-in retry functionality with configurable backoff
  • Context Support: Full context.Context support for cancellation and timeouts
  • Utilities: Additional helpers for delayed execution, parallel skipping, and more

Installation

go get github.com/bborbe/run

Quick Start

package main

import (
    "context"
    "fmt"
    "github.com/bborbe/run"
)

func main() {
    ctx := context.Background()
    
    // Run functions in parallel, stop on first error
    err := run.CancelOnFirstError(ctx,
        func(ctx context.Context) error {
            fmt.Println("Task 1")
            return nil
        },
        func(ctx context.Context) error {
            fmt.Println("Task 2") 
            return nil
        },
    )
    
    if err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

Execution Strategies

Parallel Execution with Error Handling
// Cancel all remaining functions when first one finishes
err := run.CancelOnFirstFinish(ctx, funcs...)

// Cancel all remaining functions when first error occurs
err := run.CancelOnFirstError(ctx, funcs...)

// Run all functions, collect all errors
err := run.All(ctx, funcs...)

// Run functions sequentially
err := run.Sequential(ctx, funcs...)
Retry with Backoff
retryableFunc := run.Retry(run.Backoff{
    Delay:   time.Second,
    Factor:  2.0,
    Retries: 3,
    IsRetryAble: func(err error) bool {
        // Custom logic to determine if error is retryable
        return true
    },
}, func(ctx context.Context) error {
    // Your function that may fail
    return someOperation(ctx)
})

err := retryableFunc(ctx)
Delayed Execution
// Delay execution by 5 seconds
delayedFunc := run.Delayed(func(ctx context.Context) error {
    fmt.Println("This runs after 5 seconds")
    return nil
}, 5*time.Second)

err := delayedFunc(ctx)
Prevent Parallel Execution
skipper := run.NewParallelSkipper()

// Wrap function to prevent parallel execution
protectedFunc := skipper.SkipParallel(func(ctx context.Context) error {
    // This function will be skipped if already running
    return expensiveOperation(ctx)
})

Core Types

The library is built around two main interfaces:

// Func is a function that can be executed with context
type Func func(context.Context) error

// Runnable interface for objects that can be run
type Runnable interface {
    Run(ctx context.Context) error
}

Advanced Usage

Custom Error Handling
// Get a channel of errors for custom processing
errorChan := run.Run(ctx, funcs...)
for err := range errorChan {
    if err != nil {
        log.Printf("Function failed: %v", err)
    }
}
Background Runners
// For long-running background tasks
runner := run.NewBackgroundRunner()
// ... (see source code for full API)

Examples

Web Server with Graceful Shutdown
func startServer(ctx context.Context) error {
    server := &http.Server{Addr: ":8080"}
    
    return run.CancelOnFirstFinish(ctx,
        func(ctx context.Context) error {
            // Start server
            return server.ListenAndServe()
        },
        func(ctx context.Context) error {
            // Wait for context cancellation
            <-ctx.Done()
            // Graceful shutdown
            return server.Shutdown(context.Background())
        },
    )
}
Parallel Data Processing
func processData(ctx context.Context, items []string) error {
    var funcs []run.Func
    
    for _, item := range items {
        item := item // capture loop variable
        funcs = append(funcs, func(ctx context.Context) error {
            return processItem(ctx, item)
        })
    }
    
    // Process all items, collect all errors
    return run.All(ctx, funcs...)
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the BSD-style license. See the LICENSE file for details.

Documentation

Overview

Package run provides utilities for parallel function execution with different error handling strategies.

The package offers various execution patterns for running multiple functions concurrently:

  • CancelOnFirstError: stops all functions when the first error occurs
  • CancelOnFirstFinish: stops all functions when the first one completes
  • All: runs all functions and collects all errors
  • Sequential: runs functions one after another

Additional utilities include retry mechanisms with configurable backoff, delayed execution, panic recovery, parallel execution prevention, and background task management.

Basic usage:

ctx := context.Background()
err := run.All(ctx,
	func(ctx context.Context) error { return doTask1(ctx) },
	func(ctx context.Context) error { return doTask2(ctx) },
)

The package is built around the Func type which represents any operation that can be executed with a context and may return an error.

Index

Constants

This section is empty.

Variables

View Source
var DefaultWaiter = NewWaiter()

DefaultWaiter is the default waiter implementation used by the Retry function.

Functions

func All

func All(ctx context.Context, funcs ...Func) error

All executes all given functions in parallel and waits for all to complete. It returns an aggregate error containing all errors that occurred during execution, or nil if all functions succeed.

func CancelOnFirstError

func CancelOnFirstError(ctx context.Context, funcs ...Func) error

CancelOnFirstError executes all given functions in parallel and cancels the remaining functions when the first error occurs. It returns the first error encountered, providing fail-fast behavior.

func CancelOnFirstErrorWait

func CancelOnFirstErrorWait(ctx context.Context, funcs ...Func) error

CancelOnFirstErrorWait executes all given functions in parallel and cancels the remaining functions when the first error occurs. Unlike CancelOnFirstError, it waits for all functions to complete or be canceled and returns an aggregate error of all failures.

func CancelOnFirstFinish

func CancelOnFirstFinish(ctx context.Context, funcs ...Func) error

CancelOnFirstFinish executes all given functions in parallel and cancels the remaining functions when the first one completes. It returns the error from the first function that finishes, or nil if that function succeeds.

func CancelOnFirstFinishWait

func CancelOnFirstFinishWait(ctx context.Context, funcs ...Func) error

CancelOnFirstFinishWait executes all given functions in parallel and cancels the remaining functions when the first one completes. Unlike CancelOnFirstFinish, it waits for all functions to complete or be canceled and returns an aggregate error of all failures.

func ContextWithSig added in v1.7.0

func ContextWithSig(ctx context.Context) context.Context

ContextWithSig creates a new context that is canceled when the process receives termination signals. It listens for SIGINT and SIGTERM signals and cancels the returned context when any of these signals are received. This is useful for graceful shutdown of long-running processes.

func NewErrorList

func NewErrorList(errs ...error) error

NewErrorList creates an aggregate error from the given errors. It returns nil if no errors are provided or all errors are nil.

func NewErrorListByChan

func NewErrorListByChan(ch <-chan error) error

NewErrorListByChan creates an aggregate error from all errors received from the given channel. It blocks until the channel is closed and returns nil if no errors were received.

func NewMetrics

func NewMetrics(
	registerer prometheus.Registerer,
	namespace string,
	subsystem string,
	fn Func,
) func(ctx context.Context) error

NewMetrics wraps a function with Prometheus metrics collection. It tracks started, completed, failed runs and the timestamp of the last successful execution. The metrics are registered with the provided registerer using the specified namespace and subsystem.

func Run

func Run(ctx context.Context, funcs ...Func) <-chan error

Run executes all given functions in parallel and returns a channel that receives the result of each function. The channel is closed when all functions have completed. This provides the lowest-level access to execution results.

func Sequential

func Sequential(ctx context.Context, funcs ...Func) (err error)

Sequential executes all given functions one after another in order. It stops and returns the first error encountered, or nil if all functions succeed.

Types

type AddFire

type AddFire interface {
	// Add creates and returns a new trigger that becomes part of the multi-trigger group.
	Add() Trigger
}

AddFire represents the ability to create new triggers dynamically.

type BackgroundRunner added in v1.4.0

type BackgroundRunner interface {
	FuncRunner
}

BackgroundRunner executes functions in background goroutines with parallel execution prevention. It embeds FuncRunner and inherits the Run method, executing functions asynchronously. It ensures that only one instance of a function runs at a time, skipping subsequent calls if already running.

func NewBackgroundRunner added in v1.4.0

func NewBackgroundRunner(ctx context.Context) BackgroundRunner

NewBackgroundRunner creates a new BackgroundRunner that uses the provided context for all background operations. The returned runner will skip parallel executions and log the results of background operations.

type Backoff

type Backoff struct {
	// Delay is the initial delay to wait before the first retry.
	Delay time.Duration `json:"delay"`
	// Factor is the multiplier applied to the delay for each subsequent retry.
	Factor float64 `json:"factor"`
	// Retries is the maximum number of retry attempts.
	Retries int `json:"retries"`
	// IsRetryAble is an optional function that determines if an error is retryable.
	// If nil, all errors are considered retryable.
	IsRetryAble func(error) bool `json:"-"`
}

Backoff configures retry behavior including delays, retry counts, and retry conditions.

type ConcurrentRunner

type ConcurrentRunner interface {
	Add(ctx context.Context, fn Func)
	Run(ctx context.Context) error
	io.Closer
}

ConcurrentRunner manages concurrent execution of functions with a configurable concurrency limit. It allows adding functions dynamically and executes them with controlled parallelism.

func NewConcurrentRunner

func NewConcurrentRunner(maxConcurrent int) ConcurrentRunner

NewConcurrentRunner creates a new ConcurrentRunner that limits concurrent execution to maxConcurrent functions. The runner must be closed when no longer needed to clean up resources.

type Done

type Done interface {
	// Done returns a channel that receives a signal when the trigger is fired.
	Done() <-chan struct{}
}

Done represents the ability to wait for a trigger event.

type Fire

type Fire interface {
	// Fire signals the trigger, notifying any listeners waiting on the Done channel.
	Fire()
}

Fire represents the ability to trigger an event.

type Func

type Func func(context.Context) error

Func represents a function that can be executed with a context. It forms the foundation of this package, representing any operation that may fail and supports cancellation through context.

func CatchPanic

func CatchPanic(fn Func) Func

CatchPanic wraps the given function to recover from panics and convert them to errors. If the wrapped function panics, the panic is recovered and returned as an error.

func Delayed

func Delayed(fn Func, duration time.Duration) Func

Delayed wraps the given function to delay its execution by the specified duration. The delay is implemented using a timer and respects context cancellation.

func LogErrors

func LogErrors(fn Func) Func

LogErrors wraps the given function to log any errors that occur while still propagating them. Errors are logged as warnings and then returned to the caller.

func Retry

func Retry(backoff Backoff, fn Func) Func

Retry wraps a function with retry logic using the specified backoff configuration. It uses the DefaultWaiter for delays between retry attempts.

func RetryWaiter added in v1.5.0

func RetryWaiter(backoff Backoff, waiter Waiter, fn Func) Func

RetryWaiter wraps a function with retry logic using the specified backoff configuration and custom waiter. The waiter controls how delays are implemented, allowing for custom timing behavior.

func SkipErrors

func SkipErrors(fn Func) Func

SkipErrors wraps the given function to suppress all errors and always return nil. Errors are logged as warnings but do not propagate to the caller.

func SkipErrorsAndReport

func SkipErrorsAndReport(
	fn Func,
	hasCaptureException HasCaptureException,
	tags map[string]string,
) Func

SkipErrorsAndReport wraps the given function to suppress all errors, report them to an error tracking service, and always return nil. Context cancellation errors are not reported. The function logs errors as warnings and sends them to the specified error tracker.

func Triggered

func Triggered(fn Func, trigger <-chan struct{}) Func

Triggered wraps the given function to execute only when triggered by a channel signal. The function waits for either a trigger signal or context cancellation before proceeding.

func (Func) Run

func (r Func) Run(ctx context.Context) error

Run executes the function with the provided context.

type FuncRunner added in v1.8.0

type FuncRunner interface {
	Run(runFunc Func) error
}

FuncRunner is an interface for executing Func with custom behavior. It allows wrapping, decorating, or transforming function execution.

type FuncRunnerFunc added in v1.8.0

type FuncRunnerFunc func(runFunc Func) error

FuncRunnerFunc is a function type adapter that implements the FuncRunner interface. This allows plain functions to be used wherever FuncRunner is expected, following the standard Go pattern of function types implementing single-method interfaces.

func (FuncRunnerFunc) Run added in v1.8.0

func (f FuncRunnerFunc) Run(runFunc Func) error

Run executes the function, implementing the FuncRunner interface.

type HasCaptureException added in v1.7.6

type HasCaptureException interface {
	CaptureException(
		exception error,
		hint *sentry.EventHint,
		scope sentry.EventModifier,
	) *sentry.EventID
}

HasCaptureException defines the interface for error reporting services. It is compatible with sentry.Client for reporting captured errors.

type MultiTrigger

type MultiTrigger interface {
	Done
	AddFire
}

MultiTrigger manages multiple triggers and fires when all of them have been triggered. It combines the ability to add new triggers dynamically and wait for all triggers to fire.

func NewMultiTrigger

func NewMultiTrigger() MultiTrigger

NewMultiTrigger creates a new MultiTrigger that waits for all added triggers to fire. The Done channel signals when all individual triggers have been fired.

type ParallelSkipper

type ParallelSkipper interface {
	SkipParallel(action Func) Func
}

ParallelSkipper prevents parallel execution of wrapped functions. It ensures that only one instance of a wrapped function can run at a time, skipping subsequent calls.

func NewParallelSkipper

func NewParallelSkipper() ParallelSkipper

NewParallelSkipper creates a new ParallelSkipper that can wrap functions to prevent parallel execution. Each ParallelSkipper instance maintains its own execution state.

type Runnable

type Runnable interface {
	Run(ctx context.Context) error
}

Runnable represents any object that can execute an operation with a context. This interface allows for more complex execution patterns where state or configuration needs to be maintained between calls.

type Trigger

type Trigger interface {
	Fire
	Done
}

Trigger combines the ability to fire events and wait for them. It provides a simple synchronization mechanism for coordinating between goroutines.

func NewTrigger

func NewTrigger() Trigger

NewTrigger creates a new Trigger that can be used to coordinate between goroutines. The trigger starts in an unfired state and can be fired multiple times safely.

type Waiter added in v1.5.0

type Waiter interface {
	Wait(ctx context.Context, wait time.Duration) error
}

Waiter provides an interface for implementing delays with context cancellation support. This abstraction allows for testing and custom wait implementations.

func NewWaiter added in v1.5.0

func NewWaiter() Waiter

NewWaiter creates a default Waiter implementation that uses time.Timer for delays. The waiter respects context cancellation and logs the wait duration.

type WaiterFunc added in v1.5.0

type WaiterFunc func(ctx context.Context, wait time.Duration) error

WaiterFunc is a function type that implements the Waiter interface. It allows converting simple functions into Waiter implementations.

func (WaiterFunc) Wait added in v1.5.0

func (w WaiterFunc) Wait(ctx context.Context, wait time.Duration) error

Directories

Path Synopsis
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

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