From 8f0f24bf118e88258f8b4402f615a68110251b9d Mon Sep 17 00:00:00 2001 From: Michael McQuade Date: Wed, 28 Jan 2026 20:25:21 -0600 Subject: [PATCH] chore: fix lints --- cmd/slurm-tracker/main.go | 16 ++++++++-------- internal/config/config.go | 8 ++++---- internal/slurm/slurm.go | 16 ++++++++-------- internal/state/state.go | 28 ++++++++++++++-------------- internal/tracker/tracker.go | 4 ++-- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cmd/slurm-tracker/main.go b/cmd/slurm-tracker/main.go index 92012b4..91d9f03 100644 --- a/cmd/slurm-tracker/main.go +++ b/cmd/slurm-tracker/main.go @@ -103,18 +103,18 @@ func run(cmd *cobra.Command, args []string) error { Msg("Starting Slurm usage event collector") // Initialize state driver - stateDriver, err := state.NewStateDriver(cfg.StateFile) + stateDriver, err := state.NewDriver(cfg.StateFile) if err != nil { return fmt.Errorf("failed to initialize state driver: %w", err) } defer func() { - if err := stateDriver.Shutdown(); err != nil { - log.Error().Err(err).Msg("Error shutting down state driver") + if shutdownErr := stateDriver.Shutdown(); shutdownErr != nil { + log.Error().Err(shutdownErr).Msg("Error shutting down state driver") } }() // Get Slurm jobs - jobs, err := slurm.GetSlurmJobs(cfg.LookbackMinutes) + jobs, err := slurm.GetJobs(cfg.LookbackMinutes) if err != nil { return fmt.Errorf("failed to get Slurm jobs: %w", err) } @@ -124,20 +124,20 @@ func run(cmd *cobra.Command, args []string) error { semaphore := make(chan struct{}, 10) waitGroup := sync.WaitGroup{} // Process each job and create usage events - for _, job := range jobs { + for i := range jobs { waitGroup.Add(1) semaphore <- struct{}{} - go func(job slurm.SlurmJob) { + go func(job *slurm.Job) { defer waitGroup.Done() defer func() { <-semaphore }() - if err := tracker.ProcessJob(cfg, job, stateDriver, pwClient, cfg.DryRun); err != nil { + if err := tracker.ProcessJob(&cfg, job, stateDriver, pwClient, cfg.DryRun); err != nil { log.Error(). Err(err). Int("job_id", job.JobID). Str("job_name", job.Name). Msg("Failed to process job") } - }(job) + }(&jobs[i]) } waitGroup.Wait() diff --git a/internal/config/config.go b/internal/config/config.go index e9619ae..d7043f1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,8 +20,8 @@ type PartitionMapping struct { SKU string `json:"sku"` } -// ConfigFile represents the JSON configuration file structure -type ConfigFile struct { +// File represents the JSON configuration file structure +type File struct { DefaultSku string `json:"defaultSku"` DefaultAllocation string `json:"defaultAllocation"` Partition []PartitionMapping `json:"partition"` @@ -49,10 +49,10 @@ func LoadConfigFile(path string, cfg *Config) error { if os.IsNotExist(err) { return fmt.Errorf("config file %s not found: please create the config file or specify the correct path", path) } - return fmt.Errorf("failed to read config file %s: %w. Please check file permissions or path.", path, err) + return fmt.Errorf("failed to read config file %s: %w", path, err) } - var configFile ConfigFile + var configFile File if err := json.Unmarshal(data, &configFile); err != nil { return fmt.Errorf("failed to parse config file: %w", err) } diff --git a/internal/slurm/slurm.go b/internal/slurm/slurm.go index 74d10a7..7a67e5e 100644 --- a/internal/slurm/slurm.go +++ b/internal/slurm/slurm.go @@ -24,7 +24,7 @@ type SacctOutput struct { } `json:"version"` } `json:"Slurm"` } `json:"meta"` - Jobs []SlurmJob `json:"jobs"` + Jobs []Job `json:"jobs"` Errors []any `json:"errors"` Warnings []any `json:"warnings"` } @@ -36,8 +36,8 @@ type NumberValue struct { Number int `json:"number"` } -// SlurmJob represents a single job from sacct output -type SlurmJob struct { +// Job represents a single job from sacct output +type Job struct { JobID int `json:"job_id"` Name string `json:"name"` User string `json:"user"` @@ -107,8 +107,8 @@ type TresAlloc struct { Count int `json:"count"` } -// GetSlurmJobs queries sacct and returns parsed job data -func GetSlurmJobs(lookbackMinutes int) ([]SlurmJob, error) { +// GetJobs queries sacct and returns parsed job data +func GetJobs(lookbackMinutes int) ([]Job, error) { // Calculate the start time startTime := time.Now().Add(-time.Duration(lookbackMinutes) * time.Minute) startTimeStr := startTime.Format("2006-01-02T15:04:05") @@ -156,12 +156,12 @@ func GetSlurmJobs(lookbackMinutes int) ([]SlurmJob, error) { } // IsJobRunning returns true if the job is currently running -func IsJobRunning(job SlurmJob) bool { +func IsJobRunning(job *Job) bool { return job.State.Current == "RUNNING" } // IsJobCompleted returns true if the job has reached a terminal state -func IsJobCompleted(job SlurmJob) bool { +func IsJobCompleted(job *Job) bool { completedStates := map[string]bool{ "COMPLETED": true, "FAILED": true, @@ -175,7 +175,7 @@ func IsJobCompleted(job SlurmJob) bool { } // CalculateCoreHoursForElapsed calculates core hours for a given elapsed time -func CalculateCoreHoursForElapsed(job SlurmJob, elapsedSeconds int) float64 { +func CalculateCoreHoursForElapsed(job *Job, elapsedSeconds int) float64 { // Elapsed time is in seconds elapsedHours := float64(elapsedSeconds) / 3600.0 diff --git a/internal/state/state.go b/internal/state/state.go index 40e4b24..388737d 100644 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -6,7 +6,7 @@ import ( "sync" "time" - _ "modernc.org/sqlite" + _ "modernc.org/sqlite" // register sqlite driver "github.com/rs/zerolog/log" ) @@ -20,15 +20,15 @@ type JobState struct { CompletedAt int64 `json:"completed_at,omitempty"` // unix timestamp when job completed (0 if still running) } -// StateDriver manages concurrent access to job states with SQLite persistence -type StateDriver struct { +// Driver manages concurrent access to job states with SQLite persistence +type Driver struct { db *sql.DB dbPath string mutex sync.RWMutex } -// NewStateDriver creates a new state driver with SQLite backend -func NewStateDriver(dbPath string) (*StateDriver, error) { +// NewDriver creates a new state driver with SQLite backend +func NewDriver(dbPath string) (*Driver, error) { db, err := sql.Open("sqlite", dbPath) if err != nil { return nil, fmt.Errorf("failed to open database: %w", err) @@ -38,7 +38,7 @@ func NewStateDriver(dbPath string) (*StateDriver, error) { db.SetMaxOpenConns(1) // SQLite works best with single writer db.SetMaxIdleConns(1) - driver := &StateDriver{ + driver := &Driver{ db: db, dbPath: dbPath, } @@ -57,7 +57,7 @@ func NewStateDriver(dbPath string) (*StateDriver, error) { } // initSchema creates the job_states table if it doesn't exist -func (d *StateDriver) initSchema() error { +func (d *Driver) initSchema() error { query := ` CREATE TABLE IF NOT EXISTS job_states ( job_id INTEGER PRIMARY KEY, @@ -73,7 +73,7 @@ func (d *StateDriver) initSchema() error { } // GetState retrieves a job state by ID -func (d *StateDriver) GetState(jobID int) (JobState, bool) { +func (d *Driver) GetState(jobID int) (JobState, bool) { var state JobState query := ` SELECT job_id, last_reported_elapsed, last_reported_at, total_core_hours, completed_at @@ -103,7 +103,7 @@ func (d *StateDriver) GetState(jobID int) (JobState, bool) { } // UpdateState updates a job state immediately -func (d *StateDriver) UpdateState(state JobState) { +func (d *Driver) UpdateState(state JobState) { query := ` INSERT INTO job_states (job_id, last_reported_elapsed, last_reported_at, total_core_hours, completed_at) VALUES (?, ?, ?, ?, ?) @@ -130,7 +130,7 @@ func (d *StateDriver) UpdateState(state JobState) { } // DeleteState removes a job state -func (d *StateDriver) DeleteState(jobID int) { +func (d *Driver) DeleteState(jobID int) { d.mutex.Lock() _, err := d.db.Exec("DELETE FROM job_states WHERE job_id = ?", jobID) d.mutex.Unlock() @@ -141,7 +141,7 @@ func (d *StateDriver) DeleteState(jobID int) { } // GetAllStates returns all job states -func (d *StateDriver) GetAllStates() map[int]JobState { +func (d *Driver) GetAllStates() map[int]JobState { query := ` SELECT job_id, last_reported_elapsed, last_reported_at, total_core_hours, completed_at FROM job_states @@ -177,14 +177,14 @@ func (d *StateDriver) GetAllStates() map[int]JobState { } // getJobCount returns the number of tracked jobs -func (d *StateDriver) getJobCount() (int, error) { +func (d *Driver) getJobCount() (int, error) { var count int err := d.db.QueryRow("SELECT COUNT(*) FROM job_states").Scan(&count) return count, err } // Shutdown gracefully shuts down the driver -func (d *StateDriver) Shutdown() error { +func (d *Driver) Shutdown() error { if err := d.db.Close(); err != nil { log.Error().Err(err).Msg("Error closing database") return err @@ -195,7 +195,7 @@ func (d *StateDriver) Shutdown() error { } // CleanupOldStates removes states for jobs completed more than the specified duration ago -func (d *StateDriver) CleanupOldStates(olderThan time.Duration) int { +func (d *Driver) CleanupOldStates(olderThan time.Duration) int { cutoffTime := time.Now().Add(-olderThan).Unix() d.mutex.Lock() diff --git a/internal/tracker/tracker.go b/internal/tracker/tracker.go index e857739..3da26bd 100644 --- a/internal/tracker/tracker.go +++ b/internal/tracker/tracker.go @@ -25,7 +25,7 @@ type UsageEventResponse struct { } // ProcessJob processes a single Slurm job, calculating usage and reporting it -func ProcessJob(cfg config.Config, job slurm.SlurmJob, stateDriver *state.StateDriver, pwClient *parallelworks.ClientWithResponses, dryRun bool) error { +func ProcessJob(cfg *config.Config, job *slurm.Job, stateDriver *state.Driver, pwClient *parallelworks.ClientWithResponses, dryRun bool) error { isRunning := slurm.IsJobRunning(job) isCompleted := slurm.IsJobCompleted(job) @@ -33,7 +33,7 @@ func ProcessJob(cfg config.Config, job slurm.SlurmJob, stateDriver *state.StateD if !isRunning && !isCompleted { log.Debug(). Int("job_id", job.JobID). - Str("state", fmt.Sprintf("%v", job.State.Current)). + Str("state", job.State.Current). Msg("Skipping job (not running or completed)") return nil }