discovery

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Nov 6, 2025 License: MIT Imports: 13 Imported by: 0

README

Service Discovery Extension

Enterprise-grade service discovery and registry for distributed Forge applications.

Features

  • Multiple Backends - Consul, etcd, Kubernetes, Eureka, in-memory
  • Service Registration - Automatic service registration on startup
  • Health Checks - Continuous health monitoring
  • Service Discovery - Find services by name, tags, health status
  • Load Balancing - Round-robin, random, weighted strategies
  • Service Watching - Real-time notifications of service changes
  • Auto-Deregistration - Automatic cleanup on shutdown

Installation

go get github.com/xraph/forge/extensions/discovery

Quick Start

Basic Usage

package main

import (
    "github.com/xraph/forge"
    "github.com/xraph/forge/extensions/discovery"
)

func main() {
    app := forge.NewApp(forge.AppConfig{
        Extensions: []forge.Extension{
            discovery.NewExtension(
                discovery.WithEnabled(true),
                discovery.WithBackend("memory"),
                discovery.WithServiceName("my-api"),
                discovery.WithServiceAddress("localhost", 8080),
                discovery.WithServiceTags("api", "v1"),
                discovery.WithHTTPHealthCheck("http://localhost:8080/_/health", 10*time.Second),
            ),
        },
    })

    // Get discovery service
    discoveryService := forge.Must[*discovery.Service](app.Container(), "discovery.Service")

    // Discover other services
    router := app.Router()
    router.GET("/call-user-service", func(ctx forge.Context) error {
        // Find a healthy user-service instance
        instance, err := discoveryService.SelectInstance(
            ctx.Context(),
            "user-service",
            discovery.LoadBalanceRoundRobin,
        )
        if err != nil {
            return err
        }

        // Make request to selected instance
        url := instance.URL("http") + "/users"
        resp, err := http.Get(url)
        // ...
    })

    app.Run()
}

Configuration

YAML Configuration

extensions:
  discovery:
    enabled: true
    backend: "consul"

    # Service configuration
    service:
      name: "my-api"
      version: "1.0.0"
      address: "10.0.1.5"
      port: 8080
      tags:
        - "api"
        - "v1"
      metadata:
        region: "us-east-1"
        environment: "production"
      enable_auto_deregister: true

    # Health check configuration
    health_check:
      enabled: true
      interval: 10s
      timeout: 5s
      deregister_critical_service_after: 1m
      http: "http://localhost:8080/_/health"

    # Watch configuration
    watch:
      enabled: true
      services:
        - "user-service"
        - "payment-service"
      tags:
        - "production"

    # Consul backend
    consul:
      address: "consul.company.com:8500"
      token: "${CONSUL_TOKEN}"
      datacenter: "dc1"
      tls_enabled: true

Programmatic Configuration

discovery.NewExtension(
    discovery.WithEnabled(true),
    discovery.WithConsul("consul.company.com:8500", os.Getenv("CONSUL_TOKEN")),
    discovery.WithService(discovery.ServiceConfig{
        Name:     "my-api",
        Version:  "1.0.0",
        Address:  "10.0.1.5",
        Port:     8080,
        Tags:     []string{"api", "v1"},
        Metadata: map[string]string{
            "region": "us-east-1",
        },
    }),
    discovery.WithHTTPHealthCheck("http://localhost:8080/_/health", 10*time.Second),
)

Usage Examples

Service Registration

// Automatic registration on app startup
// Service is automatically registered when extension starts

// Manual registration
instance := &discovery.ServiceInstance{
    ID:       "my-api-1",
    Name:     "my-api",
    Version:  "1.0.0",
    Address:  "10.0.1.5",
    Port:     8080,
    Tags:     []string{"api"},
    Metadata: map[string]string{"region": "us-east-1"},
}

err := service.Register(ctx, instance)

Service Discovery

// Discover all instances of a service
instances, err := service.Discover(ctx, "user-service")
if err != nil {
    return err
}

