package quotaresource
import (
streamconfig "lunar/engine/streams/config"
"lunar/toolkit-core/configuration"
"time"
)
// This function is used to convert the QuotaResourceData to a list of SingleQuotaResourceData
// Will help in processing the data to keep the original convention with minimal changes.
func (qc *QuotaResourceData) ToSingleQuotaResourceDataList() []*SingleQuotaResourceData {
singleQuotaResourceDataList := []*SingleQuotaResourceData{}
for _, quota := range qc.Quotas {
temporaryParentIDs := map[string]struct{}{}
temporaryParentIDs[quota.ID] = struct{}{}
singleData := &SingleQuotaResourceData{
Quota: quota,
InternalLimits: make([]*ChildQuotaConfig, 0),
}
for _, internalLimit := range qc.InternalLimits {
if _, found := temporaryParentIDs[internalLimit.ParentID]; !found {
continue
}
temporaryParentIDs[internalLimit.ID] = struct{}{}
singleData.InternalLimits = append(singleData.InternalLimits, internalLimit)
}
singleQuotaResourceDataList = append(singleQuotaResourceDataList, singleData)
}
return singleQuotaResourceDataList
}
func (q *QuotaMetaData) GetID() string {
return q.ID
}
func (q *QuotaMetaData) GetFilter() *streamconfig.Filter {
return q.Filter
}
func (q *QuotaMetaData) GetStrategy() *StrategyConfig {
return q.Strategy
}
func (mrd *MonthlyRenewalData) getMonthlyResetIn() (time.Time, error) {
loc, err := time.LoadLocation(mrd.Timezone)
if err != nil {
return time.Time{}, err
}
now := time.Now().In(loc)
nextReset := now.AddDate(0, 1, mrd.Day-1).
Add(time.Duration(mrd.Hour) * time.Hour).
Add(time.Duration(mrd.Minute) * time.Minute)
return nextReset, nil
}
// This function is used to assign the effective quota limit for a child quota based on its
// PercentageAllocation value. It will inherit and assign the quota strategy from the parent
// and will update the quota limit based on the percentage.
// Only applicable for FixedWindow and FixedWindowCustomCounter strategies at the moment.
func AssignQuotaLimitForPercentageAllocation(
childStrategyConfig *StrategyConfig,
parentStrategyConfig *StrategyConfig,
) error {
// We begin with keeping value of the allocation percentage
percentage := childStrategyConfig.AllocationPercentage
if percentage == 0 {
return nil
}
// Next, we prepare a copy of the parent strategy config which
// we could mutate without affecting the parent
parentCopy, err := configuration.YAMLBasedDeepCopy(parentStrategyConfig)
if err != nil {
return err
}
// Lastly, we replace in-place for the relevant strategy
// and update the quota limit based on the percentage
switch parentCopy.GetUsedStrategy() { //nolint: exhaustive
case FixedWindowStrategy:
childStrategyConfig.FixedWindow = parentCopy.FixedWindow
childStrategyConfig.AllocationPercentage = 0
updatedMax := (childStrategyConfig.FixedWindow.Max * percentage) / 100
childStrategyConfig.FixedWindow.Max = updatedMax
case FixedWindowCustomCounterStrategy:
childStrategyConfig.FixedWindowCustomCounter = parentCopy.FixedWindowCustomCounter
childStrategyConfig.AllocationPercentage = 0
updatedMax := (childStrategyConfig.FixedWindowCustomCounter.Max * percentage) / 100
childStrategyConfig.FixedWindowCustomCounter.Max = updatedMax
default:
}
return nil
}