/// <summary> /// Loads data about the specified IP address, and pushes the resulting data to /// the specified SignalR hub client. /// </summary> /// <param name="rawIp">IP address to load data for</param> /// <param name="client">SignalR client</param> /// <param name="cancellationToken">Cancellation token for if the request is cancelled</param> /// <returns>A task that resolves when all data lookups have completed</returns> public async Task LoadDataAsync(string?rawIp, IToolsHub client, CancellationToken cancellationToken) { if (rawIp != null) { var ip = IPAddress.Parse(rawIp); await LoadDataAsync(ip, async data => await client.IpDataLoaded(rawIp, data), cancellationToken); } }
protected override async Task ProcessResponseAsync( string workerId, ChannelWriter <WorkerResponse <TracerouteResponse> > writer, TracerouteResponse response, IToolsHub client, CancellationToken cancellationToken ) { await base.ProcessResponseAsync(workerId, writer, response, client, cancellationToken); await _ipData.LoadDataAsync(response.Reply?.Ip, client, cancellationToken); }
protected virtual async Task ProcessResponseAsync( string workerId, ChannelWriter <WorkerResponse <TResponse> > writer, TResponse response, IToolsHub client, CancellationToken cancellationToken ) { await writer.WriteAsync(new WorkerResponse <TResponse> { Response = response, WorkerId = workerId, }, cancellationToken).ConfigureAwait(false); }
public ChannelReader <WorkerResponse <TResponse> > Run( TRequest request, IToolsHub client, ImmutableHashSet <string>?workerIds, CancellationToken cancellationToken ) { var channel = Channel.CreateUnbounded <WorkerResponse <TResponse> >(new UnboundedChannelOptions { SingleReader = true, SingleWriter = false, }); _ = RunAsync(request, channel.Writer, client, workerIds, cancellationToken); return(channel.Reader); }
private async Task RunWorkerAsync( string workerId, TRequest request, DnsToolsWorker.DnsToolsWorkerClient client, ChannelWriter <WorkerResponse <TResponse> > writer, IToolsHub hub, CancellationToken cancellationToken ) { try { if (_workerProvider.GetStatus(workerId) != WorkerStatus.Available) { throw new WorkerUnavailableException(); } var call = CreateRequest(client, request, cancellationToken); var responseStream = call.ResponseStream.ReadAllAsync(cancellationToken); var responseTasks = new List <Task>(); await foreach (var response in responseStream.WithCancellation(cancellationToken)) { responseTasks.Add(ProcessResponseAsync(workerId, writer, response, hub, cancellationToken)); } responseTasks.Add(WorkerCompletedAsync(workerId, writer, cancellationToken)); await Task.WhenAll(responseTasks); } catch (Exception ex) { var message = ex.Message; if (ex is RpcException rpcEx && rpcEx.StatusCode == StatusCode.Cancelled) { message = "Could not connect to this worker :("; } await writer.WriteAsync(new WorkerResponse <TResponse> { Response = new TResponse { Error = new Error { Message = message, }, }, WorkerId = workerId, }, cancellationToken).ConfigureAwait(false); } }
private async Task RunAsync( TRequest request, ChannelWriter <WorkerResponse <TResponse> > writer, IToolsHub client, ImmutableHashSet <string>?workerIds, CancellationToken cancellationToken ) { try { var clients = workerIds == null ? _workerProvider.CreateAllClients() : _workerProvider.CreateClients(workerIds); var requests = clients.Select( kvp => RunWorkerAsync(kvp.Key, request, kvp.Value, writer, client, cancellationToken) ); await Task.WhenAll(requests).ConfigureAwait(false); } finally { writer.Complete(); } }