protoconf_loader

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2024 License: MIT Imports: 14 Imported by: 0

README

project-logo

Protoconf GOLANG client

codify configuration, instant delivery

license last-commit


Table of Contents

📍 Overview

protoconf_loader is a Go package that provides a flexible and robust configuration management solution.
It supports loading configuration from files, watching for file changes, and subscribing to configuration updates from a Protoconf server.


🧩 Features

  • Load configuration from files
  • Watch configuration files for changes
  • Subscribe to configuration updates from a Protoconf server
  • Hot Reload of configuration changes
  • Thread-safe access to configuration values
  • Support for various data types (int32, int64, uint32, uint64, float32, float64, bool, string)
  • Custom error handling and logging

⚙️ Installation

To install the package, use the following command:

go get github.com/protoconf/client-go

🤖 Usage

Here's a basic example of how to use the protoconf_loader:

package main

import (
    "context"
    "log"

    "github.com/protoconf/client-go/"
    "github.com/protoconf/protoconf/examples/protoconf/src/crawler"
    "google.golang.org/protobuf/proto"
)

func main() {
    // Initialize the configuration with the default configuration.
    crawlerConfig := &crawler.CrawlerService{LogLevel: 3}
    // Create a new configuration instance
    cfg, err := protoconf_loader.NewConfiguration(crawlerConfig, "path/to/config")
    if err != nil {
        log.Fatalf("Failed to create configuration: %v", err)
    }

    // Load the configuration
    err = cfg.LoadConfig("path/to/config", "config_file_name")
    if err != nil {
        log.Fatalf("Failed to load configuration: %v", err)
    }

    config.OnConfigChange(func(c proto.Message) {
		log("got new config",c)
	})
    // Start watching for changes
    err = config.WatchConfig(context.Background())
    if err != nil {
        log.Fatalf("Failed to start watching configuration: %v", err)
    }


    // Stop watching when done
    cfg.StopWatching()
}

🤝 Contributing

Contributions are welcome! Here are several ways you can contribute:

🎗 License

This project is protected under the MIT License.
For more details, refer to the LICENSE file.

Documentation

Index

Examples

Constants

View Source
const (
	AgentDefaultAddress = ":4300"
)

Variables

This section is empty.

Functions

func Get

func Get[T any](c *Configuration, f func() T) T

Get returns the result of the given function.

Types

type Configuration

type Configuration struct {
	UnmarshalOptions protojson.UnmarshalOptions

	CancelAgent context.CancelFunc
	Host        string
	Port        int
	// contains filtered or unexported fields
}
Example
// Initialize the configuration with the default configuration.
crawlerConfig := &crawler.CrawlerService{LogLevel: 3}

// Create a new mock agent.
mock := mockagent.NewProtoconfAgentMock(crawlerConfig)

// Create a new configuration with the crawler config and the mock agent.
config, err := NewConfiguration(crawlerConfig, "crawler/config", WithAgentStub(mock.Stub))
if err != nil {
	log.Fatalf("Error creating configuration: %v", err)
}

// Start the configuration watcher.
err = config.WatchConfig(context.Background())
if err != nil {
	log.Fatal(err)
}

// Mock a configuration update.
mock.SendUpdate(&crawler.CrawlerService{LogLevel: 17})
// Wait for the configuration to be updated.
time.Sleep(1 * time.Millisecond)

fmt.Printf("Config changed: %v", crawlerConfig)
Output:

