Skip to content

Commit 3f1edfd

Browse files
authored
Merge pull request #248 from LalitDeore/quick-fix
Fix duplicate usage alert email issue
2 parents 5487ed9 + 40d3a97 commit 3f1edfd

File tree

1 file changed

+136
-64
lines changed

1 file changed

+136
-64
lines changed

stats.go

Lines changed: 136 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,37 @@ func handleDailyCacheUpdate(executionInfo *ExecutionInfo) *ExecutionInfo {
14461446
return executionInfo
14471447
}
14481448

1449+
func generateAlertCacheKey(orgId string, threshold interface{}, emailList []string) string {
1450+
sortedEmails := make([]string, len(emailList))
1451+
copy(sortedEmails, emailList)
1452+
sort.Strings(sortedEmails)
1453+
1454+
emailsStr := strings.Join(sortedEmails, ",")
1455+
thresholdStr := fmt.Sprintf("%v", threshold)
1456+
1457+
key := fmt.Sprintf("alert_cache_%s_%s_%s", orgId, thresholdStr, emailsStr)
1458+
1459+
key = strings.ReplaceAll(key, "@", "_at_")
1460+
key = strings.ReplaceAll(key, ".", "_dot_")
1461+
key = strings.ReplaceAll(key, " ", "_")
1462+
1463+
return key
1464+
}
1465+
1466+
func checkAndSetAlertCache(ctx context.Context, cacheKey string) bool {
1467+
_, err := GetCache(ctx, cacheKey)
1468+
if err == nil {
1469+
return false
1470+
}
1471+
1472+
err = SetCache(ctx, cacheKey, []byte("sent"), 60)
1473+
if err != nil {
1474+
log.Printf("[WARNING] Failed setting alert cache for key %s: %s", cacheKey, err)
1475+
}
1476+
1477+
return true
1478+
}
1479+
14491480
func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment uint) *ExecutionInfo {
14501481

14511482
appendCustom := false
@@ -1650,6 +1681,19 @@ func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment ui
16501681
firstAdmin = allAdmins[0]
16511682
}
16521683

1684+
if !ArrayContains(allAdmins, "[email protected]") {
1685+
allAdmins = append(allAdmins, "[email protected]")
1686+
}
1687+
1688+
if !ArrayContains(allAdmins, "[email protected]") {
1689+
allAdmins = append(allAdmins, "[email protected]")
1690+
}
1691+
1692+
cacheKey := generateAlertCacheKey(orgId, AlertThreshold.Count, allAdmins)
1693+
if !checkAndSetAlertCache(ctx, cacheKey) {
1694+
continue
1695+
}
1696+
16531697
Subject := fmt.Sprintf("[Shuffle]: You've reached the app-runs threshold limit for your account %s", firstAdmin)
16541698

16551699
AppRunsPercentage := float64(totalAppExecutions) / float64(org.SyncFeatures.AppExecutions.Limit) * 100
@@ -1663,14 +1707,6 @@ func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment ui
16631707
"admin_email": firstAdmin,
16641708
}
16651709

