zoobzio December 10, 2025 Edit this page

Fields Reference

Flux emits capitan signals at key points in the configuration lifecycle. This reference covers all signals and field keys.

Signals

Lifecycle Signals

CapacitorStarted

Emitted when Start() is called.

var CapacitorStarted = capitan.NewSignal(
    "flux.capacitor.started",
    "Capacitor watching started",
)

Fields:

  • KeyDebounce - Configured debounce duration

CapacitorStopped

Emitted when the watch goroutine exits.

var CapacitorStopped = capitan.NewSignal(
    "flux.capacitor.stopped",
    "Capacitor watching stopped",
)

Fields:

  • KeyState - Final state at shutdown

CapacitorStateChanged

Emitted on state transitions.

var CapacitorStateChanged = capitan.NewSignal(
    "flux.capacitor.state.changed",
    "Capacitor state transition",
)

Fields:

  • KeyOldState - Previous state
  • KeyNewState - New state

Processing Signals

CapacitorChangeReceived

Emitted when raw data arrives from the watcher.

var CapacitorChangeReceived = capitan.NewSignal(
    "flux.capacitor.change.received",
    "Raw change received from watcher",
)

Fields: None

CapacitorTransformFailed

Emitted when codec unmarshal fails.

var CapacitorTransformFailed = capitan.NewSignal(
    "flux.capacitor.transform.failed",
    "Transform function failed",
)

Fields:

  • KeyError - Error message

CapacitorValidationFailed

Emitted when struct validation fails.

var CapacitorValidationFailed = capitan.NewSignal(
    "flux.capacitor.validation.failed",
    "Validation failed",
)

Fields:

  • KeyError - Validation error message

CapacitorApplyFailed

Emitted when the callback returns an error.

var CapacitorApplyFailed = capitan.NewSignal(
    "flux.capacitor.apply.failed",
    "Apply function failed",
)

Fields:

  • KeyError - Error message

CapacitorApplySucceeded

Emitted when configuration is successfully applied.

var CapacitorApplySucceeded = capitan.NewSignal(
    "flux.capacitor.apply.succeeded",
    "Config applied successfully",
)

Fields: None

Field Keys

KeyState

Current state of the Capacitor.

var KeyState = capitan.NewStringKey("state")

Type: stringValues: "loading", "healthy", "degraded", "empty"

KeyOldState

Previous state before a transition.

var KeyOldState = capitan.NewStringKey("old_state")

Type: string

KeyNewState

New state after a transition.

var KeyNewState = capitan.NewStringKey("new_state")

Type: string

KeyError

Error message when an operation fails.

var KeyError = capitan.NewStringKey("error")

Type: string

KeyDebounce

Configured debounce duration.

var KeyDebounce = capitan.NewDurationKey("debounce")

Type: time.Duration

Usage Examples

Logging All Errors

func setupErrorLogging() {
    handler := func(ctx context.Context, e *capitan.Event) {
        errMsg, _ := flux.KeyError.From(e)
        log.Printf("[%s] %s", e.Signal.Name(), errMsg)
    }

    capitan.Hook(flux.CapacitorTransformFailed, handler)
    capitan.Hook(flux.CapacitorValidationFailed, handler)
    capitan.Hook(flux.CapacitorApplyFailed, handler)
}

Metrics

func setupMetrics() {
    capitan.Hook(flux.CapacitorStateChanged, func(ctx context.Context, e *capitan.Event) {
        newState, _ := flux.KeyNewState.From(e)
        metrics.Gauge("config_state", stateToNumber(newState))
    })

    capitan.Hook(flux.CapacitorApplySucceeded, func(ctx context.Context, e *capitan.Event) {
        metrics.Increment("config_applies_total")
    })

    capitan.Hook(flux.CapacitorApplyFailed, func(ctx context.Context, e *capitan.Event) {
        metrics.Increment("config_apply_failures_total")
    })
}

State Transition Tracking

capitan.Hook(flux.CapacitorStateChanged, func(ctx context.Context, e *capitan.Event) {
    old, _ := flux.KeyOldState.From(e)
    new, _ := flux.KeyNewState.From(e)

    log.Printf("state transition: %s -> %s", old, new)

    if new == flux.StateDegraded.String() {
        alerting.Send("config update failed")
    }

    if old == flux.StateDegraded.String() && new == flux.StateHealthy.String() {
        alerting.Resolve("config update failed")
    }
})

Change Detection

capitan.Hook(flux.CapacitorChangeReceived, func(ctx context.Context, e *capitan.Event) {
    log.Println("configuration change detected")
    metrics.Increment("config_changes_received_total")
})

Signal Flow

Typical signal sequence for a successful update:

CapacitorChangeReceived
    ↓
CapacitorApplySucceeded
    ↓
CapacitorStateChanged (if state changed)

For a failed update:

CapacitorChangeReceived
    ↓
CapacitorTransformFailed / CapacitorValidationFailed / CapacitorApplyFailed
    ↓
CapacitorStateChanged (healthy -> degraded, or loading -> empty)

Next Steps