diff --git a/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index 5e8f7fe336..291bf1dce6 100644 --- a/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -48,7 +48,7 @@ public class EndpointConfiguration { private final ApplicationProperties applicationProperties; @Getter private Map endpointStatuses = new ConcurrentHashMap<>(); private Map> endpointGroups = new ConcurrentHashMap<>(); - private Set disabledGroups = new HashSet<>(); + private Set disabledGroups = ConcurrentHashMap.newKeySet(); private Map endpointDisableReasons = new ConcurrentHashMap<>(); private Map groupDisableReasons = new ConcurrentHashMap<>(); private Map> endpointAlternatives = new ConcurrentHashMap<>(); diff --git a/app/core/src/main/java/stirling/software/SPDF/service/WeeklyActiveUsersService.java b/app/core/src/main/java/stirling/software/SPDF/service/WeeklyActiveUsersService.java index 3b1ae1d048..23d8247218 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/WeeklyActiveUsersService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/WeeklyActiveUsersService.java @@ -4,7 +4,9 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; @@ -21,7 +23,7 @@ public class WeeklyActiveUsersService { private final Map activeBrowsers = new ConcurrentHashMap<>(); // Track total unique browsers seen (overall) - private long totalUniqueBrowsers = 0; + private final AtomicLong totalUniqueBrowsers = new AtomicLong(0); // Application start time private final Instant startTime = Instant.now(); @@ -36,12 +38,12 @@ public class WeeklyActiveUsersService { return; } - boolean isNewBrowser = !activeBrowsers.containsKey(browserId); - activeBrowsers.put(browserId, Instant.now()); + Instant now = Instant.now(); + Instant previous = activeBrowsers.put(browserId, now); - if (isNewBrowser) { - totalUniqueBrowsers++; - log.debug("New browser recorded: {} (Total: {})", browserId, totalUniqueBrowsers); + if (previous == null) { + long total = totalUniqueBrowsers.incrementAndGet(); + log.debug("New browser recorded: {} (Total: {})", browserId, total); } } @@ -61,7 +63,7 @@ public class WeeklyActiveUsersService { * @return Total unique browsers count */ public long getTotalUniqueBrowsers() { - return totalUniqueBrowsers; + return totalUniqueBrowsers.get(); } /** @@ -88,7 +90,8 @@ public class WeeklyActiveUsersService { activeBrowsers.entrySet().removeIf(entry -> entry.getValue().isBefore(sevenDaysAgo)); } - /** Manual cleanup trigger (can be called by scheduled task if needed) */ + /** Scheduled cleanup trigger running every hour */ + @Scheduled(fixedRate = 3600000) public void performCleanup() { int sizeBefore = activeBrowsers.size(); cleanupOldEntries(); diff --git a/app/saas/src/main/java/stirling/software/saas/service/RateLimitService.java b/app/saas/src/main/java/stirling/software/saas/service/RateLimitService.java index 775c5862ae..8a006a6934 100644 --- a/app/saas/src/main/java/stirling/software/saas/service/RateLimitService.java +++ b/app/saas/src/main/java/stirling/software/saas/service/RateLimitService.java @@ -113,19 +113,13 @@ public class RateLimitService { public void cleanupExpiredBuckets() { long now = System.currentTimeMillis(); - int hourlyRemoved = - (int) - hourlyLimits.entrySet().stream() - .filter(e -> e.getValue().getResetTime() < now) - .peek(e -> hourlyLimits.remove(e.getKey())) - .count(); + int hourlyBefore = hourlyLimits.size(); + hourlyLimits.entrySet().removeIf(e -> e.getValue().getResetTime() < now); + int hourlyRemoved = hourlyBefore - hourlyLimits.size(); - int dailyRemoved = - (int) - dailyLimits.entrySet().stream() - .filter(e -> e.getValue().getResetTime() < now) - .peek(e -> dailyLimits.remove(e.getKey())) - .count(); + int dailyBefore = dailyLimits.size(); + dailyLimits.entrySet().removeIf(e -> e.getValue().getResetTime() < now); + int dailyRemoved = dailyBefore - dailyLimits.size(); if (hourlyRemoved + dailyRemoved > 0) { log.debug(