Documentation
¶
Index ¶
- Constants
- Variables
- type Alan
- func (a *Alan) Config() Config
- func (a *Alan) HasQuorum() bool
- func (a *Alan) IsSecure() bool
- func (a *Alan) LocalAddr() net.Addr
- func (a *Alan) Lock(ctx context.Context, key string) error
- func (a *Alan) OnPeerJoin(handler PeerHandler)
- func (a *Alan) OnPeerLeave(handler PeerHandler)
- func (a *Alan) PeerCount() int
- func (a *Alan) Peers() []*net.UDPAddr
- func (a *Alan) QuorumSize() int
- func (a *Alan) Ready() <-chan struct{}
- func (a *Alan) Refresh() error
- func (a *Alan) Reply(msg Message, data []byte) (int, error)
- func (a *Alan) Send(ctx context.Context, data []byte) []SendResult
- func (a *Alan) SendAndWaitReply(ctx context.Context, data []byte) ([]Reply, error)
- func (a *Alan) SendTo(addr *net.UDPAddr, data []byte) (int, error)
- func (a *Alan) SendToAndWaitReply(ctx context.Context, addr *net.UDPAddr, data []byte) (*Reply, error)
- func (a *Alan) Start(ctx context.Context, handler MessageHandler) error
- func (a *Alan) Stop() error
- func (a *Alan) TryLock(key string) bool
- func (a *Alan) Unlock(key string) error
- func (a *Alan) WaitForQuorum(ctx context.Context) error
- type Config
- type Message
- type MessageHandler
- type Peer
- type PeerHandler
- type Reply
- type SecurityConfig
- type SendResult
Constants ¶
const ( // MsgTypeJoin is sent when a peer joins the cluster MsgTypeJoin byte = 0x01 // MsgTypeLeave is sent when a peer leaves the cluster gracefully MsgTypeLeave byte = 0x02 // MsgTypeHeartbeat is sent periodically to maintain membership MsgTypeHeartbeat byte = 0x03 // MsgTypeData is a user data message MsgTypeData byte = 0x10 // MsgTypeRequest is a request message expecting a response MsgTypeRequest byte = 0x20 // MsgTypeResponse is a response to a request message MsgTypeResponse byte = 0x21 // MsgTypeLockRequest is sent to request a distributed lock MsgTypeLockRequest byte = 0x30 // MsgTypeLockGrant is sent to grant a lock to the requester MsgTypeLockGrant byte = 0x31 // MsgTypeLockDeny is sent to deny a lock request (already held) MsgTypeLockDeny byte = 0x32 // MsgTypeLockRelease is sent to notify that a lock has been released MsgTypeLockRelease byte = 0x33 )
Message types for internal protocol
const RequestIDSize = 16
RequestIDSize is the size of request IDs in bytes
Variables ¶
var ( // ErrInvalidKeySize is returned when the key is not exactly 32 bytes ErrInvalidKeySize = errors.New("key must be exactly 32 bytes") // ErrSecurityNotEnabled is returned when trying to use encryption without enabling it ErrSecurityNotEnabled = errors.New("security is not enabled") // ErrMessageTooShort is returned when encrypted message is shorter than nonce size ErrMessageTooShort = errors.New("encrypted message too short") // ErrDecryptionFailed is returned when message authentication fails ErrDecryptionFailed = errors.New("decryption failed: message authentication failed") // ErrAlreadyStarted is returned when Start is called on an already running instance ErrAlreadyStarted = errors.New("alan is already started") // ErrNotStarted is returned when operations are attempted before Start ErrNotStarted = errors.New("alan is not started") // ErrPeerDisconnected is returned when the target peer disconnects before responding ErrPeerDisconnected = errors.New("peer disconnected before responding") // ErrNoQuorum is returned when quorum is not reached ErrNoQuorum = errors.New("quorum not reached") // ErrLockNotHeld is returned when trying to unlock a lock not held by this instance ErrLockNotHeld = errors.New("lock not held by this instance") )
Functions ¶
This section is empty.
Types ¶
type Alan ¶
type Alan struct {
// contains filtered or unexported fields
}
Alan is the main entry point for the UDP peer discovery library.
func (*Alan) HasQuorum ¶ added in v0.1.3
HasQuorum returns true if the current number of peers meets the quorum requirement. Always returns true if quorum is disabled (Quorum == 0).
func (*Alan) Lock ¶ added in v0.1.3
Lock acquires a named distributed lock, blocking until acquired or context cancelled. If quorum is enabled, it waits for quorum before attempting to acquire the lock. Returns nil on success, ctx.Err() if context is cancelled.
func (*Alan) OnPeerJoin ¶
func (a *Alan) OnPeerJoin(handler PeerHandler)
OnPeerJoin sets the callback for when a peer joins the cluster
func (*Alan) OnPeerLeave ¶
func (a *Alan) OnPeerLeave(handler PeerHandler)
OnPeerLeave sets the callback for when a peer leaves the cluster
func (*Alan) QuorumSize ¶ added in v0.1.3
QuorumSize returns the number of peers required for quorum. Returns (Quorum/2)+1 if Quorum is set, or 0 if quorum is disabled.
func (*Alan) Ready ¶
func (a *Alan) Ready() <-chan struct{}
Ready returns a channel that is closed when the instance is ready to send/receive. Use this to wait for Start() to complete initialization before calling Send/SendTo.
func (*Alan) Refresh ¶
Refresh re-resolves DNS and discovers new peers. If DNSAddr is empty or DNS resolution fails, it returns nil without error.
func (*Alan) Reply ¶
Reply sends a response to a request message. This should be called from the message handler when processing a request. Returns an error if the message is not a request.
func (*Alan) Send ¶
func (a *Alan) Send(ctx context.Context, data []byte) []SendResult
Send broadcasts data to all peers. If quorum is enabled, it waits for quorum before sending. Returns ctx.Err() in each result if context is cancelled before quorum is reached.
func (*Alan) SendAndWaitReply ¶
SendAndWaitReply broadcasts a request to all peers and waits for their responses. It waits for quorum before sending if quorum is enabled. It returns all replies received before the context is cancelled or deadline exceeded. If peers disconnect while waiting, they are removed from the expected responses. The method returns when all remaining peers have responded or the context is done.
func (*Alan) SendTo ¶
SendTo sends data to a specific peer. This method does NOT wait for quorum - it's a direct send to a known peer.
func (*Alan) SendToAndWaitReply ¶
func (a *Alan) SendToAndWaitReply(ctx context.Context, addr *net.UDPAddr, data []byte) (*Reply, error)
SendToAndWaitReply sends a request to a specific peer and waits for its response. Returns ErrPeerDisconnected if the target peer disconnects before responding.
func (*Alan) Start ¶
func (a *Alan) Start(ctx context.Context, handler MessageHandler) error
Start initializes the peer discovery system: - Resolves DNSAddr to discover initial peers (if configured and resolvable) - Starts UDP server - Sends JOIN to all peers - Starts heartbeat goroutine This method blocks until the context is cancelled or Stop() is called.
func (*Alan) TryLock ¶ added in v0.1.3
TryLock attempts to acquire a named distributed lock without blocking. Returns true if the lock was acquired, false otherwise. If quorum is enabled and not met, returns false.
func (*Alan) Unlock ¶ added in v0.1.3
Unlock releases a named distributed lock. Returns ErrLockNotHeld if this instance does not hold the lock.
func (*Alan) WaitForQuorum ¶ added in v0.1.3
WaitForQuorum blocks until quorum is reached or the context is cancelled. Returns nil immediately if quorum is disabled (Quorum == 0). Returns ctx.Err() if the context is cancelled before quorum is reached.
type Config ¶
type Config struct {
// DNSAddr is the DNS name to resolve for discovering peers (optional).
// If empty or DNS resolution fails, the library will still start and
// can discover peers through incoming messages or later DNS resolution.
DNSAddr string `cfg:"dns_addr" json:"dns_addr"`
// BindAddr is the local address to bind to (default: "0.0.0.0" for all interfaces)
BindAddr string `cfg:"bind_addr" json:"bind_addr"`
// Port is the UDP port to use (default: 5000)
// IMPORTANT: All peers in the cluster MUST use the same port
Port int `cfg:"port" json:"port"`
// Timeout is the read/write timeout duration (default: 5s)
Timeout time.Duration `cfg:"timeout" json:"timeout"`
// BufferSize is the buffer size for receiving messages (default: 4096)
BufferSize int `cfg:"buffer_size" json:"buffer_size"`
// Security holds optional encryption configuration
Security *SecurityConfig `cfg:"security" json:"security"`
// HeartbeatInterval is how often to send heartbeats (default: 5s)
HeartbeatInterval time.Duration `cfg:"heartbeat_interval" json:"heartbeat_interval"`
// HeartbeatTimeout is when a peer is considered dead (default: 15s)
HeartbeatTimeout time.Duration `cfg:"heartbeat_timeout" json:"heartbeat_timeout"`
// RefreshInterval is how often to re-resolve DNS (default: 30s, set to -1 to disable)
RefreshInterval time.Duration `cfg:"refresh_interval" json:"refresh_interval"`
// MessageQueueSize is the per-peer message buffer size (default: 256)
// Messages from the same peer are processed in order.
// When the queue is full, the listener blocks until space is available.
MessageQueueSize int `cfg:"message_queue_size" json:"message_queue_size"`
// Quorum is the expected cluster size for distributed operations.
// When set, operations like Lock() and Send() will wait until
// (Quorum/2)+1 peers are present before proceeding.
// Set to 0 to disable quorum checks (default).
Quorum int `cfg:"quorum" json:"quorum"`
}
Config holds all configuration for Alan
type Message ¶
type Message struct {
// Data contains the decrypted message payload
Data []byte
// Addr is the sender's address
Addr *net.UDPAddr
// contains filtered or unexported fields
}
Message represents an incoming data message from a peer
type MessageHandler ¶
MessageHandler is a callback for receiving data messages
type PeerHandler ¶
PeerHandler is a callback for peer membership events
type Reply ¶
type Reply struct {
// Data contains the response payload
Data []byte
// Addr is the responder's address
Addr *net.UDPAddr
}
Reply represents a response from a peer to a request
type SecurityConfig ¶
type SecurityConfig struct {
// Key is the pre-shared key for ChaCha20-Poly1305 encryption.
// Must be exactly 32 bytes.
Key []byte `cfg:"key" json:"key"`
// Enabled determines whether encryption is active
Enabled bool `cfg:"enabled" json:"enabled"`
}
SecurityConfig holds encryption settings