mirror of https://github.com/jetkvm/kvm.git
134 lines
3.0 KiB
Go
134 lines
3.0 KiB
Go
//go:build cgo
|
|
// +build cgo
|
|
|
|
package audio
|
|
|
|
import (
|
|
"context"
|
|
"os/exec"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/jetkvm/kvm/internal/logging"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// BaseSupervisor provides common functionality for audio supervisors
|
|
type BaseSupervisor struct {
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
logger *zerolog.Logger
|
|
mutex sync.RWMutex
|
|
running int32
|
|
|
|
// Process management
|
|
cmd *exec.Cmd
|
|
processPID int
|
|
|
|
// Process monitoring
|
|
processMonitor *ProcessMonitor
|
|
|
|
// Exit tracking
|
|
lastExitCode int
|
|
lastExitTime time.Time
|
|
}
|
|
|
|
// NewBaseSupervisor creates a new base supervisor
|
|
func NewBaseSupervisor(componentName string) *BaseSupervisor {
|
|
logger := logging.GetDefaultLogger().With().Str("component", componentName).Logger()
|
|
return &BaseSupervisor{
|
|
logger: &logger,
|
|
processMonitor: GetProcessMonitor(),
|
|
}
|
|
}
|
|
|
|
// IsRunning returns whether the supervisor is currently running
|
|
func (bs *BaseSupervisor) IsRunning() bool {
|
|
return atomic.LoadInt32(&bs.running) == 1
|
|
}
|
|
|
|
// setRunning atomically sets the running state
|
|
func (bs *BaseSupervisor) setRunning(running bool) {
|
|
if running {
|
|
atomic.StoreInt32(&bs.running, 1)
|
|
} else {
|
|
atomic.StoreInt32(&bs.running, 0)
|
|
}
|
|
}
|
|
|
|
// GetProcessPID returns the current process PID
|
|
func (bs *BaseSupervisor) GetProcessPID() int {
|
|
bs.mutex.RLock()
|
|
defer bs.mutex.RUnlock()
|
|
return bs.processPID
|
|
}
|
|
|
|
// GetLastExitInfo returns the last exit code and time
|
|
func (bs *BaseSupervisor) GetLastExitInfo() (exitCode int, exitTime time.Time) {
|
|
bs.mutex.RLock()
|
|
defer bs.mutex.RUnlock()
|
|
return bs.lastExitCode, bs.lastExitTime
|
|
}
|
|
|
|
// GetProcessMetrics returns process metrics if available
|
|
func (bs *BaseSupervisor) GetProcessMetrics() *ProcessMetrics {
|
|
bs.mutex.RLock()
|
|
defer bs.mutex.RUnlock()
|
|
|
|
if bs.cmd == nil || bs.cmd.Process == nil {
|
|
return &ProcessMetrics{
|
|
PID: 0,
|
|
CPUPercent: 0.0,
|
|
MemoryRSS: 0,
|
|
MemoryVMS: 0,
|
|
MemoryPercent: 0.0,
|
|
Timestamp: time.Now(),
|
|
ProcessName: "audio-server",
|
|
}
|
|
}
|
|
|
|
pid := bs.cmd.Process.Pid
|
|
if bs.processMonitor != nil {
|
|
metrics := bs.processMonitor.GetCurrentMetrics()
|
|
for _, metric := range metrics {
|
|
if metric.PID == pid {
|
|
return &metric
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return default metrics if process not found in monitor
|
|
return &ProcessMetrics{
|
|
PID: pid,
|
|
CPUPercent: 0.0,
|
|
MemoryRSS: 0,
|
|
MemoryVMS: 0,
|
|
MemoryPercent: 0.0,
|
|
Timestamp: time.Now(),
|
|
ProcessName: "audio-server",
|
|
}
|
|
}
|
|
|
|
// logSupervisorStart logs supervisor start event
|
|
func (bs *BaseSupervisor) logSupervisorStart() {
|
|
bs.logger.Info().Msg("Supervisor starting")
|
|
}
|
|
|
|
// logSupervisorStop logs supervisor stop event
|
|
func (bs *BaseSupervisor) logSupervisorStop() {
|
|
bs.logger.Info().Msg("Supervisor stopping")
|
|
}
|
|
|
|
// createContext creates a new context for the supervisor
|
|
func (bs *BaseSupervisor) createContext() {
|
|
bs.ctx, bs.cancel = context.WithCancel(context.Background())
|
|
}
|
|
|
|
// cancelContext cancels the supervisor context
|
|
func (bs *BaseSupervisor) cancelContext() {
|
|
if bs.cancel != nil {
|
|
bs.cancel()
|
|
}
|
|
}
|