Merge branch 'dev' into V6

This commit is contained in:
Jordan Dominion
2023-11-07 08:26:38 -05:00
8 changed files with 84 additions and 8 deletions
+6 -1
View File
@@ -372,13 +372,15 @@ namespace Tgstation.Server.Client
retryPolicy ??= new InfiniteThirtySecondMaxRetryPolicy();
var wrappedPolicy = new ApiClientTokenRefreshRetryPolicy(this, retryPolicy);
HubConnection? hubConnection = null;
var hubConnectionBuilder = new HubConnectionBuilder()
.AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings = SerializerSettings;
})
.WithAutomaticReconnect(retryPolicy)
.WithAutomaticReconnect(wrappedPolicy)
.WithUrl(
new Uri(Url, Routes.JobsHub),
HttpTransportType.ServerSentEvents,
@@ -480,6 +482,9 @@ namespace Tgstation.Server.Client
if (content == null && (method == HttpMethod.Post || method == HttpMethod.Put))
throw new InvalidOperationException("content cannot be null for POST or PUT!");
if (disposed)
throw new ObjectDisposedException(nameof(ApiClient));
HttpResponseMessage response;
var fullUri = new Uri(Url, route);
var serializerSettings = SerializerSettings;
@@ -0,0 +1,61 @@
using System;
using System.Threading;
using Microsoft.AspNetCore.SignalR.Client;
namespace Tgstation.Server.Client
{
/// <summary>
/// A <see cref="IRetryPolicy"/> that attempts to refresh a given <see cref="apiClient"/>'s token on the first disconnect.
/// </summary>
sealed class ApiClientTokenRefreshRetryPolicy : IRetryPolicy
{
/// <summary>
/// The backing <see cref="ApiClient"/>.
/// </summary>
readonly ApiClient apiClient;
/// <summary>
/// The wrapped <see cref="IRetryPolicy"/>.
/// </summary>
readonly IRetryPolicy wrappedPolicy;
/// <summary>
/// Initializes a new instance of the <see cref="ApiClientTokenRefreshRetryPolicy"/> class.
/// </summary>
/// <param name="apiClient">The value of <see cref="apiClient"/>.</param>
/// <param name="wrappedPolicy">The value of <see cref="wrappedPolicy"/>.</param>
public ApiClientTokenRefreshRetryPolicy(ApiClient apiClient, IRetryPolicy wrappedPolicy)
{
this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
this.wrappedPolicy = wrappedPolicy ?? throw new ArgumentNullException(nameof(wrappedPolicy));
}
/// <inheritdoc />
public TimeSpan? NextRetryDelay(RetryContext retryContext)
{
if (retryContext == null)
throw new ArgumentNullException(nameof(retryContext));
if (retryContext.PreviousRetryCount == 0)
AttemptTokenRefresh();
return wrappedPolicy.NextRetryDelay(retryContext);
}
/// <summary>
/// Attempt to refresh the <see cref="apiClient"/>s token asynchronously.
/// </summary>
async void AttemptTokenRefresh()
{
try
{
await apiClient.RefreshToken(CancellationToken.None);
}
catch
{
// intentionally ignored
}
}
}
}