feat(v0.6): route lease-freshness callsites through IsStale
InspectLease, CleanupStaleLease, runActiveLeaseCheck, and statusAt now use the PID-aware IsStale predicate. A dead local owner PID makes a lease stale immediately; SessionStatus / list / info reflect this with no display-code change. Corrects three cmd-package session-display test fixtures that built "active" leases with the local hostname but synthetic PIDs — now that freshness is PID-aware, an active session must be owned by a live process, so the fixtures use os.Getpid().
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A fresh-by-wall-clock local lease whose owner PID is dead must be
|
||||
// classified LeaseStateStale by InspectLease, so the persistent-mode
|
||||
// dispatcher routes to adoption immediately rather than after the 60s
|
||||
// wall-clock wait. (dispatchPersistent itself lives in cmd/ and is
|
||||
// covered there; this test pins the InspectLease half of the contract.)
|
||||
func TestInspectLeaseDeadLocalPIDIsStale(t *testing.T) {
|
||||
withCheckProcess(t, func(int) ProcessState { return ProcessDead })
|
||||
ws := t.TempDir()
|
||||
now := time.Now().UTC()
|
||||
writeLeaseAt(t, ws, &Lease{
|
||||
SessionID: "test",
|
||||
PID: 4242,
|
||||
Hostname: currentHostname(),
|
||||
LastHeartbeatAt: now, // fresh by wall-clock
|
||||
StartedAt: now,
|
||||
})
|
||||
if got := InspectLease(ws); got != LeaseStateStale {
|
||||
t.Errorf("dead-PID local lease: InspectLease = %v, want LeaseStateStale", got)
|
||||
}
|
||||
}
|
||||
|
||||
// The control case: a fresh local lease with a live PID stays FreshLocal,
|
||||
// so passive reattach (not adoption) is chosen.
|
||||
func TestInspectLeaseLiveLocalPIDIsFreshLocal(t *testing.T) {
|
||||
withCheckProcess(t, func(int) ProcessState { return ProcessAlive })
|
||||
ws := t.TempDir()
|
||||
now := time.Now().UTC()
|
||||
writeLeaseAt(t, ws, &Lease{
|
||||
SessionID: "test",
|
||||
PID: 4242,
|
||||
Hostname: currentHostname(),
|
||||
LastHeartbeatAt: now,
|
||||
StartedAt: now,
|
||||
})
|
||||
if got := InspectLease(ws); got != LeaseStateFreshLocal {
|
||||
t.Errorf("live-PID local lease: InspectLease = %v, want LeaseStateFreshLocal", got)
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func CleanupStaleLease(path string, staleAfter time.Duration) (*Lease, error) {
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
if IsFresh(&l, time.Now(), staleAfter) {
|
||||
if !IsStale(&l, time.Now(), staleAfter) {
|
||||
return nil, nil
|
||||
}
|
||||
if rmErr := os.Remove(path); rmErr != nil && !errors.Is(rmErr, os.ErrNotExist) {
|
||||
|
||||
@@ -56,7 +56,7 @@ func InspectLease(wsDir string) LeaseState {
|
||||
if l == nil {
|
||||
return LeaseStateNone
|
||||
}
|
||||
if !IsFresh(l, time.Now(), StaleLeaseAfter) {
|
||||
if IsStale(l, time.Now(), StaleLeaseAfter) {
|
||||
return LeaseStateStale
|
||||
}
|
||||
if l.Hostname != currentHostname() {
|
||||
|
||||
@@ -101,7 +101,7 @@ func runActiveLeaseCheck(opts PreflightOpts) (bool, bool, error) {
|
||||
existing, err := ReadLease(leasePath)
|
||||
switch {
|
||||
case err == nil && existing != nil:
|
||||
if IsFresh(existing, time.Now(), StaleLeaseAfter) {
|
||||
if !IsStale(existing, time.Now(), StaleLeaseAfter) {
|
||||
if opts.Force {
|
||||
return true, true, nil
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func statusAt(wsDir string, now time.Time) Status {
|
||||
}
|
||||
|
||||
state := SessionStateStale
|
||||
if IsFresh(&l, now, StaleLeaseAfter) {
|
||||
if !IsStale(&l, now, StaleLeaseAfter) {
|
||||
state = SessionStateActive
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user