Config changed: log_level:17
Example (ConcurrencySafety)
// Initialize the configuration with the default configuration.
config := func() *atomic.Pointer[crawler.CrawlerService] {
	crawlerConfig := &crawler.CrawlerService{LogLevel: 3}
	configHolder := &atomic.Pointer[crawler.CrawlerService]{}
	configHolder.Store(crawlerConfig)

	// Create a new mock agent.
	mock := mockagent.NewProtoconfAgentMock(crawlerConfig)

	// Create a new configuration with the crawler config and the mock agent.
	config, err := NewConfiguration(crawlerConfig, "crawler/config", WithAgentStub(mock.Stub))
	if err != nil {
		log.Fatalf("Error creating configuration: %v", err)
	}

	// Start the configuration watcher.
	err = config.WatchConfig(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	// Update the configuration holder when the configuration changes.
	config.OnConfigChange(func(c proto.Message) {
		configHolder.Store(c.(*crawler.CrawlerService))
	})
	mock.SendUpdate(&crawler.CrawlerService{LogLevel: 18})
	return configHolder
}()

// Mock a configuration update.
// Wait for the configuration to be updated.
time.Sleep(1 * time.Millisecond)

// Receive the configuration update.
fmt.Printf("Config changed: %v", config.Load())
Output:

Config changed: log_level:18
Example (WatchConfigOnDisk)
crawlerConfig := &crawler.CrawlerService{LogLevel: 3}
tempDir := os.TempDir()
configFilePath := filepath.Join(tempDir, "crawler_config.json")
os.WriteFile(configFilePath, []byte("{\"logLevel\": 3}"), 0644)

config, err := NewConfiguration(crawlerConfig, "crawler/config")
if err != nil {
	log.Fatalf("Error creating configuration: %v", err)
}
config.LoadConfig(tempDir, "crawler_config.json")
fmt.Println("Config loaded from disk:", crawlerConfig)

config.WatchConfig(context.Background())

os.WriteFile(configFilePath, []byte("{\"logLevel\": 4}"), 0644)
time.Sleep(1 * time.Millisecond)

fmt.Println("Config updated on disk:", crawlerConfig)
Output:

Config loaded from disk: log_level:3
Config updated on disk: log_level:4

func NewConfiguration

func NewConfiguration(p proto.Message, configPath string, opts ...Option) (*Configuration, error)

NewConfiguration creates a new Configuration instance with the given proto.Message, config path and optional options. It initializes the fsnotify watcher, sets the unmarshal options, and initializes other fields. If any error occurs during the watcher creation, it returns an error.

func (*Configuration) Any

func (c *Configuration) Any(f func() any) any

func (*Configuration) Bool

func (c *Configuration) Bool(f func() bool) bool

func (*Configuration) Float32

func (c *Configuration) Float32(f func() float32) float32

func (*Configuration) Float64

func (c *Configuration) Float64(f func() float64) float64

func (*Configuration) Int32

func (c *Configuration) Int32(f func() int32) int32

func (*Configuration) Int64

func (c *Configuration) Int64(f func() int64) int64

func (*Configuration) LoadConfig

func (c *Configuration) LoadConfig(configPath string, configName string) error

LoadConfig loads the configuration from the specified configPath and configName. If the configuration is already loaded, it returns nil without doing anything. It sets the configFile field to the joined path of configPath and configName, then calls the loadConfig method to actually load the configuration. Finally, it sets the isLoaded field to true and returns nil. If there is an error during loading the configuration, it returns the error.

func (*Configuration) OnConfigChange

func (c *Configuration) OnConfigChange(run func(p proto.Message))

OnConfigChange sets the event handler that is called when a config file changes.

Example
// Initialize the configuration with the default configuration.
crawlerConfig := &crawler.CrawlerService{LogLevel: 3}

// Create a new mock agent.
mock := mockagent.NewProtoconfAgentMock(crawlerConfig)

// Create a new configuration with the crawler config and the mock agent.
config, err := NewConfiguration(crawlerConfig, "crawler/config", WithAgentStub(mock.Stub))
if err != nil {
	log.Fatalf("Error creating configuration: %v", err)
}

// Start the configuration watcher.
err = config.WatchConfig(context.Background())
if err != nil {
	log.Fatal(err)
}

// Create a channel to receive configuration updates.
configUpdates := make(chan *crawler.CrawlerService)
config.OnConfigChange(func(c proto.Message) {
	configUpdates <- c.(*crawler.CrawlerService)
})

// Mock a configuration update.
mock.SendUpdate(&crawler.CrawlerService{LogLevel: 17})
// Wait for the configuration to be updated.
time.Sleep(1 * time.Millisecond)

// Receive the configuration update.
newConfig := <-configUpdates
fmt.Printf("Config changed: %v", newConfig)
Output:

Config changed: log_level:17

func (*Configuration) StopWatching

func (c *Configuration) StopWatching()

StopWatching stops watching the configuration file and the agent for changes. It closes the fsnotifyWatcher and cancels the context for the agent connection.

func (*Configuration) String

func (c *Configuration) String(f func() string) string

func (*Configuration) UInt32

func (c *Configuration) UInt32(f func() uint32) uint32

func (*Configuration) UInt64

func (c *Configuration) UInt64(f func() uint64) uint64

func (*Configuration) WatchConfig

func (c *Configuration) WatchConfig(ctx context.Context) error

WatchConfig starts watching the configuration file and the agent for changes. It returns an error if the configuration is not loaded yet. It watches for file changes and agent updates using separate goroutines. The method logs the successful start of watching and returns nil upon successful completion.

func (*Configuration) WithLock

func (c *Configuration) WithLock(f func() error) error

Atomic executes the given function atomically.

type Option

type Option func(*Configuration)

func WithAgentStub

func WithAgentStub(stub pc.ProtoconfServiceClient) Option

func WithLogger

func WithLogger(logger *slog.Logger) Option

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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