for _, instance := range instances {
    fmt.Printf("Found: %s at %s:%d\n", instance.ID, instance.Address, instance.Port)
}

Discover with Tags

// Discover only services with specific tags
instances, err := service.DiscoverWithTags(ctx, "user-service", []string{"production", "v2"})

Discover Healthy Services

// Discover only healthy instances
instances, err := service.DiscoverHealthy(ctx, "user-service")

Load Balancing

// Select a single instance using round-robin
instance, err := service.SelectInstance(
    ctx,
    "user-service",
    discovery.LoadBalanceRoundRobin,
)

// Get service URL
url, err := service.GetServiceURL(
    ctx,
    "user-service",
    "http",
    discovery.LoadBalanceRandom,
)

Service Watching

// Watch for service changes
err := service.Watch(ctx, "user-service", func(instances []*discovery.ServiceInstance) {
    logger.Info("user-service instances changed",
        forge.F("count", len(instances)),
    )

    // Update load balancer pool
    updatePool(instances)
})

Backends

Memory Backend (Development)

discovery.NewExtension(
    discovery.WithBackend("memory"),
)

Consul Backend

discovery.NewExtension(
    discovery.WithConsul("consul.company.com:8500", os.Getenv("CONSUL_TOKEN")),
)

etcd Backend

discovery.NewExtension(
    discovery.WithEtcd([]string{
        "etcd1.company.com:2379",
        "etcd2.company.com:2379",
        "etcd3.company.com:2379",
    }),
)

Kubernetes Backend

discovery.NewExtension(
    discovery.WithKubernetes("default", true), // namespace, in-cluster
)

Eureka Backend

discovery.NewExtension(
    discovery.WithEureka([]string{
        "http://eureka1.company.com:8761/eureka",
        "http://eureka2.company.com:8761/eureka",
    }),
)

Load Balancing Strategies

Round Robin

// Distribute requests evenly across instances
instance, err := service.SelectInstance(ctx, "user-service", discovery.LoadBalanceRoundRobin)

Random

// Random selection for simple load distribution
instance, err := service.SelectInstance(ctx, "user-service", discovery.LoadBalanceRandom)

Least Connections

// Select instance with fewest active connections
instance, err := service.SelectInstance(ctx, "user-service", discovery.LoadBalanceLeastConnections)

Health Checks

HTTP Health Check

health_check:
  enabled: true
  interval: 10s
  timeout: 5s
  http: "http://localhost:8080/_/health"

TCP Health Check

health_check:
  enabled: true
  interval: 10s
  timeout: 5s
  tcp: "localhost:8080"

gRPC Health Check

health_check:
  enabled: true
  interval: 10s
  timeout: 5s
  grpc: "localhost:9090"

Service Metadata

// Register service with metadata
instance := &discovery.ServiceInstance{
    Name: "my-api",
    Metadata: map[string]string{
        "version":     "1.0.0",
        "region":      "us-east-1",
        "environment": "production",
        "datacenter":  "dc1",
    },
}

// Query metadata
if region, ok := instance.GetMetadata("region"); ok {
    fmt.Printf("Service is in region: %s\n", region)
}

Client-Side Load Balancing

// Create HTTP client with service discovery
type DiscoveryClient struct {
    service     *discovery.Service
    serviceName string
    strategy    discovery.LoadBalanceStrategy
}

func (c *DiscoveryClient) Get(ctx context.Context, path string) (*http.Response, error) {
    url, err := c.service.GetServiceURL(ctx, c.serviceName, "http", c.strategy)
    if err != nil {
        return nil, err
    }

    return http.Get(url + path)
}

// Usage
client := &DiscoveryClient{
    service:     discoveryService,
    serviceName: "user-service",
    strategy:    discovery.LoadBalanceRoundRobin,
}

resp, err := client.Get(ctx, "/users/123")

Service Tags

// Register with tags
service.Register(ctx, &discovery.ServiceInstance{
    Name: "api",
    Tags: []string{"production", "v2", "us-east"},
})

