package diyanetprovider import ( "context" "errors" "fmt" "time" "prayertimes/pkg/prayer" ) type APIProvider interface { Get(ctx context.Context, locationID string) ([]prayer.Times, error) GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error) } type FallbackProvider interface { GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error) } type Provider struct { api APIProvider fallback FallbackProvider timeout time.Duration } func New(api APIProvider, fallback FallbackProvider) Provider { return Provider{ api: api, fallback: fallback, timeout: 2 * time.Second, } } var ErrEmptyTimes = errors.New("diyanet did not return any prayer times") func (p Provider) Get(ctx context.Context, locationID string) ([]prayer.Times, error) { ctxWithTimeout, cancel := context.WithTimeout(ctx, p.timeout) defer cancel() times, err := p.api.Get(ctxWithTimeout, locationID) if err != nil { return nil, fmt.Errorf("failed to get prayer times from api provider: %w", err) } if len(times) == 0 { return nil, ErrEmptyTimes } return times, nil } func (p Provider) GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error) { ctxWithTimeout, cancel := context.WithTimeout(ctx, p.timeout) defer cancel() times, err := p.api.GetByCoords(ctxWithTimeout, coords) if err == nil && len(times) > 0 { return times, nil } times, err = p.fallback.GetByCoords(ctx, coords) if err != nil { return nil, fmt.Errorf("failed to get prayer times from fallback provider: %w", err) } if len(times) == 0 { return nil, fmt.Errorf("fallback provider did not return any prayer times") } return times, nil }