diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 6bfbda0..9b908bf 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -23,22 +23,32 @@ func New[T any](path string) *Cache[T] { return &Cache[T]{path} } +var ( + ErrorUnableToMarshalJSON = errors.New("unable to marshal as JSON") + ErrorUnableToEnsureCacheDir = errors.New("unable to ensure cache-dir is present") + ErrorUnableToWriteCache = errors.New("unable to write data to cache file") + ErrorUnableToOpenCacheFile = errors.New("unable to open cache") + ErrorUnableToReadCacheFile = errors.New("unable to read cache") + ErrorUnableToUnmarshalCacheFile = errors.New("unable to unmarshal JSON from cache-file") + ErrorUnableToReadCachePath = errors.New("unable to read from cache path") +) + // Add data as JSON-file into cache-dir, returns nil if success func (c *Cache[T]) Add(name string, data any) error { j, err := json.MarshalIndent(data, "", " ") if err != nil { - return fmt.Errorf("Failed to convert data as JSON.") + return ErrorUnableToMarshalJSON } err = os.MkdirAll(c.Path, 0646) if err != nil { - return fmt.Errorf("Failed to ensure cache-dir is present.") + return ErrorUnableToEnsureCacheDir } filePath := filepath.Join(c.Path, filename(name)) d := []byte(j) err = os.WriteFile(filePath, d, 0646) if err != nil { - return fmt.Errorf("Failed write data to cache-file.") + return ErrorUnableToWriteCache } return nil @@ -53,19 +63,19 @@ func (c *Cache[T]) Get(name string) (*T, error) { rawFile, err := os.Open(filePath) if err != nil { - return nil, fmt.Errorf("Failed to read cache-file.") + return nil, ErrorUnableToOpenCacheFile } var result T bytes, err := io.ReadAll(rawFile) if err != nil { - return nil, fmt.Errorf("Failed to read data from cache-file.") + return nil, ErrorUnableToReadCacheFile } err = json.Unmarshal(bytes, &result) if err != nil { - return nil, fmt.Errorf("Failed to parse JSON from cache-file.") + return nil, ErrorUnableToUnmarshalCacheFile } return &result, nil @@ -80,7 +90,7 @@ func (c *Cache[T]) List() ([]Saved[T], error) { var result []Saved[T] filenames, err := list(c.Path) if err != nil { - return nil, fmt.Errorf("Unable to read from cache path") + return nil, ErrorUnableToReadCachePath } if len(filenames) == 0 { @@ -102,7 +112,7 @@ func (c *Cache[T]) List() ([]Saved[T], error) { func list(path string) ([]string, error) { dir, err := os.ReadDir(path) if err != nil { - return nil, fmt.Errorf("Unable to read from path") + return nil, ErrorUnableToReadCachePath } var filenames []string diff --git a/pkg/met/met.go b/pkg/met/met.go index ed9076a..02a03fa 100644 --- a/pkg/met/met.go +++ b/pkg/met/met.go @@ -3,6 +3,7 @@ package met import ( "encoding/json" + "errors" "fmt" "io" "net/http" @@ -13,10 +14,18 @@ type Met struct { siteName string } +var ( + ErrorMissingSiteName = errors.New("siteName must be defined") + ErrorMissingHeaderExpires = errors.New("missing header 'Expires'") + ErrorMissingHeaderLastModified = errors.New("missing header 'Last-Modified'") + ErrorParseExpires = errors.New("unable to parse 'Expires'") + ErrorParseLastModified = errors.New("unable to parse 'Last-Modified'") +) + // Returns valid Met client or error if empty siteName is provided func New(siteName string) (*Met, error) { if siteName == "" { - return nil, fmt.Errorf("`siteName` must be defined.") + return nil, ErrorMissingSiteName } return &Met{ @@ -60,19 +69,19 @@ func (m *Met) Forecast(lat, lon float64, alt *int) (*LocationForecastResult, err expiresRaw, ok := resp.Header["Expires"] if !ok { - return nil, fmt.Errorf("Unable to get 'Expires' header") + return nil, ErrorMissingHeaderExpires } expires, err := time.Parse(time.RFC1123, expiresRaw[0]) if err != nil { - return nil, fmt.Errorf("Unable to parse `expiresRaw`: %w", err) + return nil, errors.Join(ErrorParseExpires, err) } lastModifiedRaw, ok := resp.Header["Last-Modified"] if !ok { - return nil, fmt.Errorf("Unable to get 'Last-Modified' header") + return nil, ErrorMissingHeaderLastModified } lastModified, err := time.Parse(time.RFC1123, lastModifiedRaw[0]) if err != nil { - return nil, fmt.Errorf("Unable to parse `Last-Modified`: %w", err) + return nil, errors.Join(ErrorParseLastModified, err) } forecast := LocationForecast{} diff --git a/pkg/nominatim/nominatim.go b/pkg/nominatim/nominatim.go index 8fd126c..fb40a9c 100644 --- a/pkg/nominatim/nominatim.go +++ b/pkg/nominatim/nominatim.go @@ -2,6 +2,7 @@ package nominatim import ( "encoding/json" + "errors" "fmt" "io" "net/http" @@ -14,9 +15,13 @@ type Nominatim struct { siteName string } +var ( + ErrorMissingSiteName = errors.New("siteName must be defined") +) + func New(siteName string) (*Nominatim, error) { if siteName == "" { - return nil, fmt.Errorf("`siteName` must be defined.") + return nil, ErrorMissingSiteName } return &Nominatim{ @@ -94,7 +99,7 @@ func (n *Nominatim) Reverse(lat, lon float64) (*ReverseResult, error) { } if allFieldsNil(result) { - return nil, fmt.Errorf("No result") + return nil, fmt.Errorf("no result") } return &result, nil diff --git a/yr/yr.go b/yr/yr.go index 6e049fa..a4f6c86 100644 --- a/yr/yr.go +++ b/yr/yr.go @@ -165,7 +165,7 @@ func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) } if location == nil { - return nil, fmt.Errorf("Location name is not set") + return nil, fmt.Errorf("location name is not set") } ts := f.Properties.Timeseries