// Discover by tags
instances, err := service.DiscoverWithTags(ctx, "api", []string{"production", "v2"})

Best Practices

1. Use Health Checks

// ✅ Always enable health checks
discovery.WithHTTPHealthCheck("http://localhost:8080/_/health", 10*time.Second)

// ❌ Don't disable health checks in production

2. Include Meaningful Tags

// ✅ Good tags
Tags: []string{"production", "v2", "us-east-1", "canary"}

// ❌ Bad tags
Tags: []string{"server", "app"}

3. Auto-Deregister on Shutdown

// ✅ Always enable auto-deregister
service:
  enable_auto_deregister: true

4. Use Metadata for Configuration

// ✅ Store configuration in metadata
Metadata: map[string]string{
    "max_connections": "1000",
    "timeout": "30s",
    "protocol": "http2",
}

5. Watch Critical Services

// ✅ Watch dependencies for changes
watch:
  enabled: true
  services:
    - "database"
    - "cache"
    - "payment-gateway"

Patterns

Circuit Breaker Integration

// Combine with circuit breaker for resilience
circuitBreaker := NewCircuitBreaker(options)

instance, err := discoveryService.SelectInstance(ctx, "user-service", strategy)
if err != nil {
    return err
}

return circuitBreaker.Call(func() error {
    return callService(instance)
})

Retry with Different Instance

func callWithRetry(ctx context.Context, serviceName string, maxRetries int) error {
    for i := 0; i < maxRetries; i++ {
        instance, err := service.SelectInstance(ctx, serviceName, discovery.LoadBalanceRandom)
        if err != nil {
            return err
        }

        if err := callService(instance); err == nil {
            return nil
        }

        logger.Warn("call failed, retrying with different instance",
            forge.F("attempt", i+1),
        )
    }
    return fmt.Errorf("all retries failed")
}

Dynamic Service Pool

type ServicePool struct {
    instances []*discovery.ServiceInstance
    mu        sync.RWMutex
}

// Watch and update pool
service.Watch(ctx, "user-service", func(instances []*discovery.ServiceInstance) {
    pool.mu.Lock()
    defer pool.mu.Unlock()
    pool.instances = instances
})

Testing

func TestServiceDiscovery(t *testing.T) {
    // Use memory backend for testing
    backend := discovery.NewMemoryBackend()
    service := discovery.NewService(backend, logger)

    // Register test service
    instance := &discovery.ServiceInstance{
        ID:      "test-1",
        Name:    "test-service",
        Address: "localhost",
        Port:    8080,
        Status:  discovery.HealthStatusPassing,
    }
    service.Register(context.Background(), instance)

    // Discover
    instances, err := service.Discover(context.Background(), "test-service")
    assert.NoError(t, err)
    assert.Len(t, instances, 1)
}

Monitoring

// Expose service discovery metrics
router.GET("/_/discovery/services", func(ctx forge.Context) error {
    services, err := discoveryService.ListServices(ctx.Context())
    if err != nil {
        return err
    }

    return ctx.JSON(200, map[string]interface{}{
        "services": services,
    })
})

router.GET("/_/discovery/instances/:service", func(ctx forge.Context) error {
    serviceName := ctx.Param("service")
    instances, err := discoveryService.Discover(ctx.Context(), serviceName)
    if err != nil {
        return err
    }

    return ctx.JSON(200, map[string]interface{}{
        "service":   serviceName,
        "instances": instances,
    })
})

Performance Considerations

  • Caching: Service discovery results are cached by backends
  • Health Checks: Balance frequency vs. load (10s recommended)
  • Watch Updates: Debounce rapid changes to avoid thrashing
  • Connection Pooling: Reuse connections to backend (Consul, etcd)

Migration Guide

From Hardcoded URLs

// Before
userServiceURL := "http://user-service:8080"

// After
url, err := discoveryService.GetServiceURL(ctx, "user-service", "http", strategy)

From Environment Variables

// Before
services := map[string]string{
    "user-service": os.Getenv("USER_SERVICE_URL"),
    "payment":      os.Getenv("PAYMENT_SERVICE_URL"),
}

// After
// Services discovered automatically via service discovery

License

MIT License - see LICENSE file for details

Documentation

Index

Constants

View Source
const (
	// HealthStatusPassing indicates the service is healthy
	HealthStatusPassing = backends.HealthStatusPassing

	// HealthStatusWarning indicates the service has warnings
	HealthStatusWarning = backends.HealthStatusWarning

	// HealthStatusCritical indicates the service is unhealthy
	HealthStatusCritical = backends.HealthStatusCritical

	// HealthStatusUnknown indicates the health status is unknown
	HealthStatusUnknown = backends.HealthStatusUnknown
)

Variables

This section is empty.

Functions

func NewExtension

func NewExtension(opts ...ConfigOption) forge.Extension

NewExtension creates a new service discovery extension

func NewExtensionWithConfig

func NewExtensionWithConfig(config Config) forge.Extension

NewExtensionWithConfig creates a new extension with complete config

Types

type Backend

type Backend = backends.Backend

Backend defines the interface for service discovery backends

type Config

type Config struct {
	// Enabled determines if service discovery is enabled
	Enabled bool `yaml:"enabled" json:"enabled"`

	// Backend specifies the service discovery backend
	// Options: "consul", "etcd", "kubernetes", "eureka", "memory"
	Backend string `yaml:"backend" json:"backend"`

	// Service configuration for this instance
	Service ServiceConfig `yaml:"service" json:"service"`

	// Health check settings
	HealthCheck HealthCheckConfig `yaml:"health_check" json:"health_check"`

	// Watch settings
	Watch WatchConfig `yaml:"watch" json:"watch"`

	// Consul-specific settings
	Consul ConsulConfig `yaml:"consul" json:"consul"`

	// Etcd-specific settings
	Etcd EtcdConfig `yaml:"etcd" json:"etcd"`

	// Kubernetes-specific settings
	Kubernetes KubernetesConfig `yaml:"kubernetes" json:"kubernetes"`

	// Eureka-specific settings
	Eureka EurekaConfig `yaml:"eureka" json:"eureka"`

	// MDNS-specific settings
	MDNS MDNSConfig `yaml:"mdns" json:"mdns"`

	// FARP (Forge API Gateway Registration Protocol) settings
	FARP FARPConfig `yaml:"farp" json:"farp"`
}

Config holds service discovery extension configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default service discovery configuration

type ConfigOption

type ConfigOption func(*Config)

ConfigOption configures the service discovery extension

func WithBackend

func WithBackend(backend string) ConfigOption

WithBackend sets the service discovery backend

func WithConfig

func WithConfig(config Config) ConfigOption

WithConfig sets the complete config

func WithConsul

func WithConsul(address, token string) ConfigOption

WithConsul configures Consul backend

func WithEnabled

func WithEnabled(enabled bool) ConfigOption

WithEnabled sets whether service discovery is enabled

func WithEtcd

func WithEtcd(endpoints []string) ConfigOption

WithEtcd configures etcd backend

func WithEureka

func WithEureka(urls []string) ConfigOption

WithEureka configures Eureka backend

func WithHTTPHealthCheck

func WithHTTPHealthCheck(endpoint string, interval time.Duration) ConfigOption

WithHTTPHealthCheck sets HTTP health check

func WithHealthCheck

func WithHealthCheck(config HealthCheckConfig) ConfigOption

WithHealthCheck sets the health check configuration

func WithKubernetes

func WithKubernetes(namespace string, inCluster bool) ConfigOption

WithKubernetes configures Kubernetes backend

func WithMDNS

func WithMDNS(domain string) ConfigOption

WithMDNS configures mDNS backend

func WithService

func WithService(service ServiceConfig) ConfigOption

WithService sets the service configuration

func WithServiceAddress

func WithServiceAddress(address string, port int) ConfigOption

WithServiceAddress sets the service address and port

func WithServiceMetadata

func WithServiceMetadata(metadata map[string]string) ConfigOption

WithServiceMetadata sets the service metadata

func WithServiceName

func WithServiceName(name string) ConfigOption

WithServiceName sets the service name

func WithServiceTags

func WithServiceTags(tags ...string) ConfigOption

WithServiceTags sets the service tags

func WithWatch

func WithWatch(services []string, onChange func([]*ServiceInstance)) ConfigOption

WithWatch enables service watching

type ConsulConfig

type ConsulConfig = backends.ConsulConfig

ConsulConfig holds Consul-specific configuration

type EtcdConfig

type EtcdConfig = backends.EtcdConfig

EtcdConfig holds etcd-specific configuration

type EurekaConfig

type EurekaConfig = backends.EurekaConfig

EurekaConfig holds Eureka-specific configuration

type Extension

type Extension struct {
	*forge.BaseExtension
	// contains filtered or unexported fields
}

Extension implements forge.Extension for service discovery

func (*Extension) Dependencies

func (e *Extension) Dependencies() []string

Dependencies returns extension dependencies

func (*Extension) Health

func (e *Extension) Health(ctx context.Context) error

Health checks the extension health

func (*Extension) Register

func (e *Extension) Register(app forge.App) error

Register registers the extension with the app

func (*Extension) Service

func (e *Extension) Service() *Service

Service returns the service discovery service

func (*Extension) Start

func (e *Extension) Start(ctx context.Context) error

Start starts the extension

func (*Extension) Stop

func (e *Extension) Stop(ctx context.Context) error

Stop stops the extension gracefully

type FARPConfig

type FARPConfig struct {
	// Enabled determines if FARP schema registration is enabled
	Enabled bool `yaml:"enabled" json:"enabled"`

	// AutoRegister automatically registers schemas on service startup
	AutoRegister bool `yaml:"auto_register" json:"auto_register"`

	// Strategy for schema storage: "push" (to registry), "pull" (HTTP only), "hybrid"
	Strategy string `yaml:"strategy" json:"strategy"`

	// Schemas to register
	Schemas []FARPSchemaConfig `yaml:"schemas" json:"schemas"`

	// Endpoints configuration
	Endpoints FARPEndpointsConfig `yaml:"endpoints" json:"endpoints"`

	// Capabilities advertised by this service
	Capabilities []string `yaml:"capabilities" json:"capabilities"`
}

FARPConfig holds FARP (Forge API Gateway Registration Protocol) configuration

type FARPEndpointsConfig

type FARPEndpointsConfig struct {
	// Health check endpoint
	Health string `yaml:"health" json:"health"`

	// Metrics endpoint
	Metrics string `yaml:"metrics,omitempty" json:"metrics,omitempty"`

	// OpenAPI spec endpoint
	OpenAPI string `yaml:"openapi,omitempty" json:"openapi,omitempty"`

	// AsyncAPI spec endpoint
	AsyncAPI string `yaml:"asyncapi,omitempty" json:"asyncapi,omitempty"`

	// gRPC reflection enabled
	GRPCReflection bool `yaml:"grpc_reflection,omitempty" json:"grpc_reflection,omitempty"`

	// GraphQL endpoint
	GraphQL string `yaml:"graphql,omitempty" json:"graphql,omitempty"`
}

FARPEndpointsConfig configures service endpoints

type FARPLocationConfig

type FARPLocationConfig struct {
	// Type: "http", "registry", "inline"
	Type string `yaml:"type" json:"type"`

	// URL for HTTP location type
	URL string `yaml:"url,omitempty" json:"url,omitempty"`

	// RegistryPath for registry location type
	RegistryPath string `yaml:"registry_path,omitempty" json:"registry_path,omitempty"`

	// Headers for HTTP authentication
	Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
}

FARPLocationConfig configures where the schema is located

type FARPSchemaConfig

type FARPSchemaConfig struct {
	// Type of schema: "openapi", "asyncapi", "grpc", "graphql"
	Type string `yaml:"type" json:"type"`

	// SpecVersion is the schema specification version (e.g., "3.1.0" for OpenAPI)
	SpecVersion string `yaml:"spec_version" json:"spec_version"`

	// Location configuration
	Location FARPLocationConfig `yaml:"location" json:"location"`

	// ContentType is the schema content type
	ContentType string `yaml:"content_type" json:"content_type"`
}

FARPSchemaConfig configures a single schema to register

type HealthCheckConfig

type HealthCheckConfig struct {
	// Enabled determines if health checks are enabled
	Enabled bool `yaml:"enabled" json:"enabled"`

	// Interval is how often to perform health checks
	Interval time.Duration `yaml:"interval" json:"interval"`

	// Timeout is the health check timeout
	Timeout time.Duration `yaml:"timeout" json:"timeout"`

	// DeregisterCriticalServiceAfter is when to deregister unhealthy services
	DeregisterCriticalServiceAfter time.Duration `yaml:"deregister_critical_service_after" json:"deregister_critical_service_after"`

	// HTTP health check endpoint (if using HTTP)
	HTTP string `yaml:"http" json:"http"`

	// TCP health check address (if using TCP)
	TCP string `yaml:"tcp" json:"tcp"`

	// gRPC health check address (if using gRPC)
	GRPC string `yaml:"grpc" json:"grpc"`
}

HealthCheckConfig holds health check configuration

type HealthStatus

type HealthStatus = backends.HealthStatus

HealthStatus represents service health status

type KubernetesConfig

type KubernetesConfig = backends.KubernetesConfig

KubernetesConfig holds Kubernetes-specific configuration

type LoadBalanceStrategy

type LoadBalanceStrategy string

LoadBalanceStrategy defines load balancing strategies

const (
	// LoadBalanceRoundRobin uses round-robin selection
	LoadBalanceRoundRobin LoadBalanceStrategy = "round_robin"

	// LoadBalanceRandom uses random selection
	LoadBalanceRandom LoadBalanceStrategy = "random"

	// LoadBalanceLeastConnections uses least connections selection
	LoadBalanceLeastConnections LoadBalanceStrategy = "least_connections"

	// LoadBalanceWeightedRoundRobin uses weighted round-robin
	LoadBalanceWeightedRoundRobin LoadBalanceStrategy = "weighted_round_robin"
)

type MDNSConfig

type MDNSConfig = backends.MDNSConfig

MDNSConfig holds mDNS/DNS-SD-specific configuration Works natively on macOS (Bonjour), Linux (Avahi), and Windows (DNS-SD)

type SchemaPublisher

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

SchemaPublisher handles FARP schema registration

func NewSchemaPublisher

func NewSchemaPublisher(config FARPConfig, app forge.App) *SchemaPublisher

NewSchemaPublisher creates a new schema publisher

func (*SchemaPublisher) Close

func (p *SchemaPublisher) Close() error

Close closes the schema publisher

func (*SchemaPublisher) GetManifest

func (p *SchemaPublisher) GetManifest(ctx context.Context, instanceID string) (*farp.SchemaManifest, error)

GetManifest retrieves the manifest for an instance

func (*SchemaPublisher) Publish

func (p *SchemaPublisher) Publish(ctx context.Context, instanceID string) error

Publish generates and publishes schemas for the service

type Service

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

Service provides high-level service discovery operations

func NewService

func NewService(backend Backend, logger forge.Logger) *Service

NewService creates a new service discovery service

func (*Service) Deregister

func (s *Service) Deregister(ctx context.Context, serviceID string) error

Deregister deregisters a service instance

func (*Service) Discover

func (s *Service) Discover(ctx context.Context, serviceName string) ([]*ServiceInstance, error)

Discover discovers service instances by name

func (*Service) DiscoverHealthy

func (s *Service) DiscoverHealthy(ctx context.Context, serviceName string) ([]*ServiceInstance, error)

DiscoverHealthy discovers only healthy service instances

func (*Service) DiscoverWithTags

func (s *Service) DiscoverWithTags(ctx context.Context, serviceName string, tags []string) ([]*ServiceInstance, error)

