config.go RawHistoryFolder
1package brokeripc
2
3import (
4 "time"
5
6 "github.com/bnema/vev/internal/adapters/brokerwire"
7 "github.com/bnema/vev/internal/protocol"
8)
9
10// Bounds. Every limit below is mandatory: no listener, session, or stream
11// grows an unbounded queue, and every default is small enough that a stalled
12// peer is refused rather than absorbed.
13const (
14 // DefaultMaxClients bounds concurrent accepted client connections on one
15 // listener. A listener acquires one slot before accepting, so the bound is
16 // enforced before a socket is admitted rather than after.
17 DefaultMaxClients = 64
18)
19
20// Config bounds one endpoint. The zero value is valid and selects every
21// default; a negative or zero explicit bound is replaced by its default.
22type Config struct {
23 // MaxClients bounds concurrent accepted client connections.
24 MaxClients int
25 // HandshakeTimeout bounds one accepted connection's broker preamble, broker
26 // admission, and the wait for its Register. The client dialer also bounds
27 // its whole setup (Unix dial, preamble, Register send, and wait for
28 // Registered) with it. On the server the registration phase shares the same
29 // accept-time budget as the preamble and admission: a peer that completes
30 // the preamble and admission but never sends Register is settled when that
31 // deadline elapses, so it cannot hold a core client lease or a listener slot
32 // indefinitely. It is deliberately separate from the session handshake
33 // budget that runs inside a logical stream.
34 HandshakeTimeout time.Duration
35 // MaxPendingOperations bounds mutating operations this side is waiting for
36 // on one connection. It never exceeds the brokerwire per-connection bound.
37 MaxPendingOperations int
38 // PassiveSubscribe marks every snapshot subscription of a client
39 // connection as a read-only reader: it receives publications but never
40 // counts as observation demand, so a CLI read never triggers a probe.
41 PassiveSubscribe bool
42 Build string
43 OnRetire func()
44}
45
46// withDefaults fills every unset bound with its package default.
47func (c Config) withDefaults() Config {
48 if c.Build == "" {
49 c.Build = defaultBuildIdentity()
50 }
51 if c.MaxClients <= 0 {
52 c.MaxClients = DefaultMaxClients
53 }
54 if c.HandshakeTimeout <= 0 {
55 c.HandshakeTimeout = protocol.HandshakeTimeout
56 }
57 if c.MaxPendingOperations <= 0 {
58 c.MaxPendingOperations = brokerwire.MaxPendingOperations
59 }
60 return c
61}
62
63// validate refuses a configuration whose explicit bounds cannot be honored.
64// The zero value is always valid because withDefaults has already been applied.
65func (c Config) validate() error {
66 if c.MaxClients <= 0 || c.HandshakeTimeout <= 0 {
67 return ErrConfig
68 }
69 if c.MaxPendingOperations <= 0 || c.MaxPendingOperations > brokerwire.MaxPendingOperations {
70 return ErrConfig
71 }
72 return nil
73}