### HTTP Server with Context Integration and Graceful Shutdown (Go) Source: https://context7.com/oklog/run/llms.txt This example demonstrates integrating an HTTP server with the oklog/run package for graceful shutdown. It uses ContextHandler and SignalHandler to manage the server's lifecycle, ensuring that the server stops cleanly when the context is canceled or an OS signal is received. The shutdown process includes a timeout to prevent indefinite hangs. ```go package main import ( "context" "fmt" "net/http" "time" "github.com/oklog/run" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() var g run.Group // HTTP Server actor { server := &http.Server{ Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from oklog/run!") }), } g.Add(func() error { fmt.Println("HTTP server starting on :8080") if err := server.ListenAndServe(); err != http.ErrServerClosed { return err } return nil }, func(error) { shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() fmt.Println("Shutting down HTTP server...") server.Shutdown(shutdownCtx) }) } // Context-based actor for coordinated shutdown { ctx, cancel := context.WithCancel(ctx) g.Add(func() error { return runBusinessLogic(ctx) }, func(error) { cancel() }) } // Signal handler for graceful shutdown g.Add(run.SignalHandler(ctx)) fmt.Printf("Application terminated: %v\n", g.Run()) } func runBusinessLogic(ctx context.Context) error { <-ctx.Done() return ctx.Err() } ``` -------------------------------- ### Group.Run - Executing All Actors Concurrently Source: https://context7.com/oklog/run/llms.txt Starts all registered actors concurrently and waits for the first one to complete. It then interrupts all other actors and returns only after all have exited. The error from the first actor that stopped is returned. ```APIDOC ## Group.Run ### Description Executes all actors added to the `run.Group` concurrently. It blocks until one actor returns an error or completes. Upon completion of one actor, all other running actors are interrupted, and the group waits for them to shut down before returning. ### Method `func (g *Group) Run() error` ### Parameters This method does not take any parameters. ### Request Example ```go package main import ( "errors" "fmt" time "time" "github.com/oklog/run" ) func main() { var g run.Group // Zero-value group returns nil immediately if err := g.Run(); err != nil { fmt.Printf("Empty group error: %v\n", err) } else { fmt.Println("Empty group completed successfully") } // Group with multiple actors myError := errors.New("task failed") cancel1 := make(chan struct{}) cancel2 := make(chan struct{}) g.Add(func() error { <-cancel1 fmt.Println("Actor 1 stopped") return nil }, func(error) { close(cancel1) }) g.Add(func() error { time.Sleep(100 * time.Millisecond) fmt.Println("Actor 2 returning error") return myError }, func(error) {}) g.Add(func() error { <-cancel2 fmt.Println("Actor 3 stopped") return nil }, func(error) { close(cancel2) }) // Run blocks until all actors complete err := g.Run() fmt.Printf("Group returned: %v\n", err) } ``` ### Response #### Success Response (nil) - Returns `nil` if the group is empty or all actors complete without error. #### Error Response - Returns the `error` from the first actor that exited with an error. #### Response Example ```json { "error": "task failed" } ``` (The actual return is the Go error value, not a JSON object.) ``` -------------------------------- ### Execute Actors Concurrently with run.Group - Go Source: https://context7.com/oklog/run/llms.txt Illustrates the usage of `run.Group.Run()` to execute multiple actors concurrently. It covers the scenario of an empty group and a group with several actors, where one actor is designed to return an error, triggering the teardown process for all others. This example requires the `github.com/oklog/run` package. ```Go package main import ( "errors" "fmt" "time" "github.com/oklog/run" ) func main() { var g run.Group // Zero-value group returns nil immediately if err := g.Run(); err != nil { fmt.Printf("Empty group error: %v\n", err) } else { fmt.Println("Empty group completed successfully") } // Group with multiple actors myError := errors.New("task failed") cancel1 := make(chan struct{}) cancel2 := make(chan struct{}) g.Add(func() error { <-cancel1 fmt.Println("Actor 1 stopped") return nil }, func(error) { close(cancel1) }) g.Add(func() error { time.Sleep(100 * time.Millisecond) fmt.Println("Actor 2 returning error") return myError }, func(error) {}) // No-op interrupt for this actor g.Add(func() error { <-cancel2 fmt.Println("Actor 3 stopped") return nil }, func(error) { close(cancel2) }) // Run blocks until all actors complete err := g.Run() fmt.Printf("Group returned: %v\n", err) // Output: // Empty group completed successfully // Actor 2 returning error // Actor 1 stopped // Actor 3 stopped // Group returned: task failed } ``` -------------------------------- ### Add Actor for graceful http.Server Shutdown to run.Group Source: https://github.com/oklog/run/blob/main/README.md Adds an actor to the run.Group for graceful shutdown of an http.Server. The execute function starts the server, and the interrupt function initiates a shutdown with a timeout. Dependencies include 'context', 'net/http', and 'time'. ```go httpServer := &http.Server{ Addr: "localhost:8080", Handler: ..., } g.Add(func() error { return httpServer.ListenAndServe() }, func(error) { ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second) defer cancel() httpServer.Shutdown(ctx) }) ``` -------------------------------- ### Add Actor with net.Listener to run.Group Source: https://github.com/oklog/run/blob/main/README.md Adds an actor to the run.Group that manages an HTTP server bound to a network listener. The execute function starts the server, and the interrupt function closes the listener to shut down the server. Dependencies include 'net' and 'net/http'. ```go ln, _ := net.Listen("tcp", ":8080") g.Add(func() error { return http.Serve(ln, nil) }, func(error) { ln.Close() }) ``` -------------------------------- ### Manage TCP Listener and I/O with Coordinated Shutdown (Go) Source: https://context7.com/oklog/run/llms.txt This Go snippet demonstrates using oklog/run.Group to manage a TCP listener and an I/O pipe concurrently. It includes explicit interrupt functions for resource cleanup (closing the listener and pipe) and a context timeout to trigger the group's shutdown. ```Go package main import ( "bufio" "context" "fmt" "io" "net" "time" "github.com/oklog/run" ) func main() { var g run.Group // TCP Listener actor { ln, err := net.Listen("tcp", ":8081") if err != nil { panic(err) } g.Add(func() error { fmt.Printf("TCP server listening on %s\n", ln.Addr()) for { conn, err := ln.Accept() if err != nil { return err } go handleConnection(conn) } }, func(error) { fmt.Println("Closing TCP listener...") ln.Close() }) } // Reader actor that processes input stream { r, w := io.Pipe() go func() { w.Write([]byte("line 1\nline 2\nline 3\n")) w.Close() }() g.Add(func() error { scanner := bufio.NewScanner(r) for scanner.Scan() { fmt.Printf("Read: %s\n", scanner.Text()) } return scanner.Err() }, func(error) { r.Close() }) } // Timeout actor to trigger shutdown { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() g.Add(run.ContextHandler(ctx)) } fmt.Printf("All actors stopped: %v\n", g.Run()) } func handleConnection(conn net.Conn) { defer conn.Close() fmt.Fprintf(conn, "Connected at %s\n", time.Now()) } ``` -------------------------------- ### Add Actors to run.Group - Go Source: https://context7.com/oklog/run/llms.txt Demonstrates adding two actors to a `run.Group`. The first actor runs for a set duration or until canceled, while the second actor fails immediately. This showcases how the first actor to exit triggers the interruption of all other actors. It requires the `github.com/oklog/run` package. ```Go package main import ( "errors" "fmt" "time" "github.com/oklog/run" ) func main() { var g run.Group // First actor: runs for 5 seconds or until canceled { cancel := make(chan struct{}) g.Add(func() error { select { case <-time.After(5 * time.Second): fmt.Println("First actor completed") return nil case <-cancel: fmt.Println("First actor was canceled") return nil } }, func(err error) { fmt.Printf("First actor interrupted with: %v\n", err) close(cancel) }) } // Second actor: fails immediately, triggering teardown { g.Add(func() error { fmt.Println("Second actor failing immediately") return errors.New("immediate failure") }, func(err error) { fmt.Printf("Second actor interrupted with: %v\n", err) }) } // Run returns the error from the first actor that exits err := g.Run() fmt.Printf("Group terminated with: %v\n", err) // Output: // Second actor failing immediately // First actor interrupted with: immediate failure // Second actor interrupted with: immediate failure // First actor was canceled // Group terminated with: immediate failure } ``` -------------------------------- ### Group.Add - Adding Actors to the Group Source: https://context7.com/oklog/run/llms.txt Registers an actor with the group. The execute function runs synchronously, and the interrupt function signals the execute function to stop. The first actor to return causes all other actors to be interrupted. ```APIDOC ## Group.Add ### Description Registers an actor (execute and interrupt functions) with the `run.Group`. When the first actor returns, all other actors are interrupted. ### Method `func (g *Group) Add(execute func() error, interrupt func(error)) error` ### Parameters #### Execute Function - `execute` (func() error) - A function that performs the actor's main logic. It should return an error when it completes or fails. #### Interrupt Function - `interrupt` (func(error)) - A function called when another actor in the group returns an error. It receives the error from the actor that caused the group to shut down and should signal the execute function to stop. ### Request Example ```go package main import ( "errors" "fmt" time "time" "github.com/oklog/run" ) func main() { var g run.Group // First actor: runs for 5 seconds or until canceled { cancel := make(chan struct{}) g.Add(func() error { select { case <-time.After(5 * time.Second): fmt.Println("First actor completed") return nil case <-cancel: fmt.Println("First actor was canceled") return nil } }, func(err error) { fmt.Printf("First actor interrupted with: %v\n", err) close(cancel) }) } // Second actor: fails immediately, triggering teardown { g.Add(func() error { fmt.Println("Second actor failing immediately") return errors.New("immediate failure") }, func(err error) { fmt.Printf("Second actor interrupted with: %v\n", err) }) } err := g.Run() fmt.Printf("Group terminated with: %v\n", err) } ``` ### Response (This method modifies the group and does not directly return a response in the conventional sense. Errors are handled by `Group.Run`.) ``` -------------------------------- ### Add Actor with context.Context to run.Group Source: https://github.com/oklog/run/blob/main/README.md Adds an actor to the run.Group that utilizes context.Context for cancellation. The execute function runs a process, and the interrupt function cancels the context to signal the process to stop. Dependencies include 'context'. ```go ctx, cancel := context.WithCancel(context.Background()) g.Add(func() error { return myProcess(ctx, ...) }, func(error) { cancel() }) ``` -------------------------------- ### Add Actor with io.ReadCloser to run.Group Source: https://github.com/oklog/run/blob/main/README.md Adds an actor to the run.Group that reads from an io.ReadCloser. The execute function scans and processes lines from the reader, returning an error if scanning fails. The interrupt function closes the reader to stop reading. Dependencies include 'bufio' and 'io'. ```go var conn io.ReadCloser = ... g.Add(func() error { s := bufio.NewScanner(conn) for s.Scan() { println(s.Text()) } return s.Err() }, func(error) { conn.Close() }) ``` -------------------------------- ### ContextHandler: Terminate Actor on Context Cancellation (Go) Source: https://context7.com/oklog/run/llms.txt The ContextHandler creates an actor that gracefully terminates when its associated context is canceled. It returns the necessary execute and interrupt functions for integration with run.Group, ensuring that dependent operations are also halted. This is useful for managing background tasks that should stop when a parent process or request is terminated. ```go package main import ( "context" "fmt" "time" "github.com/oklog/run" ) func main() { ctx, cancel := context.WithCancel(context.Background()) var g run.Group // Add context handler actor g.Add(run.ContextHandler(ctx)) // Add work that runs in parallel workDone := make(chan struct{}) g.Add(func() error { fmt.Println("Starting work...") time.Sleep(500 * time.Millisecond) fmt.Println("Work completed") close(workDone) return nil }, func(error) { fmt.Println("Work interrupted") }) // Cancel context after 1 second go func() { time.Sleep(1 * time.Second) fmt.Println("Canceling context") cancel() }() err := g.Run() fmt.Printf("Group terminated with: %v\n", err) // Output: // Starting work... // Work completed // Canceling context // Work interrupted // Group terminated with: context canceled } ``` -------------------------------- ### SignalHandler: Terminate Actor on OS Signals or Context Cancellation (Go) Source: https://context7.com/oklog/run/llms.txt The SignalHandler creates an actor that terminates when the process receives specified OS signals (like SIGINT or SIGTERM) or when the parent context is canceled. It returns a SignalError upon receiving a signal, allowing for specific error handling. This is crucial for implementing graceful shutdowns in response to external termination requests. ```go package main import ( "context" "errors" "fmt" "os" "os/signal" "syscall" "time" "github.com/oklog/run" ) func main() { ctx := context.Background() var g run.Group // Handle SIGINT and SIGTERM for graceful shutdown g.Add(run.SignalHandler(ctx, os.Interrupt, syscall.SIGTERM)) // Simulate long-running work cancel := make(chan struct{}) g.Add(func() error { ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: fmt.Println("Working...") case <-cancel: fmt.Println("Work canceled") return nil } } }, func(error) { close(cancel) }) err := g.Run() // Check if termination was due to signal if errors.Is(err, run.ErrSignal) { fmt.Println("Terminated by signal") var sigErr *run.SignalError if errors.As(err, &sigErr) { fmt.Printf("Signal received: %v\n", sigErr.Signal) } } else { fmt.Printf("Terminated with error: %v\n", err) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.