internal async ValueTask <IObjectPrx?> FindObjectAsync(Identity id) { Task <IObjectPrx?>?task = null; LookupReply? replyServant; lock (_mutex) { if (!_objectReplies.TryGetValue(id, out replyServant)) { replyServant = new LookupReply(); _objectReplies.Add(id, replyServant); } else { task = replyServant.CompletionSource.Task; } } if (task == null) { task = InvokeAsync( async(lookup, lookupReply) => { try { await lookup.FindObjectByIdAsync(_domainId, id, lookupReply).ConfigureAwait(false); } catch (Exception ex) { throw new InvalidOperationException( $"failed to lookup object `{id}' with lookup proxy `{_lookup}'", ex); } }, replyServant); await task.ConfigureAwait(false); lock (_mutex) { _objectReplies.Remove(id); } } return(await task.ConfigureAwait(false)); }
internal async Task <IObjectPrx?> InvokeAsync(Func <ILookupPrx, ILookupReplyPrx, Task> find, LookupReply replyServant) { Identity requestId = _replyAdapter.AddWithUUID(replyServant, ILocatorRegistryPrx.Factory).Identity; Task <IObjectPrx?> replyTask = replyServant.CompletionSource.Task; try { for (int i = 0; i < _retryCount; ++i) { TimeSpan start = Time.Elapsed; int failureCount = 0; foreach ((ILookupPrx lookup, ILookupReplyPrx? reply) in _lookups) { ILookupReplyPrx?lookupReply = reply.Clone(requestId, ILookupReplyPrx.Factory); try { await find(lookup, lookupReply); } catch (Exception ex) { if (++failureCount == _lookups.Count) { _lookup.Communicator.Logger.Warning(ex.ToString()); replyServant.CompletionSource.SetResult(null); } } } Task?t = await Task.WhenAny(replyTask, Task.Delay(_timeout, replyServant.CancellationSource.Token)).ConfigureAwait(false); if (t == replyTask) { return(await replyTask.ConfigureAwait(false)); // We're done! } else if (t.IsCanceled) { // If the timeout was canceled we delay the completion of the request to give a chance to other // members of this replica group to reply return(await replyServant.WaitForReplicaGroupRepliesAsync(start, _latencyMultiplier)); } } replyServant.CompletionSource.SetResult(null); // Timeout return(await replyTask.ConfigureAwait(false)); } finally { _replyAdapter.Remove(requestId); } }