@@ -43,6 +43,7 @@ const (
4343 BatchLimitHeader = "x-cq-batch-limit"
4444 MinimumUpdateIntervalHeader = "x-cq-minimum-update-interval"
4545 MaximumUpdateIntervalHeader = "x-cq-maximum-update-interval"
46+ QueryIntervalHeader = "x-cq-query-interval"
4647)
4748
4849//go:generate mockgen -package=mocks -destination=../premium/mocks/marketplacemetering.go -source=usage.go AWSMarketplaceClientInterface
@@ -55,11 +56,19 @@ type TokenClient interface {
5556 GetTokenType () auth.TokenType
5657}
5758
59+ type CheckQuotaResult struct {
60+ // HasQuota is true if the quota has not been exceeded
61+ HasQuota bool
62+
63+ // SuggestedQueryInterval is the suggested interval to wait before querying the API again
64+ SuggestedQueryInterval time.Duration
65+ }
66+
5867type QuotaMonitor interface {
5968 // TeamName returns the team name
6069 TeamName () string
61- // HasQuota returns true if the quota has not been exceeded
62- HasQuota (context.Context ) (bool , error )
70+ // CheckQuota checks if the quota has been exceeded
71+ CheckQuota (context.Context ) (CheckQuotaResult , error )
6372}
6473
6574type UsageClient interface {
@@ -359,21 +368,34 @@ func (u *BatchUpdater) TeamName() string {
359368 return u .teamName
360369}
361370
362- func (u * BatchUpdater ) HasQuota (ctx context.Context ) (bool , error ) {
371+ func (u * BatchUpdater ) CheckQuota (ctx context.Context ) (CheckQuotaResult , error ) {
363372 if u .awsMarketplaceClient != nil {
364- return true , nil
373+ return CheckQuotaResult { HasQuota : true } , nil
365374 }
366375 u .logger .Debug ().Str ("url" , u .url ).Str ("team" , u .teamName ).Str ("pluginTeam" , u .pluginMeta .Team ).Str ("pluginKind" , string (u .pluginMeta .Kind )).Str ("pluginName" , u .pluginMeta .Name ).Msg ("checking quota" )
367376 usage , err := u .apiClient .GetTeamPluginUsageWithResponse (ctx , u .teamName , u .pluginMeta .Team , u .pluginMeta .Kind , u .pluginMeta .Name )
368377 if err != nil {
369- return false , fmt .Errorf ("failed to get usage: %w" , err )
378+ return CheckQuotaResult { HasQuota : false } , fmt .Errorf ("failed to get usage: %w" , err )
370379 }
371380 if usage .StatusCode () != http .StatusOK {
372- return false , fmt .Errorf ("failed to get usage: %s" , usage .Status ())
381+ return CheckQuotaResult { HasQuota : false } , fmt .Errorf ("failed to get usage: %s" , usage .Status ())
373382 }
374383
375- hasQuota := usage .JSON200 .RemainingRows == nil || * usage .JSON200 .RemainingRows > 0
376- return hasQuota , nil
384+ res := CheckQuotaResult {
385+ HasQuota : usage .JSON200 .RemainingRows == nil || * usage .JSON200 .RemainingRows > 0 ,
386+ }
387+ if usage .HTTPResponse == nil {
388+ return res , nil
389+ }
390+ if headerValue := usage .HTTPResponse .Header .Get (QueryIntervalHeader ); headerValue != "" {
391+ interval , err := strconv .ParseUint (headerValue , 10 , 32 )
392+ if interval > 0 {
393+ res .SuggestedQueryInterval = time .Duration (interval ) * time .Second
394+ } else {
395+ u .logger .Warn ().Err (err ).Str (QueryIntervalHeader , headerValue ).Msg ("failed to parse query interval" )
396+ }
397+ }
398+ return res , nil
377399}
378400
379401func (u * BatchUpdater ) Close () error {
@@ -700,8 +722,8 @@ func (n *NoOpUsageClient) TeamName() string {
700722 return n .TeamNameValue
701723}
702724
703- func (NoOpUsageClient ) HasQuota (_ context.Context ) (bool , error ) {
704- return true , nil
725+ func (NoOpUsageClient ) CheckQuota (_ context.Context ) (CheckQuotaResult , error ) {
726+ return CheckQuotaResult { HasQuota : true } , nil
705727}
706728
707729func (NoOpUsageClient ) Increase (_ uint32 ) error {
0 commit comments