feat: persist and dispatch client command input
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
// Package supervisor defines the narrow process-control seam shared by the
|
||||
// client runtime and platform implementations. It intentionally contains no
|
||||
// operating-system handles or process APIs.
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
rvboxv1 "github.com/rvbox/rvbox/gen/go/rvbox/v1"
|
||||
"github.com/rvbox/rvbox/internal/domain"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidStartSpec = errors.New("invalid supervisor start specification")
|
||||
ErrUnsupported = errors.New("supervisor operation is unsupported")
|
||||
)
|
||||
|
||||
type SignalKind uint8
|
||||
|
||||
const (
|
||||
SignalTerm SignalKind = iota + 1
|
||||
SignalKill
|
||||
)
|
||||
|
||||
// StartSpec is already validated at the protocol boundary. The supervisor
|
||||
// still checks the identity/revision/source invariants because it is a second
|
||||
// durability boundary and may be called after a restart.
|
||||
type StartSpec struct {
|
||||
IssueUUID domain.UUID
|
||||
CommandRevision uint64
|
||||
Execution *rvboxv1.ExecutionSpec
|
||||
WorkingDirectory string
|
||||
Environment map[string]string
|
||||
ExecutionProfiles []string
|
||||
}
|
||||
|
||||
func (spec StartSpec) Validate() error {
|
||||
if _, err := domain.ParseUUIDv7(spec.IssueUUID.String()); err != nil || spec.CommandRevision == 0 || spec.Execution == nil || spec.Execution.Source == nil {
|
||||
return ErrInvalidStartSpec
|
||||
}
|
||||
if spec.WorkingDirectory == "" {
|
||||
return ErrInvalidStartSpec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EffectiveIdentity is immutable process evidence captured before launch.
|
||||
// Empty user/session fields mean a Session 0 service context.
|
||||
type EffectiveIdentity struct {
|
||||
Context string
|
||||
SessionID uint32
|
||||
UserSID string
|
||||
LogonSID string
|
||||
Elevated bool
|
||||
Integrity string
|
||||
}
|
||||
|
||||
type Process interface {
|
||||
IssueUUID() domain.UUID
|
||||
Identity() EffectiveIdentity
|
||||
Wait(context.Context) (ExitStatus, error)
|
||||
WriteStdin(context.Context, []byte, bool) error
|
||||
CloseStdin(context.Context) error
|
||||
}
|
||||
|
||||
type ExitStatus struct {
|
||||
Code int32
|
||||
Signaled bool
|
||||
Signal SignalKind
|
||||
StartedAt time.Time
|
||||
FinishedAt time.Time
|
||||
OutputDrained bool
|
||||
Output bool
|
||||
}
|
||||
|
||||
type SignalOutcome struct {
|
||||
Delivered bool
|
||||
Escalated bool
|
||||
Detail string
|
||||
ObservedAt time.Time
|
||||
}
|
||||
|
||||
type ResourceSnapshot struct {
|
||||
CPUTime time.Duration
|
||||
ResidentBytes uint64
|
||||
IOReadBytes uint64
|
||||
IOWriteBytes uint64
|
||||
ProcessCount uint64
|
||||
ObservedAt time.Time
|
||||
Complete bool
|
||||
Detail string
|
||||
}
|
||||
|
||||
type Supervisor interface {
|
||||
Start(context.Context, StartSpec) (Process, error)
|
||||
Signal(context.Context, Process, SignalKind) (SignalOutcome, error)
|
||||
Snapshot(context.Context, Process) (ResourceSnapshot, error)
|
||||
StopAll(context.Context) error
|
||||
}
|
||||
Reference in New Issue
Block a user