process_settings

package module
v0.0.0-...-ffc343d Latest Latest
Warning

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

Go to latest
Published: May 2, 2023 License: MIT Imports: 8 Imported by: 0

README

Process Settings

This is the golang implementation of the process_settings library originally written in Ruby. The overall functionality of the library is the same, but due to the nature of Golang, the implementation is slightly different. Please read through the documentation below to understand how to use this library in your project.

Installation

To install this library, run the following command:

go get github.com/Invoca/process_settings.go

Usage

The process_settings.ProcessSettings object can be freely created and used at any time. But typical usage is through the global instance that should be configured at the start of your process.

Basic Configuration

Before using the global instance, you must first set it by assigning a process_settings.ProcessSettings object to it.

import (
    "github.com/Invoca/process_settings.go"
)

func main() {
    process_settings.SetGlobalProcessSettings(
      process_settings.NewProcessSettingsFromFile("/etc/process_settings/combined_process_settings.yml")
    )
}
Configuration with Static Context

When initializing a new process_settings.ProcessSettings object, you can provide a map[string]instance{} of static context. This context will be used to select the settings that are specifically targeted for your process. For example, if you're running multiple services, you might want to target settings to a specific service.

import (
    "github.com/Invoca/process_settings.go"
)

func main() {
    ps, err := process_settings.NewProcessSettingsFromFile(
        "/etc/process_settings/combined_process_settings.yml",
        map[string]instance{}{
            "service_name": "frontend",
            "datacenter": "AWS-US-EAST-1",
        }
    )

    if err != nil {
        panic(err)
    }

    process_settings.SetGlobalProcessSettings(ps)
}
Reading Settings

For the following section, consider the combined_process_settings.yml file:

---
- filename: frontend.yml
  settings:
    frontend:
      log_level: info
- filename: frontend-microsite.yml
  target:
    domain: microsite.example.com
  settings:
    frontend:
      log_level: debug
- meta:
    version: 27
    END: true

To read a setting, application code should call the process_settings.Get() method. For example:

log_level := process_settings.Get("frontend", "log_level")
Dynamic Settings

The process_settings.ProcessSettings object has a Monitor built in that loads settings changes dynamically whenever the file changes, by using the fsnotify library which in turn uses the INotify module of the Linux kernel, or FSEvents on MacOS. There is no need to restart the process or send it a signal to tell it to reload changes.

To start the monitor goroutine, call the StartMonitor() method on the process_settings.ProcessSettings object.

func main() {
    ps, err := process_settings.NewProcessSettingsFromFile(
        "/etc/process_settings/combined_process_settings.yml",
        map[string]instance{}{
            "service_name": "frontend",
            "datacenter": "AWS-US-EAST-1",
        }
    )

    if err != nil {
        panic(err)
    }

    process_settings.SetGlobalProcessSettings(ps)
    ps.StartMonitor()
}
Read Latest Settings Through process_settings.Get() and process_settings.SafeGet()

The simplest approach--as shown above--is to read the latest settings at any time through process_settings.Get() and process_settings.SafeGet() (which delegates to process_settings.instance):

http_version := process_settings.Get('frontend', 'http_version')
Register a WhenUpdated Callback

Alternatively, if you need to execute initially and whenever the value is updated, register a callback with process_settings.WhenUpdated():

process_settings.WhenUpdated(func() {
    logger.level = process_settings.Get("frontend", "log_level")
})

By default, the WhenUpdated func is called initially when registered. We've found this to be convenient in most cases; it can be disabled by passing an optional second argument false, in which case the block will be called 0 or more times in the future, when any of the process settings for this process change.

WhenUpdated is not idempotent, so adding the same func multiple times will result in multiple registered callbacks doing the same operation.

In case you need to cancel the callback later, WhenUpdated returns a handle (the index of the registered func) which can later be passed into CancelWhenUpdated.

Note that all callbacks run sequentially on the shared change monitoring thread, so please be considerate!

Targeting

Each settings YAML file has an optional target key at the top level, next to settings.

If there is no target key, the target defaults to true, meaning all processes are targeted for these settings. (However, the settings may be overridden by other YAML files. See "Precedence" below.)

Hash Key-Values Are AND'd

To target on context values, provide a hash of key-value pairs. All keys must match for the target to be met. For example, consider this target hash:

target:
  service_name: frontend
  datacenter: AWS-US-EAST-1