DiscoverWithTags discovers service instances by name and tags

func (*Service) GetServiceURL

func (s *Service) GetServiceURL(ctx context.Context, serviceName string, scheme string, strategy LoadBalanceStrategy) (string, error)

GetServiceURL gets a service URL using load balancing

func (*Service) Health

func (s *Service) Health(ctx context.Context) error

Health checks backend health

func (*Service) ListServices

func (s *Service) ListServices(ctx context.Context) ([]string, error)

ListServices lists all registered services

func (*Service) Register

func (s *Service) Register(ctx context.Context, instance *ServiceInstance) error

Register registers a service instance

func (*Service) SelectInstance

func (s *Service) SelectInstance(ctx context.Context, serviceName string, strategy LoadBalanceStrategy) (*ServiceInstance, error)

SelectInstance selects a single service instance using load balancing strategy

func (*Service) Watch

func (s *Service) Watch(ctx context.Context, serviceName string, onChange func([]*ServiceInstance)) error

Watch watches for changes to a service

type ServiceConfig

type ServiceConfig struct {
	// Name is the service name
	Name string `yaml:"name" json:"name"`

	// ID is the unique service instance ID (auto-generated if empty)
	ID string `yaml:"id" json:"id"`

	// Version is the service version
	Version string `yaml:"version" json:"version"`

	// Address is the service address
	Address string `yaml:"address" json:"address"`

	// Port is the service port
	Port int `yaml:"port" json:"port"`

	// Tags are service tags for filtering
	Tags []string `yaml:"tags" json:"tags"`

	// Metadata is arbitrary service metadata
	Metadata map[string]string `yaml:"metadata" json:"metadata"`

	// EnableAutoDeregister enables automatic deregistration on shutdown
	EnableAutoDeregister bool `yaml:"enable_auto_deregister" json:"enable_auto_deregister"`
}

ServiceConfig holds service registration configuration

type ServiceEvent

type ServiceEvent struct {
	// Type is the event type
	Type ServiceEventType

	// Service is the service instance
	Service *ServiceInstance

	// Timestamp is when the event occurred
	Timestamp int64
}

ServiceEvent represents a service change event

type ServiceEventType

type ServiceEventType string

ServiceEventType represents types of service events

const (
	// ServiceEventRegistered indicates a service was registered
	ServiceEventRegistered ServiceEventType = "registered"

	// ServiceEventDeregistered indicates a service was deregistered
	ServiceEventDeregistered ServiceEventType = "deregistered"

	// ServiceEventHealthChanged indicates service health changed
	ServiceEventHealthChanged ServiceEventType = "health_changed"

	// ServiceEventMetadataChanged indicates service metadata changed
	ServiceEventMetadataChanged ServiceEventType = "metadata_changed"
)

type ServiceInstance

type ServiceInstance = backends.ServiceInstance

ServiceInstance represents a registered service instance

type ServiceQuery

type ServiceQuery struct {
	// Name is the service name to query
	Name string

	// Tags are tags to filter by
	Tags []string

	// OnlyHealthy returns only healthy instances
	OnlyHealthy bool

	// LoadBalanceStrategy is the load balancing strategy
	LoadBalanceStrategy LoadBalanceStrategy
}

ServiceQuery represents a service discovery query

type ServiceRegistration

type ServiceRegistration struct {
	// Service is the service configuration
	Service ServiceConfig

	// HealthCheck is the health check configuration
	HealthCheck HealthCheckConfig
}

ServiceRegistration represents a service registration request

type WatchConfig

type WatchConfig struct {
	// Enabled determines if service watching is enabled
	Enabled bool `yaml:"enabled" json:"enabled"`

	// Services are service names to watch for changes
	Services []string `yaml:"services" json:"services"`

	// Tags are tags to filter services
	Tags []string `yaml:"tags" json:"tags"`

	// OnChange is called when watched services change
	// This is set programmatically, not via config
	OnChange func(services []*ServiceInstance)
}

WatchConfig holds service watch configuration

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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