Skip to content

Commit

Permalink
Merge pull request #414 from tphakala/fix-random-linter-errors
Browse files Browse the repository at this point in the history
refactor: fix various linter warnings
  • Loading branch information
tphakala authored Jan 25, 2025
2 parents f5dff52 + 19609e8 commit 8f7f3a8
Show file tree
Hide file tree
Showing 28 changed files with 125 additions and 122 deletions.
2 changes: 1 addition & 1 deletion cmd/benchmark/benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func runInferenceBenchmark(settings *conf.Settings, results *benchmarkResults) e
return nil
}

func getPerformanceRating(inferenceTime float64) (string, string) {
func getPerformanceRating(inferenceTime float64) (rating, description string) {
switch {
case inferenceTime > 3000:
return "❌ Failed", "System is too slow for BirdNET-Go real-time detection"
Expand Down
2 changes: 1 addition & 1 deletion internal/analysis/processor/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func (a *BirdWeatherAction) Execute(data interface{}) error {
return fmt.Errorf("BirdWeather client is not initialized")
}

if err := a.BwClient.Publish(a.Note, a.pcmData); err != nil {
if err := a.BwClient.Publish(&a.Note, a.pcmData); err != nil {
log.Printf("error uploading to BirdWeather: %s\n", err)
return err
} else if a.Settings.Debug {
Expand Down
2 changes: 1 addition & 1 deletion internal/analysis/queue/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Results struct {
// This is needed because the data in the struct is a pointer to the original data
// and if we don't make a deep copy, the original data will be overwritten when the
// struct is reused for another detection.
func (r Results) Copy() Results {
func (r Results) Copy() Results { //nolint:gocritic // This is a copy function, avoid warning about heavy parameters
// Create a new Results struct with simple field copies
newCopy := Results{
StartTime: r.StartTime,
Expand Down
12 changes: 6 additions & 6 deletions internal/analysis/realtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func RealtimeAnalysis(settings *conf.Settings, notificationChan chan handlers.No

// start cleanup of clips
if conf.Setting().Realtime.Audio.Export.Retention.Policy != "none" {
startClipCleanupMonitor(&wg, dataStore, quitChan)
startClipCleanupMonitor(&wg, quitChan)
}

// start weather polling
Expand Down Expand Up @@ -188,9 +188,9 @@ func startAudioCapture(wg *sync.WaitGroup, settings *conf.Settings, quitChan, re
}

// startClipCleanupMonitor initializes and starts the clip cleanup monitoring routine in a new goroutine.
func startClipCleanupMonitor(wg *sync.WaitGroup, dataStore datastore.Interface, quitChan chan struct{}) {
func startClipCleanupMonitor(wg *sync.WaitGroup, quitChan chan struct{}) {
wg.Add(1)
go clipCleanupMonitor(wg, dataStore, quitChan)
go clipCleanupMonitor(wg, quitChan)
}

// startWeatherPolling initializes and starts the weather polling routine in a new goroutine.
Expand Down Expand Up @@ -247,7 +247,7 @@ func closeDataStore(store datastore.Interface) {
}

// ClipCleanupMonitor monitors the database and deletes clips that meet the retention policy.
func clipCleanupMonitor(wg *sync.WaitGroup, dataStore datastore.Interface, quitChan chan struct{}) {
func clipCleanupMonitor(wg *sync.WaitGroup, quitChan chan struct{}) {
defer wg.Done() // Ensure that the WaitGroup is marked as done after the function exits

// Create a ticker that triggers every five minutes to perform cleanup
Expand Down Expand Up @@ -302,7 +302,7 @@ func initBirdImageCache(ds datastore.Interface, metrics *telemetry.Metrics) *ima
// Use a WaitGroup to wait for all goroutines to complete
var wg sync.WaitGroup

for _, species := range speciesList {
for i := range speciesList {
wg.Add(1)

// Launch a goroutine to fetch the image for each species
Expand All @@ -316,7 +316,7 @@ func initBirdImageCache(ds datastore.Interface, metrics *telemetry.Metrics) *ima
} else {
//log.Printf("Successfully fetched image for species %s\n", speciesName)
}*/
}(species.ScientificName)
}(speciesList[i].ScientificName)
}

// Wait for all goroutines to complete
Expand Down
10 changes: 5 additions & 5 deletions internal/birdweather/birdweather.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func New(settings *conf.Settings) (*BwClient, error) {
// RandomizeLocation adds a random offset to the given latitude and longitude to fuzz the location
// within a specified radius in meters for privacy, truncating the result to 4 decimal places.
// radiusMeters - the maximum radius in meters to adjust the coordinates
func (b *BwClient) RandomizeLocation(radiusMeters float64) (float64, float64) {
func (b *BwClient) RandomizeLocation(radiusMeters float64) (latitude, longitude float64) {
// Create a new local random generator seeded with current Unix time
src := rand.NewSource(time.Now().UnixNano())
rnd := rand.New(src)
Expand All @@ -74,10 +74,10 @@ func (b *BwClient) RandomizeLocation(radiusMeters float64) (float64, float64) {
lonOffset := (rnd.Float64() - 0.5) * 2 * degreeOffset

// Apply the offsets to the original coordinates and truncate to 4 decimal places
newLatitude := math.Floor((b.Latitude+latOffset)*10000) / 10000
newLongitude := math.Floor((b.Longitude+lonOffset)*10000) / 10000
latitude = math.Floor((b.Latitude+latOffset)*10000) / 10000
longitude = math.Floor((b.Longitude+lonOffset)*10000) / 10000

return newLatitude, newLongitude
return latitude, longitude
}

// handleNetworkError handles network errors and returns a more specific error message.
Expand Down Expand Up @@ -257,7 +257,7 @@ func (b *BwClient) PostDetection(soundscapeID, timestamp, commonName, scientific

// Upload function handles the uploading of detected clips and their details to Birdweather.
// It first parses the timestamp from the note, then uploads the soundscape, and finally posts the detection.
func (b *BwClient) Publish(note datastore.Note, pcmData []byte) error {
func (b *BwClient) Publish(note *datastore.Note, pcmData []byte) error {
// Add check for empty pcmData
if len(pcmData) == 0 {
return fmt.Errorf("pcmData is empty")
Expand Down
2 changes: 1 addition & 1 deletion internal/conf/locale.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func NormalizeLocale(inputLocale string) (string, error) {
}

for code, fullName := range LocaleCodes {
if strings.ToLower(fullName) == inputLocale {
if strings.EqualFold(fullName, inputLocale) {
return code, nil
}
}
Expand Down
6 changes: 3 additions & 3 deletions internal/conf/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func GetBasePath(path string) string {
// Check if the directory exists.
if _, err := os.Stat(basePath); os.IsNotExist(err) {
// Attempt to create the directory if it doesn't exist.
if err := os.MkdirAll(basePath, 0755); err != nil {
if err := os.MkdirAll(basePath, 0o755); err != nil {
fmt.Printf("failed to create directory '%s': %v\n", basePath, err)
// Note: In a robust application, you might want to handle this error more gracefully.
}
Expand Down Expand Up @@ -222,7 +222,7 @@ func ParsePercentage(percentage string) (float64, error) {

// ParseRetentionPeriod converts a string like "24h", "7d", "1w", "3m", "1y" to hours.
func ParseRetentionPeriod(retention string) (int, error) {
if len(retention) == 0 {
if retention == "" {
return 0, fmt.Errorf("retention period cannot be empty")
}

Expand Down Expand Up @@ -325,7 +325,7 @@ func IsFfmpegAvailable() bool {

// IsSoxAvailable checks if SoX is available in the system PATH and returns its supported audio formats.
// It returns a boolean indicating if SoX is available and a slice of supported audio format strings.
func IsSoxAvailable() (bool, []string) {
func IsSoxAvailable() (isAvailable bool, formats []string) {
// Look for the SoX binary in the system PATH
soxPath, err := exec.LookPath(GetSoxBinaryName())
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/cpuspec/cpuspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func determinePerformanceCores(brandName string) int {
model := matches[3]
switch {
case series == "9":
switch model {
switch model { //nolint:gocritic // ignore gocritic warning for this switch statement
case "285":
return 8 // Core Ultra 9 285(K): 8 P-cores (not 16 - that was E-cores)
}
Expand Down
76 changes: 40 additions & 36 deletions internal/datastore/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,50 +84,54 @@ func (ds *DataStore) Save(note *Note, results []Results) error {
continue
}

// Roll back the transaction if a panic occurs
defer func() {
if r := recover(); r != nil {
err := func() error {
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()

// Save the note and its associated results within the transaction
if err := tx.Create(note).Error; err != nil {
tx.Rollback()
if strings.Contains(strings.ToLower(err.Error()), "database is locked") {
return err
}
return fmt.Errorf("saving note: %w", err)
}
}()

// Save the note and its associated results within the transaction
if err := tx.Create(note).Error; err != nil {
tx.Rollback()
if strings.Contains(strings.ToLower(err.Error()), "database is locked") {
delay := baseDelay * time.Duration(attempt+1)
log.Printf("[%s] Database locked, retrying in %v (attempt %d/%d)", txID, delay, attempt+1, maxRetries)
time.Sleep(delay)
continue
// Assign the note ID to each result and save them
for _, result := range results {
result.NoteID = note.ID
if err := tx.Create(&result).Error; err != nil {
tx.Rollback()
if strings.Contains(strings.ToLower(err.Error()), "database is locked") {
return err
}
return fmt.Errorf("saving result: %w", err)
}
}
return fmt.Errorf("saving note: %w", err)
}

// Assign the note ID to each result and save them
for _, result := range results {
result.NoteID = note.ID
if err := tx.Create(&result).Error; err != nil {
tx.Rollback()
// Commit the transaction
if err := tx.Commit().Error; err != nil {
if strings.Contains(strings.ToLower(err.Error()), "database is locked") {
delay := baseDelay * time.Duration(attempt+1)
log.Printf("[%s] Database locked, retrying in %v (attempt %d/%d)", txID, delay, attempt+1, maxRetries)
time.Sleep(delay)
continue
return err
}
lastErr = fmt.Errorf("saving result: %w", err)
return lastErr
return fmt.Errorf("committing transaction: %w", err)
}
}

// Commit the transaction
if err := tx.Commit().Error; err != nil {
return nil
}()

if err != nil {
if strings.Contains(strings.ToLower(err.Error()), "database is locked") {
delay := baseDelay * time.Duration(attempt+1)
log.Printf("[%s] Database locked, retrying in %v (attempt %d/%d)", txID, delay, attempt+1, maxRetries)
time.Sleep(delay)
lastErr = err
continue
}
return fmt.Errorf("committing transaction: %w", err)
return err
}

// Log if retry count is not 0 and transaction was successful
Expand Down Expand Up @@ -254,7 +258,7 @@ type ClipForRemoval struct {

// GetClipsQualifyingForRemoval returns the list of clips that qualify for removal based on retention policy.
// It checks each clip's age and count of recordings per scientific name, filtering out clips based on provided minimum hours and clip count criteria.
func (ds *DataStore) GetClipsQualifyingForRemoval(minHours int, minClips int) ([]ClipForRemoval, error) {
func (ds *DataStore) GetClipsQualifyingForRemoval(minHours, minClips int) ([]ClipForRemoval, error) {
// Validate input parameters
if minHours <= 0 || minClips <= 0 {
return nil, fmt.Errorf("invalid parameters: minHours and minClips must be greater than 0")
Expand Down Expand Up @@ -327,7 +331,7 @@ func (ds *DataStore) GetHourlyOccurrences(date, commonName string, minConfidence
}

// SpeciesDetections retrieves bird species detections for a specific date and time period.
func (ds *DataStore) SpeciesDetections(species, date, hour string, duration int, sortAscending bool, limit int, offset int) ([]Note, error) {
func (ds *DataStore) SpeciesDetections(species, date, hour string, duration int, sortAscending bool, limit, offset int) ([]Note, error) {
sortOrder := sortAscendingString(sortAscending)

query := ds.DB.Where("common_name = ? AND date = ?", species, date)
Expand Down Expand Up @@ -374,7 +378,7 @@ func (ds *DataStore) GetAllDetectedSpecies() ([]Note, error) {
}

// SearchNotes performs a search on notes with optional sorting, pagination, and limits.
func (ds *DataStore) SearchNotes(query string, sortAscending bool, limit int, offset int) ([]Note, error) {
func (ds *DataStore) SearchNotes(query string, sortAscending bool, limit, offset int) ([]Note, error) {
var notes []Note
sortOrder := sortAscendingString(sortAscending)

Expand Down Expand Up @@ -496,7 +500,7 @@ func createGormLogger() logger.Interface {
}

// GetHourlyDetections retrieves bird detections for a specific date and hour.
func (ds *DataStore) GetHourlyDetections(date string, hour string, duration int) ([]Note, error) {
func (ds *DataStore) GetHourlyDetections(date, hour string, duration int) ([]Note, error) {
var detections []Note

startTime, endTime := getHourRange(hour, duration)
Expand Down Expand Up @@ -539,10 +543,10 @@ func (ds *DataStore) CountSearchResults(query string) (int64, error) {
return count, nil
}

func getHourRange(hour string, duration int) (string, string) {
func getHourRange(hour string, duration int) (startTime, endTime string) {
startHour, _ := strconv.Atoi(hour)
endHour := (startHour + duration) % 24
startTime := fmt.Sprintf("%02d:00:00", startHour)
endTime := fmt.Sprintf("%02d:00:00", endHour)
startTime = fmt.Sprintf("%02d:00:00", startHour)
endTime = fmt.Sprintf("%02d:00:00", endHour)
return startTime, endTime
}
4 changes: 2 additions & 2 deletions internal/datastore/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ type MySQLStore struct {
Settings *conf.Settings
}

func validateMySQLConfig(settings *conf.Settings) error {
func validateMySQLConfig() error {
// Add validation logic for MySQL configuration
// Return an error if the configuration is invalid
return nil
}

// InitializeDatabase sets up the MySQL database connection
func (store *MySQLStore) Open() error {
if err := validateMySQLConfig(store.Settings); err != nil {
if err := validateMySQLConfig(); err != nil {
return err // validateMySQLConfig returns a properly formatted error
}

Expand Down
4 changes: 2 additions & 2 deletions internal/datastore/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ type SQLiteStore struct {
Settings *conf.Settings
}

func validateSQLiteConfig(settings *conf.Settings) error {
func validateSQLiteConfig() error {
// Add validation logic for SQLite configuration
// Return an error if the configuration is invalid
return nil
}

// InitializeDatabase sets up the SQLite database connection
func (store *SQLiteStore) Open() error {
if err := validateSQLiteConfig(store.Settings); err != nil {
if err := validateSQLiteConfig(); err != nil {
return err // validateSQLiteConfig returns a properly formatted error
}

Expand Down
2 changes: 1 addition & 1 deletion internal/diagnostics/capture_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func CaptureSystemInfo(errorMessage string) string {
debugFilePath := filepath.Join(filepath.Dir(configPath), debugFileName)

// Write the debug info to the file
err = os.WriteFile(debugFilePath, []byte(info.String()), 0644)
err = os.WriteFile(debugFilePath, []byte(info.String()), 0o644)
if err != nil {
log.Printf("Error writing debug file: %v", err)
} else {
Expand Down
16 changes: 8 additions & 8 deletions internal/diagnostics/support_collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ func CollectDiagnostics() (string, error) {
case "linux":
err = collectLinuxDiagnostics(tmpDir)
case "windows":
err = collectWindowsDiagnostics(tmpDir)
err = collectWindowsDiagnostics()
case "darwin":
err = collectMacOSDiagnostics(tmpDir)
err = collectMacOSDiagnostics()
default:
err = fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
Expand Down Expand Up @@ -137,7 +137,7 @@ func collectLegacyLogs(tmpDir string) error {
fmt.Printf("Notice: Failed to tail %s: %v\n", file, err)
continue
}
if _, err := f.WriteString(fmt.Sprintf("=== %s ===\n", file)); err != nil {
if _, err := fmt.Fprintf(f, "=== %s ===\n", file); err != nil {
return fmt.Errorf("failed to write file header: %w", err)
}
if _, err := f.Write(tailOutput); err != nil {
Expand Down Expand Up @@ -186,7 +186,7 @@ func collectHardwareInfo(tmpDir string) error {
}

// collectWindowsDiagnostics gathers Windows-specific diagnostic information
func collectWindowsDiagnostics(tmpDir string) error {
func collectWindowsDiagnostics() error {
// TODO: Implement Windows-specific diagnostics collection
// This function should gather information such as:
// - System information (using 'systeminfo' command)
Expand All @@ -200,7 +200,7 @@ func collectWindowsDiagnostics(tmpDir string) error {
}

// collectMacOSDiagnostics gathers macOS-specific diagnostic information
func collectMacOSDiagnostics(tmpDir string) error {
func collectMacOSDiagnostics() error {
// TODO: Implement macOS-specific diagnostics collection
// This function should gather information such as:
// - System information (using 'system_profiler' command)
Expand Down Expand Up @@ -311,7 +311,7 @@ func runCommand(command string, args []string, outputFile string) error {

// Write the command output to the specified file
// 0644 sets read/write permissions for owner, and read-only for others
return os.WriteFile(outputFile, output, 0644)
return os.WriteFile(outputFile, output, 0o644)
}

// zipDirectory compresses the contents of a source directory into a zip file
Expand Down Expand Up @@ -413,7 +413,7 @@ func collectConfigFile(tmpDir string) error {

// Write the masked config to the temporary directory
outputPath := filepath.Join(tmpDir, "config.yaml")
err = os.WriteFile(outputPath, []byte(maskedContent), 0644)
err = os.WriteFile(outputPath, []byte(maskedContent), 0o644)
if err != nil {
return fmt.Errorf("error writing masked config file: %w", err)
}
Expand Down Expand Up @@ -466,7 +466,7 @@ func maskValue(value string) string {
// isIPOrURL checks if a string is an IP address or URL
func isIPOrURL(value string) bool {
ipRegex := regexp.MustCompile(`^(\d{1,3}\.){3}\d{1,3}(:\d+)?$`)
urlRegex := regexp.MustCompile(`^(http|https|rtsp):\/\/`)
urlRegex := regexp.MustCompile(`^(http|https|rtsp)://`)
return ipRegex.MatchString(value) || urlRegex.MatchString(value)
}

Expand Down
Loading

0 comments on commit 8f7f3a8

Please sign in to comment.