Commit 57ccc40
Eric Bower
·
2026-05-08 20:16:53 -0400 EDT
parent 97d87a6
chore: copy changes
2 files changed,
+22,
-5
M
main.go
+21,
-5
| ... | ... | @@ -54,6 +54,7 @@ type Cfg struct { | |
| 54 | 54 | Event string // event JSON passed via --event flag | |
| 55 | 55 | EventSource io.ReadCloser // when set, used directly as the event source (for testing) | |
| 56 | 56 | MonitorInterval time.Duration | |
| 57 | + | GCInterval time.Duration | |
| 57 | 58 | NewWorkspace WorkspaceFactory | |
| 58 | 59 | StatusOutput io.Writer // where status JSONL is written (default: os.Stdout) | |
| 59 | 60 | IncludeRunning bool // emit running status updates in addition to terminal |
| ... | ... | @@ -73,12 +74,14 @@ type Event struct { | |
| 73 | 74 | func NewCfg() (*Cfg, string, bool) { | |
| 74 | 75 | var keyLoc, certLoc, artifactDir, event string | |
| 75 | 76 | var monitorInterval time.Duration | |
| 77 | + | var gcInterval time.Duration | |
| 76 | 78 | var logLevel string | |
| 77 | 79 | flag.StringVar(&keyLoc, "pk", "", "ssh private key used to authenticate with pico services") | |
| 78 | 80 | flag.StringVar(&certLoc, "ck", "", "ssh certificate public key used to authenticate with pico services (only required if using ssh certificates)") | |
| 79 | 81 | flag.StringVar(&artifactDir, "artifact-dir", "/tmp/pici-artifacts", "local directory to stage artifacts") | |
| 80 | 82 | flag.StringVar(&event, "event", "", "event JSON to run (alternative to reading from stdin)") | |
| 81 | 83 | flag.DurationVar(&monitorInterval, "monitor-interval", 5*time.Second, "interval for monitoring zmx sessions") | |
| 84 | + | flag.DurationVar(&gcInterval, "gc-interval", 10*time.Minute, "interval for garbage collection in monitor (0 to disable)") | |
| 82 | 85 | flag.StringVar(&logLevel, "log-level", "info", "log level: debug, info, warn, error") | |
| 83 | 86 | var includeRunning bool | |
| 84 | 87 | var human bool |
| ... | ... | @@ -107,6 +110,7 @@ func NewCfg() (*Cfg, string, bool) { | |
| 107 | 110 | ArtifactDir: artifactDir, | |
| 108 | 111 | Event: event, | |
| 109 | 112 | MonitorInterval: monitorInterval, | |
| 113 | + | GCInterval: gcInterval, | |
| 110 | 114 | IncludeRunning: includeRunning, | |
| 111 | 115 | HumanOutput: human, | |
| 112 | 116 | Wait: wait, |
| ... | ... | @@ -226,6 +230,7 @@ FLAGS | |
| 226 | 230 | -ck <path> SSH certificate public key | |
| 227 | 231 | -artifact-dir <path> Local directory to stage artifacts (default: /tmp/pici-artifacts) | |
| 228 | 232 | -monitor-interval <dur> Poll interval (default: 5s) | |
| 233 | + | -gc-interval <dur> Garbage collection interval (default: 10m, 0 to disable) | |
| 229 | 234 | -include-running Emit running status updates in addition to terminal (default: terminal only) | |
| 230 | 235 | -human Human-readable output instead of JSONL (for terminal, not piping) | |
| 231 | 236 | -log-level <level> Log level: debug, info, warn, error (default: info)`) |
| ... | ... | @@ -892,10 +897,17 @@ func runMonitor(cfg *Cfg) error { | |
| 892 | 897 | ticker := time.NewTicker(cfg.MonitorInterval) | |
| 893 | 898 | defer ticker.Stop() | |
| 894 | 899 | ||
| 900 | + | // Optional GC ticker — runs garbage collection on a separate interval. | |
| 901 | + | var gcTicker *time.Ticker | |
| 902 | + | if cfg.GCInterval > 0 { | |
| 903 | + | gcTicker = time.NewTicker(cfg.GCInterval) | |
| 904 | + | defer gcTicker.Stop() | |
| 905 | + | } | |
| 906 | + | ||
| 895 | 907 | // Track per-job display state across ticks (for human output) | |
| 896 | 908 | jobStates := make(map[string]*monitorJobState) // key: "name/jobID" | |
| 897 | 909 | ||
| 898 | - | log.Debug("monitor started", "interval", cfg.MonitorInterval, "artifact_dir", cfg.ArtifactDir) | |
| 910 | + | log.Debug("monitor started", "interval", cfg.MonitorInterval, "gc_interval", cfg.GCInterval, "artifact_dir", cfg.ArtifactDir) | |
| 899 | 911 | log.Debug("monitoring ci.* sessions for job status, writing status to stdout") | |
| 900 | 912 | ||
| 901 | 913 | for { |
| ... | ... | @@ -904,10 +916,14 @@ func runMonitor(cfg *Cfg) error { | |
| 904 | 916 | log.Debug("context cancelled, stopping monitor") | |
| 905 | 917 | return cfg.Ctx.Err() | |
| 906 | 918 | case <-ticker.C: | |
| 907 | - | } | |
| 908 | - | ||
| 909 | - | if err := monitorTick(cfg, log, output, jobStates); err != nil { | |
| 910 | - | log.Error("monitor tick", "err", err) | |
| 919 | + | if err := monitorTick(cfg, log, output, jobStates); err != nil { | |
| 920 | + | log.Error("monitor tick", "err", err) | |
| 921 | + | } | |
| 922 | + | case <-gcTicker.C: | |
| 923 | + | log.Debug("running periodic garbage collection") | |
| 924 | + | if err := runGC(cfg); err != nil { | |
| 925 | + | log.Error("periodic gc", "err", err) | |
| 926 | + | } | |
| 911 | 927 | } | |
| 912 | 928 | } | |
| 913 | 929 | } |
+1,
-0
| ... | ... | @@ -17,6 +17,7 @@ | |
| 17 | 17 | <span>ID: {{.JobID}}</span> | |
| 18 | 18 | <span>Duration: {{.Duration}}</span> | |
| 19 | 19 | {{if .ExitCode}}<span>Exit: {{.ExitCode}}</span>{{end}} | |
| 20 | + | <span>Connect: <code>zmx attach {{.SessionName}}</code></span> | |
| 20 | 21 | </div> | |
| 21 | 22 | <div class="zmx-output">{{.Content}}</div> | |
| 22 | 23 | <div class="links"> |