• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OneBusAway / watchdog / 16541364171

26 Jul 2025 03:40PM UTC coverage: 49.644% (-10.2%) from 59.798%
16541364171

Pull #77

github

Abo-Omar-74
refactor(gtfs): merge GTFS-RT fetching and parsing into FetchAndStoreGTFSRTFeed

- pass shared *http.Client and *RealtimeStore to avoid redundant API calls
- update function signature to support external dependency injection
- replaces old FetchGTFSRTFeed with unified FetchAndStoreGTFSRTFeed
- update test logic and function signature
- add HashRealtimeData helper for deterministic equality in tests of FetchAndStoreGTFSRTFeed
Pull Request #77: feat: use shared http.Client and RealtimeStore across GTFS functions

83 of 388 new or added lines in 13 files covered. (21.39%)

26 existing lines in 4 files now uncovered.

768 of 1547 relevant lines covered (49.64%)

0.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.97
/internal/utils/cache.go
1
package utils
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "log/slog"
7
        "os"
8
        "path/filepath"
9
        "strings"
10
        "time"
11

12
        "github.com/getsentry/sentry-go"
13
        "watchdog.onebusaway.org/internal/report"
14
)
15

16
func GetLastCachedFile(cacheDir string, serverID int) (string, error) {
1✔
17
        files, err := os.ReadDir(cacheDir)
1✔
18
        if err != nil {
2✔
19
                return "", err
1✔
20
        }
1✔
21

22
        var lastModTime time.Time
1✔
23
        var lastModFile string
1✔
24

1✔
25
        serverPrefix := fmt.Sprintf("server_%d_", serverID)
1✔
26

1✔
27
        for _, file := range files {
2✔
28
                if !file.IsDir() && strings.HasPrefix(file.Name(), serverPrefix) {
2✔
29
                        fileInfo, err := file.Info()
1✔
30
                        if err != nil {
1✔
31
                                return "", err
×
32
                        }
×
33
                        if fileInfo.ModTime().After(lastModTime) {
2✔
34
                                lastModTime = fileInfo.ModTime()
1✔
35
                                lastModFile = file.Name()
1✔
36
                        }
1✔
37
                }
38
        }
39

40
        if lastModFile == "" {
2✔
41
                return "", fmt.Errorf("no cached files found for server %d", serverID)
1✔
42
        }
1✔
43

44
        return filepath.Join(cacheDir, lastModFile), nil
1✔
45
}
46

47
// CreateCacheDirectory ensures the cache directory exists, creating it if necessary.
48
func CreateCacheDirectory(cacheDir string, logger *slog.Logger) error {
1✔
49
        stat, err := os.Stat(cacheDir)
1✔
50

1✔
51
        if err != nil {
2✔
52
                if os.IsNotExist(err) {
2✔
53
                        if err := os.MkdirAll(cacheDir, os.ModePerm); err != nil {
1✔
54
                                report.ReportErrorWithSentryOptions(err, report.SentryReportOptions{
×
55
                                        Level: sentry.LevelError,
×
56
                                        ExtraContext: map[string]interface{}{
×
57
                                                "cache_dir": cacheDir,
×
58
                                        },
×
59
                                })
×
60
                                return err
×
61
                        }
×
62
                        return nil
1✔
63
                }
64
                return err
×
65

66
        }
67
        if !stat.IsDir() {
2✔
68
                err := fmt.Errorf("%s is not a directory", cacheDir)
1✔
69
                report.ReportErrorWithSentryOptions(err, report.SentryReportOptions{
1✔
70
                        Level: sentry.LevelError,
1✔
71
                        ExtraContext: map[string]interface{}{
1✔
72
                                "cache_dir": cacheDir,
1✔
73
                        },
1✔
74
                })
1✔
75
                return err
1✔
76
        }
1✔
77
        return nil
1✔
78
}
79

NEW
80
func SaveMapToFile[C comparable, V any](data map[C]V, filepath string) error {
×
NEW
81
        file, err := os.Create(filepath)
×
NEW
82
        if err != nil {
×
NEW
83
                return err
×
NEW
84
        }
×
NEW
85
        defer file.Close()
×
NEW
86

×
NEW
87
        return json.NewEncoder(file).Encode(data)
×
88
}
89

NEW
90
func LoadMapFromFile[C comparable, V any](filepath string) (map[C]V, error) {
×
NEW
91
        file, err := os.Open(filepath)
×
NEW
92
        if err != nil {
×
NEW
93
                return nil, err
×
NEW
94
        }
×
NEW
95
        defer file.Close()
×
NEW
96

×
NEW
97
        var data map[C]V
×
NEW
98
        err = json.NewDecoder(file).Decode(&data)
×
NEW
99
        return data, err
×
100
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc