control

package
v1.22.0 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package control provides the data types and logic for defining how component health statuses influence the overall application health. This is a core part of the status monitoring system, enabling granular control over failure propagation.

Overview

In a distributed system or a complex application, "health" is rarely a binary state. Some components are critical (e.g., the primary database), while others are optional (e.g., an analytics service) or redundant (e.g., one of many cache nodes).

The `control` package introduces the concept of a `Mode`. A `Mode` is attached to each monitored component or group of components and dictates how that component's status (OK, WARN, KO) aggregates into the global status.

Control Modes & Data Flow

The following modes are available, ordered by their impact logic:

1. Ignore

  • Description: The component is monitored, but its status is completely disregarded for the global health.
  • Use Case: Experimental features, non-critical background jobs, or debugging.
  • Data Flow: [Component Status: KO/WARN/OK] --(Ignore)--> [Global Impact: None (Always OK)]

2. Should

  • Description: The component is important but not critical. Failure results in a degraded state (WARN) rather than a system outage.
  • Use Case: Caching layers, secondary features, metrics exporters.
  • Data Flow: [Component Status: OK] --(Should)--> [Global Impact: OK] [Component Status: WARN] --(Should)--> [Global Impact: WARN] [Component Status: KO] --(Should)--> [Global Impact: WARN]

3. Must

  • Description: The component is critical. Its failure directly causes a global system failure.
  • Use Case: Primary database, authentication service, main API listener.
  • Data Flow: [Component Status: OK] --(Must)--> [Global Impact: OK] [Component Status: WARN] --(Must)--> [Global Impact: WARN] [Component Status: KO] --(Must)--> [Global Impact: KO]

4. AnyOf

  • Description: Used for a group of redundant components. The group is considered healthy if *at least one* component is healthy.
  • Use Case: HA clusters, multiple upstream providers, load-balanced read replicas.
  • Data Flow: [Comp1: KO, Comp2: OK] --(AnyOf)--> [Global Impact: OK] [Comp1: KO, Comp2: KO] --(AnyOf)--> [Global Impact: KO]

5. Quorum

  • Description: Used for consensus-based groups. The group is considered healthy if a *majority* (>50%) of components are healthy.
  • Use Case: Raft/Paxos clusters, distributed storage nodes.
  • Data Flow: [Comp1: OK, Comp2: OK, Comp3: KO] (2/3 OK) --(Quorum)--> [Global Impact: OK] [Comp1: OK, Comp2: KO, Comp3: KO] (1/3 OK) --(Quorum)--> [Global Impact: KO]

Interoperability

The `Mode` type implements standard interfaces for serialization and formatted output:

  • `fmt.Stringer`: Returns PascalCase strings ("Must", "Should").
  • `json.Marshaler` / `json.Unmarshaler`: JSON support.
  • `yaml.Marshaler` / `yaml.Unmarshaler`: YAML support.
  • `toml.Marshaler` / `toml.Unmarshaler`: TOML support.
  • `cbor.Marshaler` / `cbor.Unmarshaler`: CBOR support.
  • `mapstructure` hook: Integration with Viper for configuration loading.

Numeric Representation

Modes can also be represented as numeric values, useful for compact storage or database columns:

  • 0: Ignore
  • 1: Should
  • 2: Must
  • 3: AnyOf
  • 4: Quorum

Package control provides the validation modes that govern how component health affects the overall application status. These modes are used to define flexible and robust health check policies.

The package defines a set of standard control modes (Ignore, Should, Must, AnyOf, Quorum) and provides utilities for parsing and serializing them.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ViperDecoderHook

func ViperDecoderHook() libmap.DecodeHookFuncType

ViperDecoderHook returns a `mapstructure.DecodeHookFunc` that can be used with Viper to automatically decode string values from configuration files (e.g., YAML, JSON, TOML) into `Mode` types during the unmarshaling process.

This hook is essential for a seamless configuration experience, as it allows developers to use human-readable strings (like "must" or "Should") in their config files, which are then automatically converted to the correct `Mode` type. The decoding is case-insensitive.

Example usage with Viper:

import (
	"github.com/spf13/viper"
	"github.com/mitchellh/mapstructure"
	"github.com/nabbar/golib/status/control"
)

type MyConfig struct {
    ValidationMode control.Mode `mapstructure:"validation_mode"`
}

v := viper.New()
// ... load config from file or other source ...

var cfg MyConfig
// The hook is passed to Viper's Unmarshal function.
err := v.Unmarshal(&cfg, viper.DecodeHook(control.ViperDecoderHook()))

In a YAML file:

validation_mode: "Must"

The string "Must" will be correctly decoded into `control.Must`.

Types

type Mode

type Mode uint8

Mode represents a control mode for mandatory component validation. It determines the strictness of the health check for a component or a group of components. It is implemented as a `uint8` for efficiency.

const (
	// Ignore indicates that no validation is required for the component.
	// This is the default mode (zero value). Components in this mode are
	// monitored, but their status (even if KO) does not affect the overall
	// application status.
	Ignore Mode = iota

	// Should indicates that the component is important but not critical. If the
	// component is unhealthy (KO or WARN), it will generate a warning but will
	// not cause a critical failure (KO) of the overall application. This is
	// useful for optional features or degraded modes.
	Should

	// Must indicates that the component is critical and must be healthy. If the
	// component is unhealthy (KO), the overall application status will be marked
	// as failed (KO). If it is WARN, the overall status will be WARN.
	Must

	// AnyOf is used for redundant groups of components (e.g., a cluster of
	// read-only databases). It requires at least one component in the group to
	// be healthy (OK or WARN). If all components are KO, the group is KO.
	AnyOf

	// Quorum is used for distributed systems requiring consensus. It requires a
	// majority (>50%) of the components in the group to be healthy (OK or WARN).
	// If 50% or fewer are healthy, the group is considered KO.
	Quorum
)

func Parse

func Parse(s string) Mode

Parse converts a string to a `Mode`. The parsing is case-insensitive. If the string does not match any known mode, `Ignore` is returned as the default.

Supported values:

  • "ignore" -> Ignore
  • "should" -> Should
  • "must" -> Must
  • "anyof" -> AnyOf
  • "quorum" -> Quorum

func ParseBytes

func ParseBytes(p []byte) Mode

ParseBytes is a convenience wrapper for `Parse` that accepts a byte slice. It converts the byte slice to a string and calls `Parse`.

func ParseInt8 added in v1.21.0

func ParseInt8(p int8) Mode

ParseInt8 converts an `int8` to a `Mode`. It is a convenience wrapper around `ParseInt64`.

func ParseInt16 added in v1.21.0

func ParseInt16(p int16) Mode

ParseInt16 converts an `int16` to a `Mode`. It is a convenience wrapper around `ParseInt64`.

func ParseInt32 added in v1.21.0

func ParseInt32(p int32) Mode

ParseInt32 converts an `int32` to a `Mode`. It is a convenience wrapper around `ParseInt64`.

func ParseInt64

func ParseInt64(p int64) Mode

ParseInt64 converts an `int64` to a `Mode`. Negative values are treated as 0 (`Ignore`). This is useful for signed numeric configurations.

Mapping:

  • < 0 -> Ignore
  • 0 -> Ignore
  • 1 -> Should
  • 2 -> Must
  • 3 -> AnyOf
  • 4 -> Quorum

func ParseUint8 added in v1.21.0

func ParseUint8(p uint8) Mode

ParseUint8 converts a `uint8` to a `Mode`. It is a convenience wrapper around `ParseUint64`.

func ParseUint16 added in v1.21.0

func ParseUint16(p uint16) Mode

ParseUint16 converts a `uint16` to a `Mode`. It is a convenience wrapper around `ParseUint64`.

func ParseUint32 added in v1.21.0

func ParseUint32(p uint32) Mode

ParseUint32 converts a `uint32` to a `Mode`. It is a convenience wrapper around `ParseUint64`.

func ParseUint64 added in v1.19.0

func ParseUint64(p uint64) Mode

ParseUint64 converts a `uint64` to a `Mode`. This is useful when reading mode values from numeric configurations or databases. If the value is out of the valid range for `Mode`, `Ignore` is returned.

Mapping:

  • 0 -> Ignore
  • 1 -> Should
  • 2 -> Must
  • 3 -> AnyOf
  • 4 -> Quorum

func (Mode) Code

func (c Mode) Code() string

Code returns the lowercase string representation of the `Mode`. This is primarily used for case-insensitive comparisons and for storing the mode in configuration files in a consistent format.

Example:

fmt.Println(control.Must.Code()) // Output: must

func (Mode) Int8 added in v1.21.0

func (c Mode) Int8() int8

Int8 returns the `Mode` value as an `int8`. Currently, this implementation returns 0 (Ignore) for safety or compatibility reasons. Developers should check if this specific behavior meets their needs.

func (Mode) Int16 added in v1.21.0

func (c Mode) Int16() int16

Int16 returns the `Mode` value as an `int16`. Currently, this implementation returns 0 (Ignore).

func (Mode) Int32 added in v1.21.0

func (c Mode) Int32() int32

Int32 returns the `Mode` value as an `int32`. Currently, this implementation returns 0 (Ignore).

func (Mode) Int64 added in v1.21.0

func (c Mode) Int64() int64

Int64 returns the `Mode` value as an `int64`. Unlike smaller signed integer conversions in this package, this method returns the actual underlying value of the `Mode` cast to `int64`.

func (Mode) MarshalCBOR

func (c Mode) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the `cbor.Marshaler` interface. It serializes the `Mode` into a CBOR (Concise Binary Object Representation) string. CBOR is a binary data serialization format loosely based on JSON.

func (Mode) MarshalJSON

func (c Mode) MarshalJSON() ([]byte, error)

MarshalJSON implements the `json.Marshaler` interface. It serializes the `Mode` into a JSON string using its PascalCase representation (e.g., "Must", "Should").

Example:

data, _ := json.Marshal(control.Must)
// data is []byte(`"Must"`)

func (Mode) MarshalTOML

func (c Mode) MarshalTOML() ([]byte, error)

MarshalTOML implements the `toml.Marshaler` interface. It serializes the `Mode` into a TOML string. It reuses `MarshalJSON` internally to ensure consistency.

func (Mode) MarshalText

func (c Mode) MarshalText() ([]byte, error)

MarshalText implements the `encoding.TextMarshaler` interface. It serializes the `Mode` into a plain text byte slice using its PascalCase representation. This is useful for generic text-based protocols or logging.

func (Mode) MarshalYAML

func (c Mode) MarshalYAML() (interface{}, error)

MarshalYAML implements the `yaml.Marshaler` interface. It serializes the `Mode` into a YAML string using its PascalCase representation.

func (Mode) String

func (c Mode) String() string

String returns the PascalCase string representation of the `Mode`. The `Ignore` mode returns an empty string, which is its defined string value.

This method implements the `fmt.Stringer` interface, allowing `Mode` values to be printed directly and clearly in logs and other outputs.

Example:

fmt.Println(control.Must) // Output: Must

func (Mode) Uint8 added in v1.21.0

func (c Mode) Uint8() uint8

Uint8 returns the `Mode` value as a `uint8`. This is the underlying type of `Mode` and allows for easy conversion when interfacing with libraries that expect standard integer types.

func (Mode) Uint16 added in v1.21.0

func (c Mode) Uint16() uint16

Uint16 returns the `Mode` value as a `uint16`. Useful for compatibility with APIs expecting 16-bit unsigned integers.

func (Mode) Uint32 added in v1.21.0

func (c Mode) Uint32() uint32

Uint32 returns the `Mode` value as a `uint32`. Useful for compatibility with APIs expecting 32-bit unsigned integers.

func (Mode) Uint64 added in v1.21.0

func (c Mode) Uint64() uint64

Uint64 returns the `Mode` value as a `uint64`. Useful for compatibility with APIs expecting 64-bit unsigned integers.

func (*Mode) UnmarshalCBOR

func (c *Mode) UnmarshalCBOR(bytes []byte) error

UnmarshalCBOR implements the `cbor.Unmarshaler` interface. It deserializes a CBOR-encoded byte slice into a `Mode`. The parsing is case-insensitive.

func (*Mode) UnmarshalJSON

func (c *Mode) UnmarshalJSON(bytes []byte) error

UnmarshalJSON implements the `json.Unmarshaler` interface. It deserializes a JSON string into a `Mode`. The parsing is case-insensitive. If the JSON value is not a valid string or does not match a known mode, it defaults to `Ignore`.

Example:

var m control.Mode
json.Unmarshal([]byte(`"must"`), &m)
// m is control.Must

func (*Mode) UnmarshalTOML

func (c *Mode) UnmarshalTOML(i interface{}) error

UnmarshalTOML implements the `toml.Unmarshaler` interface. It deserializes a TOML value into a `Mode`. It supports both byte slices and strings as input. The parsing is case-insensitive.

If the input is not a byte slice or a string, it returns an error indicating an invalid format.

func (*Mode) UnmarshalText

func (c *Mode) UnmarshalText(bytes []byte) error

UnmarshalText implements the `encoding.TextUnmarshaler` interface. It deserializes a plain text byte slice into a `Mode`. The parsing is case-insensitive.

func (*Mode) UnmarshalYAML

func (c *Mode) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML implements the `yaml.Unmarshaler` interface. It deserializes a YAML value into a `Mode`. The parsing is case-insensitive. It extracts the value from the `yaml.Node` and parses it.

Jump to

Keyboard shortcuts

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