Documentation
¶
Overview ¶
Package primarylease supplies a locally verifiable, short-lived primary write lease for Meldbase V2 deployments.
It intentionally does not elect a leader or persist distributed controller state. A separately operated controller must atomically fence an old owner before signing a lease for a new one. The guard keeps the database commit path free of network I/O: it verifies a controller-signed certificate when it is installed, then performs only bounded local checks for each write.
Index ¶
- Variables
- func CertificateTextLimit() int
- func Sign(certificate Certificate, privateKey ed25519.PrivateKey) (string, error)
- func ValidateLeaseRecord(record LeaseRecord, databaseID [16]byte) error
- type Authority
- type AuthorityOptions
- type AuthorityStats
- type Certificate
- type DurableConsumerPromotionReadiness
- type FileStore
- type Grant
- type GrantRequest
- type Guard
- func (guard *Guard) BindV2FollowerPromotion(ctx context.Context, fence meldbase.FollowerPromotionFence) error
- func (guard *Guard) Install(encoded string) error
- func (guard *Guard) LeaseStatus() GuardLeaseStatus
- func (guard *Guard) Revoke()
- func (guard *Guard) ValidateV2PrimaryWrite(request meldbase.PrimaryWriteFenceRequest) error
- type GuardLeaseStatus
- type GuardOptions
- type LeaseRecord
- type LeaseStore
- type MemoryStore
- type PrimaryRuntime
- type PrimaryV2Options
- type PromotionAuthority
- type PromotionReadiness
- type PromotionReadinessFunc
- type QuorumReplica
- type QuorumStats
- type QuorumStore
- func (store *QuorumStore) CompareAndSwapPrimaryLease(ctx context.Context, databaseID [16]byte, previous *LeaseRecord, ...) (bool, error)
- func (store *QuorumStore) LoadPrimaryLease(ctx context.Context, databaseID [16]byte) (LeaseRecord, bool, error)
- func (store *QuorumStore) Stats() QuorumStats
- func (store *QuorumStore) String() string
- type RenewalClient
- type Renewer
- type RenewerOptions
- type RenewerStats
Constants ¶
This section is empty.
Variables ¶
var ( // ErrLeaseActive means another owner may still possess a locally valid // certificate. Callers must wait for RetryAfter rather than attempting to // shorten that previous lease. ErrLeaseActive = errors.New("meldbase primary lease: previous owner may still be active") // ErrLeaseSequence rejects a controller request that would certify a source // position older than the controller has already recorded. ErrLeaseSequence = errors.New("meldbase primary lease: commit sequence regressed") // ErrLeaseStore reports a malformed or unavailable controller state store. ErrLeaseStore = errors.New("meldbase primary lease: controller state store failure") // ErrLeasePromotionReadiness means a promotion lacks the external proof that // its follower is safe to become primary at the requested source position. ErrLeasePromotionReadiness = errors.New("meldbase primary lease: promotion readiness was not proven") )
var ( // ErrCertificate reports a malformed, invalid or unsuitable lease // certificate. It intentionally gives no signature-verification detail. ErrCertificate = errors.New("meldbase primary lease: invalid certificate") // ErrLeaseExpired reports a certificate that is not currently valid. ErrLeaseExpired = errors.New("meldbase primary lease: lease is not currently valid") // ErrLeaseOwner reports a lease issued for a different configured owner. ErrLeaseOwner = errors.New("meldbase primary lease: certificate owner mismatch") // ErrLeaseEpoch reports an attempted local rollback or replay of a fenced // controller epoch. ErrLeaseEpoch = errors.New("meldbase primary lease: stale controller epoch") )
var ( // ErrLeaseQuorum means too few configured independent members completed an // operation. It is deliberately distinct from a CAS conflict. ErrLeaseQuorum = errors.New("meldbase primary lease: quorum unavailable") // ErrLeaseConflict means a read quorum observed no exact majority record. // This can occur after interrupted or crossed partial writes; choosing a // plausible-looking highest epoch would be unsafe. ErrLeaseConflict = errors.New("meldbase primary lease: quorum state conflict") )
var ErrPrimaryRuntimeConfiguration = errors.New("meldbase primary lease: invalid primary runtime configuration")
ErrPrimaryRuntimeConfiguration reports an unsafe primary runtime assembly. In particular, callers must not inject an unrelated write fence alongside a Guard that a Renewer will update.
var ErrRenewalConfiguration = errors.New("meldbase primary lease: invalid renewal agent configuration")
Functions ¶
func CertificateTextLimit ¶
func CertificateTextLimit() int
CertificateTextLimit is the maximum encoded certificate length. It remains below Meldbase's promotion-fence epoch limit.
func Sign ¶
func Sign(certificate Certificate, privateKey ed25519.PrivateKey) (string, error)
Sign returns a compact URL-safe certificate suitable for FollowerPromotionFence.Epoch. privateKey belongs only to the controller; a database process needs the corresponding public key.
func ValidateLeaseRecord ¶
func ValidateLeaseRecord(record LeaseRecord, databaseID [16]byte) error
ValidateLeaseRecord checks that record is a well-formed controller record for databaseID. Network adapters use it before handing a decoded value to a LeaseStore; it does not judge whether the lease is currently expired.
Types ¶
type Authority ¶
type Authority struct {
// contains filtered or unexported fields
}
Authority issues signed certificates only after an external LeaseStore CAS makes the handoff durable. It has no HTTP listener, peer authentication or membership logic; those are deployment concerns around the store.
func NewAuthority ¶
func NewAuthority(options AuthorityOptions) (*Authority, error)
NewAuthority validates controller-local configuration. It is intentionally impossible to construct an Authority with a default in-memory store: doing so would make an accidental single-process test controller look durable.
func (*Authority) Grant ¶
Grant issues a new epoch. A renewal for the same owner may be granted before the old certificate expires; a different owner must wait until the old expiry plus MaxClockSkew. This explicit availability gap is the price of not allowing two clock-skewed processes to write concurrently.
func (*Authority) Revoke ¶
func (authority *Authority) Revoke(ctx context.Context, databaseID [16]byte, epoch uint64) (LeaseRecord, error)
Revoke advances the durable controller epoch and removes the current owner. It does not shorten an already issued certificate: an unreachable old owner may still be using it. The next owner must respect the same handoff window in Grant. A reachable owner should receive Guard.Revoke through its local control agent as an optimization, not as the safety proof.
func (*Authority) Stats ¶
func (authority *Authority) Stats() AuthorityStats
Stats returns an O(1), allocation-free aggregate snapshot. It is separate from DBStats because a controller can manage many databases and is not part of the database commit path.
type AuthorityOptions ¶
type AuthorityOptions struct {
Store LeaseStore
PrivateKey ed25519.PrivateKey
LeaseDuration time.Duration
MaxClockSkew time.Duration
Clock func() time.Time
CASRetries int
}
AuthorityOptions configures a controller-side certificate issuer. MaxClockSkew is the maximum absolute offset allowed between a primary and the controller. A new owner cannot receive a currently valid certificate until the preceding certificate's expiry plus this window.
type AuthorityStats ¶
type AuthorityStats struct {
GrantAttempts uint64
Granted uint64
HandoffWaits uint64
PromotionAttempts uint64
PromotionReadinessRejected uint64
SequenceRejected uint64
StoreFailures uint64
CASConflicts uint64
RevokeAttempts uint64
Revoked uint64
}
AuthorityStats is a fixed-cardinality, identity-free process snapshot for a controller issuer. It deliberately excludes database IDs, owners, epochs, certificates, endpoints and error details. Read it from a sampler rather than from a controller request hot path.
type Certificate ¶
type Certificate struct {
DatabaseID [16]byte
Owner string
Epoch uint64
CommitSequence uint64
NotBefore time.Time
NotAfter time.Time
}
Certificate is a controller-issued, signed authority to accept writes for a bounded time. CommitSequence is the source position at which the authority was issued; the first accepted write must advance beyond it. Epoch must grow monotonically in the controller, but the guard treats it as opaque ordering data because it cannot contact the controller in the write path.
func Parse ¶
func Parse(encoded string, publicKey ed25519.PublicKey) (Certificate, error)
Parse verifies and decodes an opaque signed certificate. The returned value has millisecond precision because that is the signed wire representation.
func (Certificate) String ¶
func (certificate Certificate) String() string
type DurableConsumerPromotionReadiness ¶
type DurableConsumerPromotionReadiness struct {
Source *meldbase.DB
ConsumerName string
Buffer int
}
DurableConsumerPromotionReadiness is a first-party readiness check for a single-writer follower. It verifies that the source's authenticated named durable database consumer has durably acknowledged exactly the candidate follower's local token, and that the source has not advanced beyond it.
Authority runs readiness only after the old lease's skew-safe handoff point. The deployment must still ensure that the source used that lease guard and that ConsumerName is bound by its replication transport to this follower's trusted identity. It deliberately stays closed if the source is unavailable, history state is missing or either position differs.
func (DurableConsumerPromotionReadiness) VerifyV2FollowerPromotion ¶
func (readiness DurableConsumerPromotionReadiness) VerifyV2FollowerPromotion(ctx context.Context, request meldbase.FollowerPromotionRequest, record LeaseRecord, exists bool) error
type FileStore ¶
type FileStore struct {
// contains filtered or unexported fields
}
FileStore is one durable, single-member LeaseStore rooted in a trusted existing directory. It is suitable as the local state of one independently operated quorum member, not as a quorum or leader-election service by itself. Each database identity has a separate atomically replaced record.
The directory must be on storage appropriate for the controller's durability contract. FileStore writes use a per-record advisory flock, durable temporary file, atomic rename and directory fsync. A checksum makes torn, malformed or substituted record data fail closed.
func NewFileStore ¶
NewFileStore opens an existing controller-state directory. It never creates the directory implicitly, so deployment ownership and permissions remain explicit.
func (*FileStore) CompareAndSwapPrimaryLease ¶
func (store *FileStore) CompareAndSwapPrimaryLease(ctx context.Context, databaseID [16]byte, previous *LeaseRecord, next LeaseRecord) (bool, error)
func (*FileStore) LoadPrimaryLease ¶
type Grant ¶
type Grant struct {
Certificate string
Record LeaseRecord
RetryAfter time.Time
}
Grant is the controller response for a primary or follower-promotion request. RetryAfter is set only with ErrLeaseActive.
type GrantRequest ¶
GrantRequest identifies the owner and exact source position the controller is asked to certify. Owner must derive from authenticated controller-side identity, never an application request.
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard implements meldbase.V2PrimaryWriteFence and meldbase.FollowerPromotionFenceBinder. Install is used for an already elected primary; follower promotion binds the certificate returned by the external promotion authority automatically.
func NewGuard ¶
func NewGuard(publicKey ed25519.PublicKey, options GuardOptions) (*Guard, error)
NewGuard creates an initially closed guard. A database using it rejects all V2 business writes until Install or follower promotion binds a certificate.
func (*Guard) BindV2FollowerPromotion ¶
func (guard *Guard) BindV2FollowerPromotion(ctx context.Context, fence meldbase.FollowerPromotionFence) error
BindV2FollowerPromotion verifies that the authority's opaque epoch is a certificate for this exact promotion point before enabling local writes.
func (*Guard) Install ¶
Install verifies and atomically replaces the locally accepted lease. An external controller renews authority by signing a new certificate and calling Install before the old one expires. Revocation clears it locally.
func (*Guard) LeaseStatus ¶
func (guard *Guard) LeaseStatus() GuardLeaseStatus
LeaseStatus returns an O(1), allocation-free local lease snapshot. It is for a renewal supervisor's scheduling and must never replace the hot-path write fence, which validates the certificate again for every commit.
func (*Guard) Revoke ¶
func (guard *Guard) Revoke()
Revoke immediately closes local write admission. It is safe to call more than once. A partitioned old primary remains bounded by NotAfter even if it never receives this local revocation.
func (*Guard) ValidateV2PrimaryWrite ¶
func (guard *Guard) ValidateV2PrimaryWrite(request meldbase.PrimaryWriteFenceRequest) error
ValidateV2PrimaryWrite is the hot-path Meldbase fence. It performs no I/O, allocation or controller call; its only synchronization is an RLock around the installed immutable certificate.
type GuardLeaseStatus ¶
type GuardLeaseStatus struct {
Installed bool
Epoch uint64
CommitSequence uint64
NotBefore time.Time
NotAfter time.Time
}
GuardLeaseStatus is a fixed local snapshot for a renewal supervisor. It contains no certificate text or owner identity. Installed does not imply the lease is still time-valid; callers evaluate NotAfter against their own trusted local clock.
type GuardOptions ¶
GuardOptions configures a local primary write guard. Owner is a stable, controller-defined process identity; it is not supplied by an untrusted client. Clock is intended for deterministic tests; production callers leave it nil.
type LeaseRecord ¶
type LeaseRecord struct {
DatabaseID [16]byte
Owner string
Epoch uint64
CommitSequence uint64
NotAfter time.Time
Revoked bool
}
LeaseRecord is the controller's durable compare-and-swap state for one database. It is deliberately distinct from a rollback anchor: Owner/Epoch move forward and a lease may expire, while a rollback anchor is a permanent lower bound on recoverable history.
type LeaseStore ¶
type LeaseStore interface {
LoadPrimaryLease(context.Context, [16]byte) (LeaseRecord, bool, error)
CompareAndSwapPrimaryLease(context.Context, [16]byte, *LeaseRecord, LeaseRecord) (bool, error)
}
LeaseStore is the minimal durable CAS required by Authority. Implement it with a quorum-backed transactional store in production. Load and CompareAndSwap must be linearizable for a database identity; a local file or MemoryStore is useful only for deterministic development/testing.
previous is nil only when the record is expected not to exist. A false swap result is a concurrent state change, not a successful no-op.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is a linearizable in-process LeaseStore for tests and local deterministic demos. It must not be used as a production quorum store.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
func (*MemoryStore) CompareAndSwapPrimaryLease ¶
func (store *MemoryStore) CompareAndSwapPrimaryLease(ctx context.Context, databaseID [16]byte, previous *LeaseRecord, next LeaseRecord) (bool, error)
func (*MemoryStore) LoadPrimaryLease ¶
func (store *MemoryStore) LoadPrimaryLease(ctx context.Context, databaseID [16]byte) (LeaseRecord, bool, error)
type PrimaryRuntime ¶
PrimaryRuntime owns the safely wired primary components. The database starts closed to writes because Guard starts without a certificate; call Renew once explicitly or Run under a long-lived supervisor before serving mutations.
func OpenV2Primary ¶
func OpenV2Primary(path string, options PrimaryV2Options) (*PrimaryRuntime, error)
OpenV2Primary creates one V2 primary database with a freshly constructed Guard installed as its only PrimaryWriteFence and a matching Renewer. It does not contact the controller or start a goroutine; callers choose the startup ordering and context by calling Renew or Run.
func (*PrimaryRuntime) Close ¶
func (runtime *PrimaryRuntime) Close() error
Close immediately closes local primary admission before closing the database.
type PrimaryV2Options ¶
type PrimaryV2Options struct {
V2Options meldbase.V2Options
PublicKey ed25519.PublicKey
GuardOptions GuardOptions
RenewalClient RenewalClient
RequestTimeout time.Duration
RetryInterval time.Duration
KeepLeaseOnStop bool
}
PrimaryV2Options assembles one V2 primary with the exact Guard instance that its Renewer will update. V2Options remains available for storage settings, but PrimaryWriteFence and Follower are owned by this constructor and must be left unset/false.
type PromotionAuthority ¶
type PromotionAuthority struct {
Authority *Authority
Owner string
Readiness PromotionReadiness
}
PromotionAuthority adapts a controller Authority to meldbase.FollowerPromotionAuthority. Construct it with the authenticated target process owner identity; it never accepts that identity from a replication frame.
func (PromotionAuthority) AuthorizeFollowerPromotion ¶
func (authority PromotionAuthority) AuthorizeFollowerPromotion(ctx context.Context, request meldbase.FollowerPromotionRequest) (meldbase.FollowerPromotionFence, error)
type PromotionReadiness ¶
type PromotionReadiness interface {
VerifyV2FollowerPromotion(context.Context, meldbase.FollowerPromotionRequest, LeaseRecord, bool) error
}
PromotionReadiness proves that a specific follower position is eligible for promotion against the controller state observed by the same Authority CAS attempt. A production implementation normally verifies durable replication receipt/ack evidence and any required application recovery policy. Owner and epoch fencing alone cannot prove that an asynchronous follower contains all writes from the former primary.
type PromotionReadinessFunc ¶
type PromotionReadinessFunc func(context.Context, meldbase.FollowerPromotionRequest, LeaseRecord, bool) error
PromotionReadinessFunc adapts a function to PromotionReadiness.
func (PromotionReadinessFunc) VerifyV2FollowerPromotion ¶
func (function PromotionReadinessFunc) VerifyV2FollowerPromotion(ctx context.Context, request meldbase.FollowerPromotionRequest, record LeaseRecord, exists bool) error
type QuorumReplica ¶
type QuorumReplica struct {
MemberID string
Store LeaseStore
}
QuorumReplica binds one independent, statically identified controller member to a local LeaseStore adapter. Store typically represents an authenticated HTTPS/mTLS RPC client. MemberID must be stable configuration, not a value supplied by a request or endpoint response.
type QuorumStats ¶
type QuorumStats struct {
Replicas uint64
Quorum uint64
Loads uint64
CompareAndSwaps uint64
EndpointFailures uint64
QuorumFailures uint64
Conflicts uint64
}
QuorumStats is a fixed, identity-free operational snapshot. It intentionally omits endpoint and database identities.
type QuorumStore ¶
type QuorumStore struct {
// contains filtered or unexported fields
}
QuorumStore turns independent linearizable member stores into a fail-closed LeaseStore. A successful CAS is persisted on a strict majority. Reads accept only a record (or absence) held identically by a strict majority; they never choose a maximum from crossed or partial histories.
This is the quorum layer, not a membership/election system. Deployments must still use separately operated failure domains and an authenticated adapter for every replica.
func NewQuorumStore ¶
func NewQuorumStore(replicas []QuorumReplica) (*QuorumStore, error)
NewQuorumStore accepts one development member or an odd number of at least three members. Duplicate IDs are rejected so endpoint aliases cannot create a fake quorum.
func (*QuorumStore) CompareAndSwapPrimaryLease ¶
func (store *QuorumStore) CompareAndSwapPrimaryLease(ctx context.Context, databaseID [16]byte, previous *LeaseRecord, next LeaseRecord) (bool, error)
func (*QuorumStore) LoadPrimaryLease ¶
func (store *QuorumStore) LoadPrimaryLease(ctx context.Context, databaseID [16]byte) (LeaseRecord, bool, error)
func (*QuorumStore) Stats ¶
func (store *QuorumStore) Stats() QuorumStats
Stats reports no per-member identity so it is safe for aggregate telemetry.
func (*QuorumStore) String ¶
func (store *QuorumStore) String() string
type RenewalClient ¶
RenewalClient is the narrow control-plane dependency used by Renewer. The supplied authorityhttp.Client implements it. Owner authentication stays in that transport and is never an argument to a renewal request.
type Renewer ¶
type Renewer struct {
// contains filtered or unexported fields
}
Renewer performs controller I/O outside the database writer. It is not a leader-election, replication-ack or promotion mechanism: its commit sequence snapshot is a controller checkpoint and cannot establish follower completeness after a source failure.
func NewRenewer ¶
func NewRenewer(options RenewerOptions) (*Renewer, error)
func (*Renewer) Renew ¶
Renew takes one current DB token snapshot, obtains a fresh controller certificate and installs it locally. The database writer is never held while client.Grant is in progress. A failed request leaves an existing lease in place until its normal local expiry; it does not extend authority and does not silently reopen an initially closed guard.
func (*Renewer) Run ¶
Run renews immediately, then schedules the next request at one third of the current certificate duration before expiry. It retries failures at the bounded RetryInterval. On context completion it revokes the local guard by default, making deliberate supervisor shutdown fail closed immediately.
func (*Renewer) Stats ¶
func (renewer *Renewer) Stats() RenewerStats
Stats returns an O(1), identity-free aggregate snapshot. It is designed for an external sampler rather than calls from the database write path.
type RenewerOptions ¶
type RenewerOptions struct {
DB *meldbase.DB
Guard *Guard
Client RenewalClient
RequestTimeout time.Duration
RetryInterval time.Duration
KeepLeaseOnStop bool
Clock func() time.Time
}
RenewerOptions configures a single-primary renewal agent. DB must be the same V2 database that was opened with Guard as its PrimaryWriteFence. The API cannot infer that pointer equality across the Meldbase boundary, so this deployment wiring is explicit and checked at least for a configured fence.
KeepLeaseOnStop is deliberately false by default: Run revokes the local guard when its supervisory context ends, so a stopped supervisor cannot leave a process writable until natural certificate expiry. Set it only when another supervisor takes over with the same process and guard lifecycle.
type RenewerStats ¶
type RenewerStats struct {
Attempts uint64
Succeeded uint64
Failed uint64
InstallFailed uint64
ConsecutiveFailures uint64
Running bool
}
RenewerStats is a fixed-cardinality, identity-free supervisor snapshot. It intentionally contains no certificate, endpoint, owner or database ID.