Deactivate completed Orleans grains after TTL
CI / test (push) Successful in 1m27s Details

This commit is contained in:
MpakobecEx 2026-10-21 16:18:18 +05:00
parent f8f10dea35
commit f60805d27c
5 changed files with 33 additions and 5 deletions

View File

@ -127,18 +127,32 @@ public sealed class MatchGrainRegistry
public void Remove(string matchId) => _matches.TryRemove(matchId, out _);
public void RemoveExpired(DateTimeOffset now)
public async Task RemoveExpiredAsync(DateTimeOffset now)
{
var ttl = TimeSpan.FromSeconds(_options.CompletedMatchTtlSeconds);
foreach (var (matchId, match) in _matches)
{
var summary = match.Summary;
if (summary.IsFinished && summary.FinishedAt is { } finishedAt && now - finishedAt >= ttl)
if (!summary.IsFinished || summary.FinishedAt is not { } finishedAt || now - finishedAt < ttl)
continue;
if (!_matches.TryRemove(matchId, out _))
continue;
if (match is OrleansMatchAdapter adapter)
{
_matches.TryRemove(matchId, out _);
_logger.LogInformation("Match {MatchId} removed after completion.", matchId);
try
{
await adapter.DeactivateAsync();
}
catch (Exception exception)
{
_logger.LogDebug(exception, "Match {MatchId}: Orleans deactivation failed.", matchId);
}
}
_logger.LogInformation("Match {MatchId} removed after completion.", matchId);
}
}
}

View File

@ -42,7 +42,7 @@ public sealed class MatchTicker : BackgroundService
}
}
_registry.RemoveExpired(now);
await _registry.RemoveExpiredAsync(now);
}
}
}

View File

@ -31,6 +31,9 @@ public interface IMatchActor : IGrainWithStringKey
Task<MatchSummaryData> GetSummaryAsync();
Task<bool> HasPlayerAsync(string playerId);
/// <summary>Выгрузить завершённый матч из silo после TTL.</summary>
Task DeactivateAsync();
}
[GenerateSerializer]

View File

@ -146,6 +146,12 @@ public sealed class MatchActorGrain : Grain, IMatchActor
return match.HasPlayer(playerId);
}
public Task DeactivateAsync()
{
DeactivateOnIdle();
return Task.CompletedTask;
}
private async Task<MatchGrain> RequireAsync()
{
await EnsureInitializedAsync();

View File

@ -88,6 +88,11 @@ public sealed class OrleansMatchAdapter : IMatchGrain
await RefreshAsync();
}
public async Task DeactivateAsync()
{
await _actor.DeactivateAsync();
}
private async Task RefreshAsync()
{
try