Wie kann ich von einem DelegatingHandler auf eine langlebige Einheit zugreifen?
Posted: 16 Feb 2025, 11:46
Ich habe eine dauerhafte Orchestrierung, in der ich die Anforderungen an eine externe API bewerten muss. Es gibt eine Reihe von Aufgaben im Orchestrator, die eine "DownloadData" -Funktion mit unterschiedlichen Parametern aufrufen, aber ich konnte nicht herausfinden Ich dachte, ich würde versuchen, eine langlebige Entität zu verwenden, um die verbleibenden Anrufe innerhalb eines bestimmten Zeitrahmens zu verfolgen. Begrenzung über die langlebige Entität stürzt jedoch die App ab, da sie den DurabletaskClient nicht über DI festlegen kann, und ich weiß nicht, wie man dies behebt.
Wie kann man den DurabletaskClient richtig registrieren und auf die Entität aus dem DelegatingHandler zugreifen?
Code: Select all
public class AuthenticationHandler : DelegatingHandler
{
private readonly IKeyVaultService _keyVaultService;
private readonly ILogger _logger;
private readonly DurableTaskClient _durableClient;
public AuthenticationHandler(IKeyVaultService keyVaultService, ILogger logger, DurableTaskClient durableClient)
{
_keyVaultService = keyVaultService ?? throw new ArgumentNullException(nameof(keyVaultService));
_logger = logger;
_durableClient = durableClient;
}
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string token = await _keyVaultService.GetAccessTokenAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var entityId = new EntityInstanceId(nameof(RateLimiterEntity), "RateLimiter");
EntityMetadata? entity = await _durableClient.Entities.GetEntityAsync(entityId, cancellation: cancellationToken);
_logger.LogInformation("Remaining requests: {rem}", entity.State.RemainingRequests.ToString());
if (entity != null && entity.State.RemainingRequests TimeSpan.Zero)
{
_logger.LogWarning("Rate limit reached. Delaying for {Delay} seconds", delay.TotalSeconds);
await Task.Delay(delay, cancellationToken);
}
await _durableClient.Entities.SignalEntityAsync(entityId, nameof(RateLimiterEntity.Reset), cancellationToken);
}
await _durableClient.Entities.SignalEntityAsync(entityId, nameof(RateLimiterEntity.Decrement), cancellationToken);
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
< /code>
Hier ist die langlebige Entität (isoliert, .NET 8): < /p>
[DurableTask(nameof(RateLimiterEntity))]
public class RateLimiterEntity
{
public int RemainingRequests { get; set; } = 100;
public DateTime ResetTime { get; set; } = DateTime.UtcNow.AddSeconds(60);
public void Reset()
{
RemainingRequests = 100;
ResetTime = DateTime.UtcNow.AddSeconds(60);
}
public void Decrement()
{
RemainingRequests--;
}
[Function(nameof(RateLimiterEntity))]
public static Task Run([EntityTrigger] TaskEntityDispatcher dispatcher)
=> dispatcher.DispatchAsync();
}