ctxo

package
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 8 Imported by: 0

README

GlobalContext Package

Overview

The GlobalContext package provides a process-wide context management system that allows graceful shutdown of all components when the application receives termination signals (SIGINT, SIGTERM). It ensures that all child contexts are properly cancelled when the global context is shut down.

Features

  • Process-wide context management: Single global context shared across the entire application
  • Automatic signal handling: Listens for SIGINT and SIGTERM signals for graceful shutdown
  • Child context support: Create child contexts that automatically respect the global shutdown
  • Thread-safe: Uses mutexes to protect concurrent access
  • Idempotent operations: Safe to call Init/Get multiple times

API Reference

GetGlobalContext()

Returns a new GlobalContext instance. Multiple instances share the same underlying global context state.

gc := GetGlobalContext()
Init() context.Context

Initializes the global context if it hasn't been created yet. Sets up signal handlers for graceful shutdown. Returns the global context.

ctx := gc.Init()

Behavior:

  • If global context already exists and is active, returns the existing context
  • If global context doesn't exist or was cancelled, creates a new one
  • Sets up signal handlers (SIGINT, SIGTERM) on first initialization
  • Thread-safe
Get() context.Context

Returns the currently initialized global context. If no context exists, calls Init() automatically.

ctx := gc.Get()

Behavior:

  • Returns existing global context if available
  • Automatically initializes if context doesn't exist
  • Thread-safe
NewChildContext() (context.Context, context.CancelFunc)

Creates a child context derived from the global context. The child context will be automatically cancelled when the global context is shut down.

childCtx, cancel := gc.NewChildContext()
defer cancel() // Always defer cancel to avoid leaks

Returns:

  • context.Context: The child context
  • context.CancelFunc: Function to cancel the child context independently

Behavior:

  • Child context is automatically cancelled when global context shuts down
  • Can be cancelled independently without affecting global context
  • Thread-safe
Shutdown()

Cancels the global context and all its child contexts. Resets the global state so a new context can be initialized.

gc.Shutdown()

Behavior:

  • Cancels the global context
  • All child contexts are automatically cancelled (cascade effect)
  • Resets internal state
  • Thread-safe

Usage Examples

Basic Usage
package main

import (
    "context"
    "gossipnode/config/Context"
    "time"
)

func main() {
    // Get GlobalContext instance
    gc := Context.GetGlobalContext()
    
    // Initialize global context
    ctx := gc.Init()
    
    // Create a child context for a specific operation
    childCtx, cancel := gc.NewChildContext()
    defer cancel()
    
    // Use the child context
    doWork(childCtx)
    
    // Global context will be cancelled on SIGINT/SIGTERM
    <-ctx.Done()
}

func doWork(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return // Exit gracefully when context is cancelled
        default:
            // Do work
            time.Sleep(1 * time.Second)
        }
    }
}
Child Context with Timeout
gc := Context.GetGlobalContext()
gc.Init()

// Create child context
childCtx, cancel := gc.NewChildContext()
defer cancel()

// Add timeout to child context
timeoutCtx, timeoutCancel := context.WithTimeout(childCtx, 5*time.Second)
defer timeoutCancel()

// Use timeout context
select {
case <-timeoutCtx.Done():
    if timeoutCtx.Err() == context.DeadlineExceeded {
        // Timeout occurred
    } else if timeoutCtx.Err() == context.Canceled {
        // Parent was cancelled
    }
case <-time.After(10 * time.Second):
    // Work completed before timeout
}
Multiple Child Contexts
gc := Context.GetGlobalContext()
globalCtx := gc.Init()

// Create multiple child contexts for different components
dbCtx, dbCancel := gc.NewChildContext()
defer dbCancel()

apiCtx, apiCancel := gc.NewChildContext()
defer apiCancel()

workerCtx, workerCancel := gc.NewChildContext()
defer workerCancel()

// Each component can manage its own lifecycle
go runDatabase(dbCtx)
go runAPI(apiCtx)
go runWorkers(workerCtx)

// All will be cancelled when global context shuts down
<-globalCtx.Done()
Graceful Shutdown Pattern
gc := Context.GetGlobalContext()
ctx := gc.Init()

// Start components with child contexts
components := []struct{
    name string
    ctx  context.Context
    cancel context.CancelFunc
}{
    {"database", gc.NewChildContext()},
    {"api", gc.NewChildContext()},
    {"workers", gc.NewChildContext()},
}

// Start all components
for _, comp := range components {
    go runComponent(comp.name, comp.ctx)
}

// Wait for shutdown signal
<-ctx.Done()

// All child contexts are automatically cancelled
// Components should exit gracefully

