Public Access
fix(library): sync again after a Steam ID change and keep library on empty result
An empty Steam answer (error, private profile, wrong ID) was stored as OK and soft-deleted the whole library. It is now FAILED, keeps the library and is retried after 15 minutes (app.library.failed-retry-minutes). The automatic sync now also runs when the Steam ID in the token differs from the stored one, and removes the games of the previous Steam account.
This commit is contained in:
1 parent
342ce1bea1
commit
b29cff76c8
4 files changed
+221
-6
No files matched your search
@@ -27,19 +27,22 @@ public class LibrarySyncService {
|
||||
@Value("${app.library.running-stale-minutes:5}")
|
||||
private long runningStaleMinutes;
|
||||
|
||||
@Value("${app.library.failed-retry-minutes:15}")
|
||||
private long failedRetryMinutes;
|
||||
|
||||
/**
|
||||
* Trigger sync only if data is older than TTL. Cheap gate check on caller thread,
|
||||
* actual sync runs async via worker.
|
||||
* Trigger sync only if data is older than TTL or was synced for another Steam ID.
|
||||
* Cheap gate check on caller thread, actual sync runs async via worker.
|
||||
*/
|
||||
public void syncIfStale(Long userId, String steamId) {
|
||||
UserSteamSync sync = userSteamSyncRepository.findById(userId).orElse(null);
|
||||
if (sync != null && !isStale(sync)) {
|
||||
return;
|
||||
}
|
||||
if (sync != null && isAlreadyRunning(sync)) {
|
||||
log.debug("Sync already running for user {}", userId);
|
||||
return;
|
||||
}
|
||||
if (sync != null && steamId.equals(sync.getSteamId()) && !isStale(sync)) {
|
||||
return;
|
||||
}
|
||||
worker.runSync(userId, steamId);
|
||||
}
|
||||
|
||||
@@ -62,7 +65,10 @@ public class LibrarySyncService {
|
||||
|
||||
private boolean isStale(UserSteamSync sync) {
|
||||
if (sync.getLastSyncedAt() == null) return true;
|
||||
return sync.getLastSyncedAt().isBefore(Instant.now().minus(Duration.ofHours(syncTtlHours)));
|
||||
Duration maxAge = sync.getLastSyncStatus() == UserSteamSync.Status.FAILED
|
||||
? Duration.ofMinutes(failedRetryMinutes)
|
||||
: Duration.ofHours(syncTtlHours);
|
||||
return sync.getLastSyncedAt().isBefore(Instant.now().minus(maxAge));
|
||||
}
|
||||
|
||||
private boolean isAlreadyRunning(UserSteamSync sync) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package core_service.modules.library.service;
|
||||
import core_service.modules.library.domain.SteamGame;
|
||||
import core_service.modules.library.domain.UserGame;
|
||||
import core_service.modules.library.domain.UserGameId;
|
||||
import core_service.modules.library.domain.UserSteamSync;
|
||||
import core_service.modules.library.repo.SteamGameRepository;
|
||||
import core_service.modules.library.repo.UserGameRepository;
|
||||
import core_service.modules.library.repo.UserSteamSyncRepository;
|
||||
@@ -43,6 +44,9 @@ public class LibrarySyncWorker {
|
||||
@Transactional
|
||||
public void runSync(Long userId, String steamId) {
|
||||
Instant runningStaleBefore = Instant.now().minus(Duration.ofMinutes(runningStaleMinutes));
|
||||
String previousSteamId = userSteamSyncRepository.findById(userId)
|
||||
.map(UserSteamSync::getSteamId)
|
||||
.orElse(null);
|
||||
int claimed = userSteamSyncRepository.tryClaimRun(userId, steamId, runningStaleBefore);
|
||||
if (claimed == 0) {
|
||||
log.info("Sync skipped for user {} — another run already in flight", userId);
|
||||
@@ -52,8 +56,17 @@ public class LibrarySyncWorker {
|
||||
Instant syncStartedAt = Instant.now();
|
||||
Status finalStatus = Status.FAILED;
|
||||
try {
|
||||
if (previousSteamId != null && !previousSteamId.equals(steamId)) {
|
||||
// The old games belong to the previous Steam account. The upserts below restore the games this account also owns.
|
||||
userGameRepository.softDeleteMissingSince(userId, syncStartedAt, Instant.now());
|
||||
}
|
||||
List<SteamOwnedGamesResponse.Game> games = steamApiService.getOwnedGames(steamId);
|
||||
log.info("Sync user={} fetched {} games from Steam", userId, games.size());
|
||||
if (games.isEmpty()) {
|
||||
// Steam errors and a private "Game details" setting also end here. A soft-delete would wipe the library.
|
||||
log.warn("Sync user={} got no games for SteamID {}", userId, steamId);
|
||||
return;
|
||||
}
|
||||
|
||||
for (SteamOwnedGamesResponse.Game g : games) {
|
||||
if (g.appid() == null) continue;
|
||||
|
||||
Reference in new issue
Block a user