1666-
if !ArrayContains(allAdmins, "[email protected]") {
1667-
allAdmins = append(allAdmins, "[email protected]")
1668-
}
1669-
1670-
if !ArrayContains(allAdmins, "[email protected]") {
1671-
allAdmins = append(allAdmins, "[email protected]")
1672-
}
1673-
16741710
err = sendMailSendgridV2(
16751711
[]string{"[email protected]"},
16761712
Subject,
@@ -1709,25 +1745,6 @@ func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment ui
17091745
// hard limit aleart
17101746
if org.Billing.AppRunsHardLimit > 0 && orgStatistics.MonthlyAppExecutions > org.Billing.AppRunsHardLimit {
17111747
// send alert to all admin in the orgs
1712-
subject := fmt.Sprintf("App Runs Hard Limit Exceeded for Org %s (%s)", org.Name, org.Id)
1713-
message := fmt.Sprintf(
1714-
`Dear Team,
1715-
1716-
Your organization <strong>%s</strong> (ID: %s) has exceeded the monthly app runs hard limit of <strong>%d</strong> runs.
1717-
1718-
<strong>Current usage:</strong> %d app runs.
1719-
1720-
As a result, all workflows have been temporarily blocked until the start of the next billing cycle.
1721-
To increase your organization's hard limit, please visit the admin panel of the parent organization.
1722-
If you have any questions, feel free to reach out to us at <a href="mailto:[email protected]">[email protected]</a>.
1723-
1724-
Note: This is an automated message sent by Shuffle to notify you about the exceeded app runs hard limit.
1725-
1726-
Best regards,
1727-
The Shuffler Team`,
1728-
org.Name, org.Id, org.Billing.AppRunsHardLimit, orgStatistics.MonthlyAppExecutions,
1729-
)
1730-
17311748
admins := []string{}
17321749

17331750
for _, user := range org.Users {
@@ -1736,9 +1753,33 @@ func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment ui
17361753
}
17371754
}
17381755

1739-
err = sendMailSendgrid(admins, subject, message, false, []string{})
1740-
if err != nil {
1741-
log.Printf("[ERROR] Failed sending alert email to admins of org %s (%s): %s", org.Name, org.Id, err)
1756+
cacheKey := generateAlertCacheKey(orgId, "hard_limit", admins)
1757+
if !checkAndSetAlertCache(ctx, cacheKey) {
1758+
log.Printf("[DEBUG] Skipping duplicate hard limit alert for org %s - alert sent within last minute", orgId)
1759+
} else {
1760+
subject := fmt.Sprintf("App Runs Hard Limit Exceeded for Org %s (%s)", org.Name, org.Id)
1761+
message := fmt.Sprintf(
1762+
`Dear Team,
1763+
1764+
Your organization <strong>%s</strong> (ID: %s) has exceeded the monthly app runs hard limit of <strong>%d</strong> runs.
1765+
1766+
<strong>Current usage:</strong> %d app runs.
1767+
1768+
As a result, all workflows have been temporarily blocked until the start of the next billing cycle.
1769+
To increase your organization's hard limit, please visit the admin panel of the parent organization.
1770+
If you have any questions, feel free to reach out to us at <a href="mailto:[email protected]">[email protected]</a>.
1771+
1772+
Note: This is an automated message sent by Shuffle to notify you about the exceeded app runs hard limit.
1773+
1774+
Best regards,
1775+
The Shuffler Team`,
1776+
org.Name, org.Id, org.Billing.AppRunsHardLimit, orgStatistics.MonthlyAppExecutions,
1777+
)
1778+
1779+
err = sendMailSendgrid(admins, subject, message, false, []string{})
1780+
if err != nil {
1781+
log.Printf("[ERROR] Failed sending alert email to admins of org %s (%s): %s", org.Name, org.Id, err)
1782+
}
17421783
}
17431784
}
17441785

@@ -1835,56 +1876,87 @@ func HandleIncrement(dataType string, orgStatistics *ExecutionInfo, increment ui
18351876
Subject = fmt.Sprintf("[Shuffle] %s: You've reached the app-runs threshold limit for your account %s", leadInfo, firstAdmin)
18361877
}
18371878

1838-
totalAppExecutions := validationOrgStatistics.MonthlyAppExecutions + validationOrgStatistics.MonthlyChildAppExecutions
1839-
AppRunsPercentage := float64(totalAppExecutions) / float64(validationOrg.SyncFeatures.AppExecutions.Limit) * 100
1840-
1841-
substitutions := map[string]interface{}{
1842-
"app_runs_usage": totalAppExecutions,
1843-
"app_runs_limit": validationOrg.SyncFeatures.AppExecutions.Limit,
1844-
"app_runs_usage_percentage": int64(AppRunsPercentage),
1845-
"org_name": validationOrg.Name,
1846-
"org_id": validationOrg.Id,
1847-
"admin_email": firstAdmin,
1879+
if len(leadInfo) == 0 && !ArrayContains(newEmailList, "[email protected]") {
1880+
newEmailList = append(newEmailList, "[email protected]")
18481881
}
18491882

1850-
if currentThreshold > 100 {
1851-
substitutions["lead_info"] = leadInfo
1883+
if len(leadInfo) == 0 && !ArrayContains(newEmailList, "[email protected]") {
1884+
newEmailList = append(newEmailList, "[email protected]")
18521885
}
18531886

1854-
err = sendMailSendgridV2(
1855-
[]string{"[email protected]"},
1856-
Subject,
1857-
substitutions,
1858-
false,
1859-
"d-3678d48b2b7144feb4b0b4cff7045016",
1860-
newEmailList,
1861-
)
1862-
1863-
if err != nil {
1864-
log.Printf("[ERROR] Failed sending alert mail for child org in increment (1): %s", err)
1887+
cacheKey := generateAlertCacheKey(validationOrg.Id, currentThreshold, newEmailList)
1888+
if !checkAndSetAlertCache(ctx, cacheKey) {
1889+
log.Printf("[DEBUG] Skipping duplicate percentage threshold alert for org %s, threshold %d%% - alert sent within last minute", validationOrg.Id, currentThreshold)
18651890
} else {
1866-
log.Printf("[DEBUG] Successfully sent alert mail for child org %s to parent org %s (1)", validationOrg.Name, validationOrg.Name)
1867-
}
1868-
1869-
if currentThreshold == 100 || currentThreshold == 50 {
1870-
if len(leadInfo) > 0 {
1871-
Subject = fmt.Sprintf("[Shuffle] %s: You've reached the app-runs threshold limit for your account %s", leadInfo, firstAdmin)
1891+
totalAppExecutions := validationOrgStatistics.MonthlyAppExecutions + validationOrgStatistics.MonthlyChildAppExecutions
1892+
AppRunsPercentage := float64(totalAppExecutions) / float64(validationOrg.SyncFeatures.AppExecutions.Limit) * 100
1893+
1894+
substitutions := map[string]interface{}{
1895+
"app_runs_usage": totalAppExecutions,
1896+
"app_runs_limit": validationOrg.SyncFeatures.AppExecutions.Limit,
1897+
"app_runs_usage_percentage": int64(AppRunsPercentage),
1898+
"org_name": validationOrg.Name,
1899+
"org_id": validationOrg.Id,
1900+
"admin_email": firstAdmin,
18721901
}
18731902

1874-
substitutions["lead_info"] = leadInfo
1903+
if currentThreshold > 100 {
1904+
substitutions["lead_info"] = leadInfo
1905+
}
18751906

18761907
err = sendMailSendgridV2(
1877-
1908+
[]string{"[email protected]"},
18781909
Subject,
18791910
substitutions,
18801911
false,
18811912
"d-3678d48b2b7144feb4b0b4cff7045016",
1882-
[]string{},
1913+
newEmailList,
18831914
)
1915+
18841916
if err != nil {
1885-
log.Printf("[ERROR] Failed sending alert mail for child org in increment (2): %s", err)
1917+
log.Printf("[ERROR] Failed sending alert mail for child org in increment (1): %s", err)
1918+
} else {
1919+
log.Printf("[DEBUG] Successfully sent alert mail for child org %s to parent org %s (1)", validationOrg.Name, validationOrg.Name)
1920+
}
1921+
}
1922+
1923+
if (currentThreshold == 100 || currentThreshold == 50) && len(leadInfo) > 0 {
1924+
secondEmailList := []string{"[email protected]", "[email protected]", "[email protected]"}
1925+
secondCacheKey := generateAlertCacheKey(validationOrg.Id, fmt.Sprintf("second_%d", currentThreshold), secondEmailList)
1926+
if !checkAndSetAlertCache(ctx, secondCacheKey) {
1927+
log.Printf("[DEBUG] Skipping duplicate second alert for org %s, threshold %d%% - alert sent within last minute", validationOrg.Id, currentThreshold)
18861928
} else {
1887-
log.Printf("[DEBUG] Successfully sent alert mail for child org %s to parent org %s (2)", validationOrg.Name, validationOrg.Name)
1929+
if len(leadInfo) > 0 {
1930+
Subject = fmt.Sprintf("[Shuffle] %s: You've reached the app-runs threshold limit for your account %s", leadInfo, firstAdmin)
1931+
}
1932+
1933+
totalAppExecutions := validationOrgStatistics.MonthlyAppExecutions + validationOrgStatistics.MonthlyChildAppExecutions
1934+
AppRunsPercentage := float64(totalAppExecutions) / float64(validationOrg.SyncFeatures.AppExecutions.Limit) * 100
1935+
1936+
substitutions := map[string]interface{}{
1937+
"app_runs_usage": totalAppExecutions,
1938+
"app_runs_limit": validationOrg.SyncFeatures.AppExecutions.Limit,
1939+
"app_runs_usage_percentage": int64(AppRunsPercentage),
1940+
"org_name": validationOrg.Name,
1941+
"org_id": validationOrg.Id,
1942+
"admin_email": firstAdmin,
1943+
"lead_info": leadInfo,
1944+
}
1945+
1946+
log.Printf("[DEBUG] Sending second alert mail for child org %s to parent org %s (2)", validationOrg.Name, validationOrg.Name)
1947+
err = sendMailSendgridV2(
1948+
1949+
Subject,
1950+
substitutions,
1951+
false,
1952+
"d-3678d48b2b7144feb4b0b4cff7045016",
1953+
[]string{},
1954+
)
1955+
if err != nil {
1956+
log.Printf("[ERROR] Failed sending alert mail for child org in increment (2): %s", err)
1957+
} else {
1958+
log.Printf("[DEBUG] Successfully sent alert mail for child org %s to parent org %s (2)", validationOrg.Name, validationOrg.Name)
1959+
}
18881960
}
18891961
}
18901962

0 commit comments

Comments
 (0)