This will be applied in any process that has service_name == "frontend" AND is running in datacenter == "AWS-US-EAST-1".

Multiple Values Are OR'd

Values may be set to an array, in which case the key matches if any of the values matches. For example, consider this target hash:

target:
  service_name: [frontend, auth]
  datacenter: AWS-US-EAST-1

This will be applied in any process that has (service_name == "frontend" OR service_name == "auth") AND datacenter == "AWS-US-EAST-1".

Precedence

The settings YAML files are always combined in alphabetical order by file path. Later settings take precedence over the earlier ones.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Documentation

Overview

Package process_settings implements dynamic settings for the process.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CancelWhenUpdated

func CancelWhenUpdated(index int) error

CancelWhenUpdated cancels a function that was registered on the global ProcessSettings instance using WhenUpdated. If the global instance has not been set, an error is returned.

func Get

func Get(settingPath ...string) (interface{}, error)

Get returns the value of a setting based on the current targeting. If the global instance has not been set, or the requested setting is not found, an error is returned.

func SafeGet

func SafeGet(settingPath ...string) (interface{}, error)

SafeGet returns the value of a setting based on the current targeting. If the global instance has not been set, or the requested setting is not found, nil is returned.

func SetGlobalProcessSettings

func SetGlobalProcessSettings(settings *ProcessSettings)

SetGlobalProcessSettings sets the global process settings instance to be used by the rest of the process.

func WhenUpdated

func WhenUpdated(fn func(), initial_update ...bool) (int, error)

WhenUpdated registers a function to be called when the settings are updated on the global ProcessSettings instance. If the global instance has not been set, an error is returned.

Types

type ProcessSettings

type ProcessSettings struct {
	FilePath            string            // The path to the settings file that was used to create the ProcessSettings
	Settings            *[]SettingsFile   // The settings files that make up the ProcessSettings
	TargetEvaluator     TargetEvaluator   // The target evaluator that is used to determine which settings files are applicable
	Monitor             *fsnotify.Watcher // The file monitor that is used to detect changes to the settings file
	WhenUpdatedRegistry []func()          // A list of functions to call when the settings are updated
}

A ProcessSettings is a collection of settings files and a target evaluator that can be used to get the value of a settings based on the current targeting.

func NewProcessSettingsFromFile

func NewProcessSettingsFromFile(filePath string, staticContext map[string]interface{}) (*ProcessSettings, error)

NewProcessSettingsFromFile creates a new instance of ProcessSettings by loading the settings from a specified file path and using the specified static context to evaluate the targeting.

func (*ProcessSettings) CancelWhenUpdated

func (ps *ProcessSettings) CancelWhenUpdated(index int)

CancelWhenUpdated cancels a function that was registered using WhenUpdated.

func (*ProcessSettings) Get

func (ps *ProcessSettings) Get(settingPath ...string) (interface{}, error)

Get returns the value of a setting based on the current targeting. If the requested setting is not found, an error is returned.

func (*ProcessSettings) SafeGet

func (ps *ProcessSettings) SafeGet(settingPath ...string) (interface{}, error)

SafeGet returns the value of a setting based on the current targeting. If the requested setting is not found, nil is returned.

func (*ProcessSettings) StartMonitor

func (ps *ProcessSettings) StartMonitor()

StartMonitor starts a goroutine that monitors the settings file for changes

func (*ProcessSettings) WhenUpdated

func (ps *ProcessSettings) WhenUpdated(fn func(), initial_update ...bool) int

WhenUpdated registers a function to be called when the settings are updated and by default calls the function immediately. Optionally false can be passed as the second argument to not call the function immediately. The function returns an index that can be used to cancel the function using CancelWhenUpdated.

type SettingNotFound

type SettingNotFound struct {
	SettingPath []string
}

func (*SettingNotFound) Error

func (e *SettingNotFound) Error() string

type SettingsFile

type SettingsFile struct {
	FileName string                 `yaml:"filename"`
	Target   map[string]interface{} `yaml:"target"`
	Settings map[string]interface{} `yaml:"settings"`
	Metadata SettingsMetadata       `yaml:"meta"`
}

type SettingsMetadata

type SettingsMetadata struct {
	Version int  `yaml:"version"`
	End     bool `yaml:"END"`
}

type TargetEvaluator

type TargetEvaluator struct {
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

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