mirror of
https://github.com/Xevion/HATray.git
synced 2025-12-05 23:15:09 -06:00
refactor: simplify interactive console run path, remove 'interactive' mode, use debug service
I'm unsure why this was originally done; I hope I'm not messing up by doing this. Based on documentation, it makes more sense that the debug mode is the intention of the 'interactive console' concept.
This commit is contained in:
@@ -10,18 +10,17 @@ import (
|
|||||||
"ha-tray/internal/app"
|
"ha-tray/internal/app"
|
||||||
|
|
||||||
winsvc "golang.org/x/sys/windows/svc"
|
winsvc "golang.org/x/sys/windows/svc"
|
||||||
winsvcDebug "golang.org/x/sys/windows/svc/debug"
|
"golang.org/x/sys/windows/svc/debug"
|
||||||
winsvcEventlog "golang.org/x/sys/windows/svc/eventlog"
|
"golang.org/x/sys/windows/svc/eventlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const serviceName = "HATray"
|
const serviceName = "HATray"
|
||||||
|
|
||||||
// WindowsService implements the Service interface for Windows
|
// WindowsService implements the Service interface for Windows
|
||||||
type WindowsService struct {
|
type WindowsService struct {
|
||||||
logger *slog.Logger
|
app *app.App
|
||||||
elog winsvcDebug.Log
|
logger *slog.Logger // logger instance, logs to file (and console in debug mode)
|
||||||
isDebug bool
|
elog debug.Log // event log instance; connects to the Windows Event Log
|
||||||
app *app.App
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newService creates a new Windows service instance
|
// newService creates a new Windows service instance
|
||||||
@@ -39,66 +38,37 @@ func (svc *WindowsService) Run() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to determine if running as Windows service: %v", err)
|
return fmt.Errorf("failed to determine if running as Windows service: %v", err)
|
||||||
}
|
}
|
||||||
|
svc.logger.Debug("isService", "value", isService)
|
||||||
|
|
||||||
svc.isDebug = !isService
|
var run func(string, winsvc.Handler) error
|
||||||
|
|
||||||
|
// Acquire the appropriate run function & eventlog instance depending on service type
|
||||||
if isService {
|
if isService {
|
||||||
return svc.runAsService()
|
run = winsvc.Run
|
||||||
}
|
svc.elog, err = eventlog.Open(serviceName)
|
||||||
|
|
||||||
// Interactive mode
|
|
||||||
return svc.runInteractive()
|
|
||||||
}
|
|
||||||
|
|
||||||
// runAsService runs the application as a Windows service
|
|
||||||
func (svc *WindowsService) runAsService() error {
|
|
||||||
var err error
|
|
||||||
if svc.isDebug {
|
|
||||||
svc.elog = winsvcDebug.New(serviceName)
|
|
||||||
} else {
|
|
||||||
svc.elog, err = winsvcEventlog.Open(serviceName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open event log: %v", err)
|
return fmt.Errorf("failed to open event log: %v", err)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
run = debug.Run
|
||||||
|
svc.elog = debug.New(serviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer svc.elog.Close()
|
defer svc.elog.Close()
|
||||||
|
|
||||||
svc.elog.Info(1, fmt.Sprintf("starting %s service", serviceName))
|
svc.elog.Info(1, fmt.Sprintf("starting %s service", serviceName))
|
||||||
|
// Run the service with our handler
|
||||||
run := winsvc.Run
|
|
||||||
if svc.isDebug {
|
|
||||||
run = winsvcDebug.Run
|
|
||||||
}
|
|
||||||
|
|
||||||
err = run(serviceName, &serviceHandler{
|
err = run(serviceName, &serviceHandler{
|
||||||
service: svc,
|
service: svc,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
svc.elog.Error(1, fmt.Sprintf("%s service failed: %v", serviceName, err))
|
svc.elog.Error(1, fmt.Sprintf("%s service failed: %v", serviceName, err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.elog.Info(1, fmt.Sprintf("%s service stopped", serviceName))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runInteractive runs the application in interactive mode
|
|
||||||
func (svc *WindowsService) runInteractive() error {
|
|
||||||
svc.logger.Info("Application starting in interactive mode")
|
|
||||||
|
|
||||||
// Simple interactive loop
|
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for range ticker.C {
|
|
||||||
svc.logger.Debug("Application heartbeat")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serviceHandler implements the Windows service handler interface
|
|
||||||
type serviceHandler struct {
|
type serviceHandler struct {
|
||||||
service *WindowsService
|
service *WindowsService
|
||||||
}
|
}
|
||||||
@@ -107,7 +77,7 @@ func (handler *serviceHandler) Execute(args []string, r <-chan winsvc.ChangeRequ
|
|||||||
const cmdsAccepted = winsvc.AcceptStop | winsvc.AcceptShutdown | winsvc.AcceptPauseAndContinue
|
const cmdsAccepted = winsvc.AcceptStop | winsvc.AcceptShutdown | winsvc.AcceptPauseAndContinue
|
||||||
changes <- winsvc.Status{State: winsvc.StartPending}
|
changes <- winsvc.Status{State: winsvc.StartPending}
|
||||||
|
|
||||||
handler.service.logger.Info("Service starting")
|
handler.service.logger.Info("service starting")
|
||||||
changes <- winsvc.Status{State: winsvc.Running, Accepts: cmdsAccepted}
|
changes <- winsvc.Status{State: winsvc.Running, Accepts: cmdsAccepted}
|
||||||
|
|
||||||
// Service heartbeat
|
// Service heartbeat
|
||||||
@@ -123,7 +93,7 @@ func (handler *serviceHandler) Execute(args []string, r <-chan winsvc.ChangeRequ
|
|||||||
case winsvc.Stop, winsvc.Shutdown:
|
case winsvc.Stop, winsvc.Shutdown:
|
||||||
changes <- winsvc.Status{State: winsvc.StopPending}
|
changes <- winsvc.Status{State: winsvc.StopPending}
|
||||||
|
|
||||||
handler.service.logger.Info("Service stopping")
|
handler.service.logger.Info("service stopping")
|
||||||
if err := handler.service.app.Stop(); err != nil {
|
if err := handler.service.app.Stop(); err != nil {
|
||||||
handler.service.logger.Error("Failed to stop app layer", "error", err)
|
handler.service.logger.Error("Failed to stop app layer", "error", err)
|
||||||
}
|
}
|
||||||
@@ -131,14 +101,14 @@ func (handler *serviceHandler) Execute(args []string, r <-chan winsvc.ChangeRequ
|
|||||||
case winsvc.Pause:
|
case winsvc.Pause:
|
||||||
changes <- winsvc.Status{State: winsvc.Paused, Accepts: cmdsAccepted}
|
changes <- winsvc.Status{State: winsvc.Paused, Accepts: cmdsAccepted}
|
||||||
|
|
||||||
handler.service.logger.Info("Service pausing")
|
handler.service.logger.Info("service pausing")
|
||||||
if err := handler.service.app.Pause(); err != nil {
|
if err := handler.service.app.Pause(); err != nil {
|
||||||
handler.service.logger.Error("Failed to pause app layer", "error", err)
|
handler.service.logger.Error("Failed to pause app layer", "error", err)
|
||||||
}
|
}
|
||||||
case winsvc.Continue:
|
case winsvc.Continue:
|
||||||
changes <- winsvc.Status{State: winsvc.Running, Accepts: cmdsAccepted}
|
changes <- winsvc.Status{State: winsvc.Running, Accepts: cmdsAccepted}
|
||||||
|
|
||||||
handler.service.logger.Info("Service continuing")
|
handler.service.logger.Info("service continuing")
|
||||||
if err := handler.service.app.Resume(); err != nil {
|
if err := handler.service.app.Resume(); err != nil {
|
||||||
handler.service.logger.Error("Failed to resume app layer", "error", err)
|
handler.service.logger.Error("Failed to resume app layer", "error", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user