public void ReturnInternalIfPlayerJoinRequestNotFound()
        {
            // Setup the client such that it will claim there is no JoinRequest associated with one of the members of
            // the dequeued parties.
            _transaction
            .Setup(tx => tx.DequeueAsync(MatchmakingType, 1))
            .Returns(Task.FromResult <IEnumerable <string> >(new List <string> {
                _soloParty.Id
            }));

            _memoryStoreClient.Setup(client => client.GetAsync <PartyJoinRequest>(_soloParty.Id))
            .ReturnsAsync(new PartyJoinRequest(_soloParty, "", null));
            _memoryStoreClient.Setup(client => client.GetAsync <PlayerJoinRequest>(SoloPartyLeader))
            .ReturnsAsync((PlayerJoinRequest)null);

            // Verify that an Internal StatusCode was returned.
            var context = Util.CreateFakeCallContext();
            var request = new PopWaitingPartiesRequest {
                Type = MatchmakingType, NumParties = 1
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _service.PopWaitingParties(request, context));

            Assert.AreEqual(StatusCode.Internal, exception.StatusCode);
            Assert.AreEqual($"could not find JoinRequest for {SoloPartyLeader}", exception.Status.Detail);
        }
Пример #2
0
        public override async Task <PopWaitingPartiesResponse> PopWaitingParties(PopWaitingPartiesRequest request,
                                                                                 ServerCallContext context)
        {
            Reporter.GetWaitingPartiesInc(request.NumParties);
            if (request.NumParties == 0)
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, "must request at least one party"));
            }

            using (var memClient = _matchmakingMemoryStoreClientManager.GetClient())
            {
                try
                {
                    Task <IEnumerable <string> > dequeuedPartyIds;
                    using (var tx = memClient.CreateTransaction())
                    {
                        dequeuedPartyIds = tx.DequeueAsync(request.Type, request.NumParties);
                    }

                    dequeuedPartyIds.Wait();

                    // TODO investigate best approach to handling this error (leave as null, log warning, ignore?)
                    IEnumerable <PartyJoinRequest> partyJoinRequests;
                    try
                    {
                        partyJoinRequests = dequeuedPartyIds.Result
                                            .Select(async id =>
                                                    await memClient.GetAsync <PartyJoinRequest>(id) ?? throw new EntryNotFoundException(id))
                                            .Select(t => t.Result)
                                            .ToList();
                    }
                    catch (AggregateException ex)
                    {
                        throw ex.InnerException;
                    }

                    var playerJoinRequestsToUpdate = new List <PlayerJoinRequest>();
                    foreach (var partyJoinRequest in partyJoinRequests)
                    {
                        foreach (var(memberId, _) in partyJoinRequest.Party.MemberIdToPit)
                        {
                            var playerJoinRequest = await memClient.GetAsync <PlayerJoinRequest>(memberId) ??
                                                    throw new EntryNotFoundException(memberId);

                            playerJoinRequest.State = MatchState.Matching;
                            playerJoinRequestsToUpdate.Add(playerJoinRequest);
                        }
                    }

                    using (var tx = memClient.CreateTransaction())
                    {
                        tx.UpdateAll(playerJoinRequestsToUpdate);
                    }

                    var response = new PopWaitingPartiesResponse();
                    foreach (var partyJoinRequest in partyJoinRequests)
                    {
                        response.Parties.Add(ConvertToProto(partyJoinRequest));
                    }

                    return(response);
                }
                catch (EntryNotFoundException ex)
                {
                    // TODO: maybe add metrics for this.
                    throw new RpcException(new Status(StatusCode.Internal, $"could not find JoinRequest for {ex.Id}"));
                }
                catch (InsufficientEntriesException)
                {
                    Reporter.InsufficientWaitingPartiesInc(request.NumParties);
                    throw new RpcException(new Status(StatusCode.ResourceExhausted,
                                                      "requested number of parties players could not be met"));
                }
                catch (TransactionAbortedException)
                {
                    throw new RpcException(new Status(StatusCode.Unavailable,
                                                      "dequeue aborted due to concurrent modification; safe to retry"));
                }
            }
        }