Documentation
¶
Overview ¶
Package clientapi implements the etcd-compatible gRPC Client API, including KV (Range, Txn), Watch, Lease, Cluster, and Maintenance services. Replicas proxy write requests to the Primary via the Peer API.
Index ¶
- type ClientAPIServer
- func (cs *ClientAPIServer) Alarm(_ context.Context, _ *pb.AlarmRequest) (*pb.AlarmResponse, error)
- func (cs *ClientAPIServer) ApplyTxn(ctx context.Context, r *pb.TxnRequest) (resp *pb.TxnResponse, err error)
- func (clientServer *ClientAPIServer) Close()
- func (cs *ClientAPIServer) LeaseGrant(ctx context.Context, r *pb.LeaseGrantRequest) (resp *pb.LeaseGrantResponse, err error)
- func (cs *ClientAPIServer) LeaseKeepAlive(ka pb.Lease_LeaseKeepAliveServer) error
- func (cs *ClientAPIServer) LeaseLeases(ctx context.Context, r *pb.LeaseLeasesRequest) (resp *pb.LeaseLeasesResponse, err error)
- func (cs *ClientAPIServer) LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) (resp *pb.LeaseRevokeResponse, err error)
- func (cs *ClientAPIServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (resp *pb.LeaseTimeToLiveResponse, err error)
- func (cs *ClientAPIServer) MemberList(ctx context.Context, _ *pb.MemberListRequest) (*pb.MemberListResponse, error)
- func (cs *ClientAPIServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error)
- func (cs *ClientAPIServer) Status(_ context.Context, _ *pb.StatusRequest) (*pb.StatusResponse, error)
- func (cs *ClientAPIServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error)
- func (cs *ClientAPIServer) Watch(ws pb.Watch_WatchServer) error
- type Metrics
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ClientAPIServer ¶
type ClientAPIServer struct {
pb.UnimplementedKVServer
pb.UnimplementedWatchServer
pb.UnimplementedLeaseServer
pb.UnimplementedClusterServer
pb.UnimplementedMaintenanceServer
pb.UnimplementedAuthServer
// contains filtered or unexported fields
}
ClientAPIServer implements a gRPC server compatible with the Kubernetes etcd API subset @see https://github.com/etcd-io/etcd/blob/main/api/etcdserverpb/rpc.proto#L37 @see https://github.com/etcd-io/etcd/blob/main/api/etcdserverpb/rpc.pb.go etcd has the following gRPC "services": * KV * Watch * Lease * Cluster * Maintenance * Auth we include the 'Unimplemented' services by default and override them where required
func NewServer ¶
func NewServer(logger *slog.Logger, conf *config.Config, db localdb.Database, grpcServer *grpc.Server, peerServer *primary.Server, peerClients *peerclient.Manager, watchManager *watch.Manager, state *nodestate.State, ml memberLister, m *Metrics) *ClientAPIServer
NewServer registers the etcd-compatible Client API services on the provided gRPC server. The memberLister is called locally when this node is the Elector; non-Elector nodes proxy MemberList requests to the Elector via peerClients.
func (*ClientAPIServer) Alarm ¶
func (cs *ClientAPIServer) Alarm(_ context.Context, _ *pb.AlarmRequest) (*pb.AlarmResponse, error)
Alarm returns the current alarm status. Netsy does not implement real etcd alarm semantics (NOSPACE, CORRUPT), but reports a CORRUPT alarm when the node's Health State is not Healthy (Loading or Degraded). This ensures tools like `etcdctl endpoint health` correctly reflect node health.
func (*ClientAPIServer) ApplyTxn ¶
func (cs *ClientAPIServer) ApplyTxn(ctx context.Context, r *pb.TxnRequest) (resp *pb.TxnResponse, err error)
ApplyTxn processes a Txn write locally on the Primary. It is called directly for local requests and via the PeerKVServer for proxied requests from Replicas.
func (*ClientAPIServer) Close ¶
func (clientServer *ClientAPIServer) Close()
Close gracefully stops the gRPC server and closes the database.
func (*ClientAPIServer) LeaseGrant ¶
func (cs *ClientAPIServer) LeaseGrant(ctx context.Context, r *pb.LeaseGrantRequest) (resp *pb.LeaseGrantResponse, err error)
func (*ClientAPIServer) LeaseKeepAlive ¶
func (cs *ClientAPIServer) LeaseKeepAlive(ka pb.Lease_LeaseKeepAliveServer) error
func (*ClientAPIServer) LeaseLeases ¶
func (cs *ClientAPIServer) LeaseLeases(ctx context.Context, r *pb.LeaseLeasesRequest) (resp *pb.LeaseLeasesResponse, err error)
func (*ClientAPIServer) LeaseRevoke ¶
func (cs *ClientAPIServer) LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) (resp *pb.LeaseRevokeResponse, err error)
func (*ClientAPIServer) LeaseTimeToLive ¶
func (cs *ClientAPIServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (resp *pb.LeaseTimeToLiveResponse, err error)
func (*ClientAPIServer) MemberList ¶
func (cs *ClientAPIServer) MemberList(ctx context.Context, _ *pb.MemberListRequest) (*pb.MemberListResponse, error)
MemberList returns the current cluster member list. When this node is the Elector, the response is built directly from the local Elector's in-memory node map. Otherwise the request is proxied to the Elector via the peer connection.
func (*ClientAPIServer) Range ¶
func (cs *ClientAPIServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error)
Range serves a read request limited to the committed revision. Records above the committed revision are tentative and must not be visible to clients.
func (*ClientAPIServer) Status ¶
func (cs *ClientAPIServer) Status(_ context.Context, _ *pb.StatusRequest) (*pb.StatusResponse, error)
Status returns the status of this node. Unlike MemberList, Status is always answered locally — it is never proxied — because the response reflects the responding Node's own database size, health, and view of the current Primary (leader).
Raft-related fields (RaftIndex, RaftTerm, RaftAppliedIndex) are intentionally kept at zero because Netsy does not use Raft. IsLearner is always false because Netsy has no learner role.
func (*ClientAPIServer) Txn ¶
func (cs *ClientAPIServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error)
Txn handles an etcd Txn (write) request. If this node is the active Primary the request is processed locally; otherwise it is forwarded to the current Primary via the Peer API. Replica watch delivery for forwarded writes happens via the replication stream, not here.
func (*ClientAPIServer) Watch ¶
func (cs *ClientAPIServer) Watch(ws pb.Watch_WatchServer) error
Watch is a handler for pb.Watch_WatchServer requests It is invoked on the creation of a new 'watcher' server, which is a gRPC bidirectional stream (where one kube-apiserver is the main client, though we may need to support multiple clients at some point). Note that this Watch handler is invoked on its own go routine. Watch loops on the gRPC stream until it receives an error, such as when a client disconnects or the context is cancelled. Watchers/clients can have multiple 'watches', and will coelesce multiple 'watches' on the one Watch stream e.g. a kube-apiserver will have a single stream but multiple 'kubectl watch' commands would be coalesced into its one stream. Each watcher has an 'inbox' channel. Watch runs a separate goroutine to process any incoming messages on the inbox channel and send back to the watcher. The inbox channel messages are expected to already be a WatchResponse.
type Metrics ¶
type Metrics struct {
RequestsTotal *prometheus.CounterVec
RequestDuration *prometheus.HistogramVec
Watchers prometheus.Gauge
Watches prometheus.Gauge
WatchMinRevision prometheus.Gauge
// ProxyRequestsTotal and ProxyRequestDuration are Replica-scoped.
// They are registered through a separate RoleGroup.
ProxyRequestsTotal *prometheus.CounterVec
ProxyRequestDuration *prometheus.HistogramVec
}
Metrics holds always-on Client API Prometheus metrics.
func (*Metrics) AlwaysOnCollectors ¶
func (m *Metrics) AlwaysOnCollectors() []prometheus.Collector
AlwaysOnCollectors returns always-on collectors for direct registry registration.
func (*Metrics) ReplicaCollectors ¶
func (m *Metrics) ReplicaCollectors() []prometheus.Collector
ReplicaCollectors returns Replica-scoped collectors for registration through a Replica RoleGroup.