main
1package aod
2
3import (
4 "context"
5 "log/slog"
6 "time"
7
8 "github.com/bryfry/mm/internal/minecraft"
9)
10
11func Watch(domain string, timeout bool) error {
12
13 const (
14 _targetPort uint16 = 25565
15 _checkInterval time.Duration = time.Second * 5
16 _logInterval time.Duration = time.Minute * 5
17 _inactiveTimeout time.Duration = time.Minute * 55
18 )
19
20 ticker := time.NewTicker(_checkInterval)
21 defer ticker.Stop()
22
23 slog.Info("active or die: starting",
24 slog.String("domain", domain),
25 slog.Int("port", int(_targetPort)),
26 slog.Bool("poweroff_on_timeout", timeout))
27
28 // loop variables and timers
29 lastActive := time.Now()
30 lastLog := time.Now()
31 connections := -1 // log first active connection check
32 for {
33 select {
34 case <-ticker.C:
35
36 c, err := minecraft.Connections(domain, _targetPort)
37 if err != nil {
38 return err
39 }
40
41 // trigger logging if changes
42 changed := connections != c
43 connections = c
44
45 // calculate inacivity
46 inactiveDuration := time.Since(lastActive).Round(time.Second)
47 msg := "inactive"
48 details := []slog.Attr{
49 slog.String("duration", inactiveDuration.String()),
50 }
51 if timeout {
52 details = append(details,
53 slog.String("timeout", _inactiveTimeout.String()),
54 )
55 }
56
57 // reset if active
58 if connections != 0 {
59 lastActive = time.Now()
60 inactiveDuration = 0
61 msg = "active"
62 details = []slog.Attr{
63 slog.Int("connections", connections),
64 }
65 }
66
67 // log on change or at log interval
68 if changed || time.Since(lastLog) > _logInterval {
69 slog.LogAttrs(context.Background(), slog.LevelInfo, msg, details...)
70 lastLog = time.Now()
71 }
72
73 if inactiveDuration > _inactiveTimeout {
74 if timeout {
75 msg = "inactive timeout: powering off"
76 slog.LogAttrs(context.Background(), slog.LevelInfo, msg, details...)
77 return poweroff()
78 }
79 }
80 }
81 }
82}