Skip to content

feat: add download quota limit per provider#62

Merged
javi11 merged 1 commit intomainfrom
feat/download-quota-limit-per-provider
Apr 11, 2026
Merged

feat: add download quota limit per provider#62
javi11 merged 1 commit intomainfrom
feat/download-quota-limit-per-provider

Conversation

@javi11
Copy link
Copy Markdown
Owner

@javi11 javi11 commented Apr 11, 2026

Summary

  • Adds QuotaBytes int64 and QuotaPeriod time.Duration fields to Provider, allowing a per-provider download cap with optional auto-reset (e.g. 100 GB/month)
  • When a provider's quota is reached it is skipped in dispatch (weight 0 in round-robin, skipped in FIFO) and hard-guarded in the main/backup provider loops
  • All providers over quota → ErrQuotaExceeded returned to caller
  • Quota state exposed in ProviderStats via Client.Stats(): QuotaBytes, QuotaUsed, QuotaResetAt, QuotaExceeded

Performance

Hot-path overhead when quota is not exceeded: one atomic.Bool load (~1 ns). time.Now() is only called after the quota flag is set (i.e. when a provider has actually run out). See PR description for full analysis.

Test plan

  • TestProviderGroup_isQuotaExceeded_UnlimitedQuotaBytes=0 always returns false
  • TestProviderGroup_isQuotaExceeded_NotYetHit — fast path before threshold
  • TestProviderGroup_isQuotaExceeded_FlagSet_NoReset — lifetime cap never resets
  • TestProviderGroup_isQuotaExceeded_PeriodElapsed_Resets — quota resets after period
  • TestProviderGroup_isQuotaExceeded_PeriodNotYetElapsed — stays exceeded before period ends
  • TestProviderStats_QuotaAccounting — byte accounting sets the flag correctly
  • TestClient_Stats_QuotaFieldsStats() exposes quota fields with correct values
  • TestClient_QuotaExceeded_FallsThrough — request falls through to second provider when first is exceeded
  • TestClient_AllQuotaExceeded_ReturnsErrorErrQuotaExceeded when all providers exceeded
  • make check (lint + race test suite) passes

Adds QuotaBytes and QuotaPeriod fields to Provider, allowing operators
to cap the total bytes downloaded from each provider per rolling window
(e.g. 100 GB/month). When a provider's quota is reached it is skipped
in dispatch — both during selection (weight 0 in round-robin, skipped
in FIFO) and as a hard guard in the main/backup provider loops. If all
providers are over quota, ErrQuotaExceeded is returned.

The hot-path overhead is a single atomic.Bool load (~1 ns) when quota
is not exceeded. time.Now() is only called once the cached flag is set,
i.e. when a provider has actually run out of quota. Quota usage resets
automatically after QuotaPeriod elapses (0 = lifetime cap, no reset).

Quota state (QuotaBytes, QuotaUsed, QuotaResetAt, QuotaExceeded) is
exposed via ProviderStats / Client.Stats().
@javi11 javi11 merged commit 35a332e into main Apr 11, 2026
1 check passed
@javi11 javi11 deleted the feat/download-quota-limit-per-provider branch April 11, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant