Skip to content

Commit

Permalink
feat: Allow players to be tracked initially for idle tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
angelobreuer committed Mar 16, 2024
1 parent 72974d9 commit 988512f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Lavalink4NET.InactivityTracking.Trackers.Idle;

using System.Collections.Immutable;
using System.Diagnostics;
using Lavalink4NET.Events.Players;
using Lavalink4NET.Players;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -33,7 +34,9 @@ public ValueTask RunAsync(IInactivityTrackerContext trackerContext, Cancellation
trackerContext: trackerContext,
playerManager: _playerManager,
idleStates: _options.IdleStates,
timeout: _options.Timeout);
timeout: _options.Timeout,
initialTimeout: _options.InitialTimeout,
trackNewPlayers: _options.TrackNewPlayers);

return context.RunAsync(cancellationToken);
}
Expand All @@ -46,12 +49,16 @@ file sealed class IdleInactivityTrackerContext
private readonly IPlayerManager _playerManager;
private readonly ImmutableArray<PlayerState> _idleStates;
private readonly TimeSpan? _timeout;
private readonly TimeSpan? _initialTimeout;
private readonly bool _trackNewPlayers;

public IdleInactivityTrackerContext(
IInactivityTrackerContext trackerContext,
IPlayerManager playerManager,
ImmutableArray<PlayerState> idleStates,
TimeSpan? timeout)
TimeSpan? timeout,
TimeSpan? initialTimeout,
bool trackNewPlayers)
{
ArgumentNullException.ThrowIfNull(trackerContext);
ArgumentNullException.ThrowIfNull(playerManager);
Expand All @@ -61,6 +68,8 @@ public IdleInactivityTrackerContext(
_playerManager = playerManager;
_timeout = timeout;
_idleStates = idleStates;
_initialTimeout = initialTimeout;
_trackNewPlayers = trackNewPlayers;
}

public async ValueTask RunAsync(CancellationToken cancellationToken = default)
Expand All @@ -69,6 +78,11 @@ public async ValueTask RunAsync(CancellationToken cancellationToken = default)

_playerManager.PlayerStateChanged += PlayerStateChanged;

if (_trackNewPlayers)
{
_playerManager.PlayerCreated += PlayerCreated;
}

try
{
var taskCompletionSource = new TaskCompletionSource<object?>(
Expand All @@ -83,9 +97,26 @@ public async ValueTask RunAsync(CancellationToken cancellationToken = default)
finally
{
_playerManager.PlayerStateChanged -= PlayerStateChanged;

if (_trackNewPlayers)
{
_playerManager.PlayerCreated -= PlayerCreated;
}
}
}

private Task PlayerCreated(object sender, PlayerCreatedEventArgs eventArgs)
{
ArgumentNullException.ThrowIfNull(sender);
ArgumentNullException.ThrowIfNull(eventArgs);

Debug.Assert(_trackNewPlayers);

NotifyActivityStateChange(eventArgs.Player, eventArgs.Player.State, _initialTimeout ?? _timeout);

return Task.CompletedTask;
}

private Task PlayerStateChanged(object sender, PlayerStateChangedEventArgs eventArgs)
{
ArgumentNullException.ThrowIfNull(sender);
Expand All @@ -96,21 +127,26 @@ private Task PlayerStateChanged(object sender, PlayerStateChangedEventArgs event
return Task.CompletedTask; // ignore, player is destroyed
}

NotifyActivityStateChange(eventArgs.Player, eventArgs.State, _timeout);

return Task.CompletedTask;
}

private void NotifyActivityStateChange(ILavalinkPlayer player, PlayerState playerState, TimeSpan? timeout)
{
lock (_trackerContextSyncRoot)
{
using var scope = _trackerContext.CreateScope();
var isIdle = _idleStates.Contains(eventArgs.State);
var isIdle = _idleStates.Contains(playerState);

if (isIdle)
{
scope.MarkInactive(eventArgs.Player.GuildId, _timeout);
scope.MarkInactive(player.GuildId, timeout);
}
else
{
scope.MarkActive(eventArgs.Player.GuildId);
scope.MarkActive(player.GuildId);
}
}

return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,24 @@ public sealed record class IdleInactivityTrackerOptions

public TimeSpan? Timeout { get; set; }

/// <summary>
/// Gets or sets the states that are considered as idle.
/// </summary>
public ImmutableArray<PlayerState> IdleStates { get; set; } = IdleInactivityTrackerOptionsDefaults.DefaultIdleStates;

/// <summary>
/// Gets or sets the initial timeout for new players.
/// </summary>
/// <remarks>
/// If <see cref="InitialTimeout"/> is set, <see cref="InitialTimeout"/> will be used as the timeout for new players. Otherwise, <see cref="Timeout"/> will be used.
/// If <see cref="InitialTimeout"/> are <see cref="Timeout"/> are both <see langword="null"/>, the default timeout will be used.
/// </remarks>
public TimeSpan? InitialTimeout { get; set; }

/// <summary>
/// Gets or sets a value indicating whether new players should be considered as idle when their initial state is in <see cref="IdleStates"/>. Default is <see langword="true"/>.
/// </summary>
public bool TrackNewPlayers { get; set; } = true;
}

file static class IdleInactivityTrackerOptionsDefaults
Expand Down

0 comments on commit 988512f

Please sign in to comment.