Best Practices

  1. Always defer cancel: When creating child contexts, always defer the cancel function to avoid context leaks

    childCtx, cancel := gc.NewChildContext()
    defer cancel()
    
  2. Initialize once: Call Init() early in your application startup, or use Get() which initializes automatically

  3. Check context in loops: Always check ctx.Done() in long-running operations

    for {
        select {
        case <-ctx.Done():
            return
        default:
            // Do work
        }
    }
    
  4. Use child contexts for components: Create separate child contexts for different components (database, API, workers) so they can be managed independently

  5. Respect cancellation: Always respect context cancellation and exit gracefully

Signal Handling

The package automatically sets up signal handlers for:

  • SIGINT (Ctrl+C)
  • SIGTERM (Termination signal)

When either signal is received:

  1. The global context is cancelled via Shutdown()
  2. All child contexts are automatically cancelled
  3. Components should exit gracefully

Thread Safety

All operations are thread-safe:

  • Multiple goroutines can call Init(), Get(), NewChildContext() concurrently
  • The underlying global state is protected by mutexes
  • Child contexts can be created and cancelled from different goroutines

Testing

See GlobalContext_test.go for comprehensive test examples including:

  • Basic initialization and retrieval
  • Child context creation
  • Timeout handling
  • Concurrent operations
  • Shutdown behavior

Architecture

GlobalContext (package-level state)
    ├── Child Context 1
    │   └── Timeout Context 1.1
    ├── Child Context 2
    │   └── Timeout Context 2.1
    └── Child Context 3

When Shutdown() is called or a signal is received:

  • GlobalContext is cancelled
  • All Child Contexts are cancelled (cascade)
  • All Timeout Contexts are cancelled (cascade)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SpawnChild

func SpawnChild(ctx context.Context) (context.Context, context.CancelFunc)

Spawn Child for the given context

func SpawnChildWithTimeout

func SpawnChildWithTimeout(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc)

Spawn Child for the given context with timeout

Types

type AppContext

type AppContext struct {
	GlobalContext *GlobalContext
	App           string
}

func (*AppContext) Done

func (ac *AppContext) Done(ctx context.Context)

func (*AppContext) Get

func (ac *AppContext) Get() context.Context

GetApp returns the app-level context for the current app, initializing it if needed.

func (*AppContext) Init

func (ac *AppContext) Init() context.Context

InitApp initializes an app-level context as a child of the global context. If an app context already exists for this app name, it returns the existing one.

func (*AppContext) NewChildContext

func (ac *AppContext) NewChildContext() (context.Context, context.CancelFunc)

NewChildContextForApp creates a child context derived from the app-level context.

func (*AppContext) NewChildContextWithTimeout

func (ac *AppContext) NewChildContextWithTimeout(timeout time.Duration) (context.Context, context.CancelFunc)

NewChildContextForAppWithTimeout creates a child context with timeout from the app-level context.

func (*AppContext) SetAppName

func (ac *AppContext) SetAppName(app string)

SetAppName sets the name of the app for the app context.

func (*AppContext) Shutdown

func (ac *AppContext) Shutdown()

ShutdownApp cancels the app-level context for the current app.

type ContextInterface

type ContextInterface interface {
	Init() context.Context
	Get() context.Context
	Shutdown()
	Done(ctx context.Context)
	NewChildContext() (context.Context, context.CancelFunc)
	NewChildContextWithTimeout(timeout time.Duration) (context.Context, context.CancelFunc)
	SetAppName(app string)
}

func GetAppContext

func GetAppContext(app string) ContextInterface

func GetGlobalContext

func GetGlobalContext() ContextInterface

type GlobalContext

type GlobalContext struct{}

func (*GlobalContext) Done

func (gc *GlobalContext) Done(ctx context.Context)

func (*GlobalContext) Get

func (gc *GlobalContext) Get() context.Context

Get returns the currently initialized global context, calling Init if needed so callers can always rely on a valid parent context.

func (*GlobalContext) Init

func (gc *GlobalContext) Init() context.Context

Init sets up the global context if it hasn't been created yet and returns it so callers can use it as a parent.

func (*GlobalContext) ListActiveApps

func (gc *GlobalContext) ListActiveApps() []string

ListActiveApps returns a list of all apps with active contexts.

func (*GlobalContext) NewChildContext

func (gc *GlobalContext) NewChildContext() (context.Context, context.CancelFunc)

NewChildContext creates a child context derived from the global context.

func (*GlobalContext) NewChildContextWithTimeout

func (gc *GlobalContext) NewChildContextWithTimeout(timeout time.Duration) (context.Context, context.CancelFunc)

NewChildContextWithTimeout creates a child context with timeout from the global context.

func (*GlobalContext) SetAppName

func (gc *GlobalContext) SetAppName(app string)

SetAppName is a no-op for GlobalContext since it doesn't have an app name.

func (*GlobalContext) Shutdown

func (gc *GlobalContext) Shutdown()

Shutdown triggers the cancellation of the global context and all app-level contexts.

Jump to

Keyboard shortcuts

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