diff --git a/.jules/bolt.md b/.jules/bolt.md index 18bfea9..aaa84e6 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -5,3 +5,5 @@ ## 2025-12-18 - [JSON Unmarshalling] **Learning:** Polymorphic JSON messages (flat structure) often lead to double parsing (once for type, once for content). **Action:** Use a "Unified" struct containing all possible fields to allow single-pass unmarshalling when fields do not collide. ## 2024-05-22 - [Buffer String Construction] **Learning:** Using `strings.Builder` with `Grow` is significantly faster than `bytes.Buffer` for constructing strings from parts, as `strings.Builder.String()` avoids the final allocation. **Action:** Prefer `strings.Builder` over `bytes.Buffer` when the final goal is a `string`. + +## 2026-01-29 - [System Call Hoisting] **Learning:** `os.Executable()` on Linux performs a `readlink` syscall which is not cached by the Go runtime. In a loop, this syscall overhead dominates execution time (e.g., ~2.8µs vs ~0.35µs per op). **Action:** Hoist `os.Executable()` and similar system calls (like `os.Getwd`) out of hot loops. diff --git a/cmd/daemon.go b/cmd/daemon.go index 0ca04a0..c80c02f 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -417,6 +417,12 @@ func generateCronContent(jobs []protocol.JobDefinition, systemMode bool) []byte buf.WriteString("SHELL=/bin/bash\n") buf.WriteString("PATH=/usr/local/bin:/usr/bin:/bin\n\n") + // Self-executable path + execPath, err := os.Executable() + if err != nil { + execPath = "/usr/local/bin/cc-agent" + } + for _, job := range jobs { if containsNewline(job.CronExpression) || containsNewline(job.JobID) || containsNewline(job.Command) { log.Printf("Skipping job %q: contains invalid characters", job.JobID) @@ -434,12 +440,6 @@ func generateCronContent(jobs []protocol.JobDefinition, systemMode bool) []byte buf.WriteString("root ") } - // Self-executable path - execPath, err := os.Executable() - if err != nil { - execPath = "/usr/local/bin/cc-agent" - } - buf.WriteString(execPath) buf.WriteString(" exec --job-id ") writeShellQuote(&buf, job.JobID)