예제 #1
0
        private async Task <IEnumerable <Match> > GetMatchesPageAsync(string guid, int pageNumber, bool includeTreeInfo, Throttle throttle, ProgressData progressData)
        {
            var nameUnavailableCount = 0;
            var nameUnavailableMax   = 60;
            var retryCount           = 0;
            var retryMax             = 5;

            while (true)
            {
                try
                {
                    await throttle.WaitAsync();

                    using (var testsResponse = await _dnaHomeClient.GetAsync($"dna/secure/tests/{guid}/matches?filterBy=ALL&sortBy=RELATIONSHIP&rows={_matchesPerPage}&page={pageNumber}"))
                    {
                        testsResponse.EnsureSuccessStatusCode();
                        var matches = await testsResponse.Content.ReadAsAsync <Matches>();

                        var result = matches.MatchGroups.SelectMany(matchGroup => matchGroup.Matches);

                        // Sometimes Ancestry returns matches with partial data.
                        // If that happens, retry and hope to get full data the next time.
                        if (result.Any(match => match.Name == "name unavailable") && ++nameUnavailableCount < nameUnavailableMax)
                        {
                            await Task.Delay(3000);

                            continue;
                        }

                        throttle.Release();
                        progressData.Increment();
                        if (includeTreeInfo)
                        {
                            try
                            {
                                await GetLinkedTreesAsync(guid, result, throttle);
                            }
                            catch
                            {
                                // non-fatal if unable to download trees
                            }
                        }

                        progressData.Increment();
                        return(result);
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        throttle.Release();
                        throw;
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
            }
        }
        private async Task GetAdditionalInfoAsync(string guid, IEnumerable <Match> matches, Throttle throttle)
        {
            while (true)
            {
                await throttle.WaitAsync();

                var throttleReleased = false;

                try
                {
                    var matchesDictionary = matches.ToDictionary(match => match.TestGuid);
                    var url = $"/discoveryui-matchesservice/api/samples/{guid}/matchesv2/additionalInfo?ids=[{"%22" + string.Join("%22,%22", matchesDictionary.Keys) + "%22"}]&ancestors=true&tree=true";
                    using (var testsResponse = await _dnaHomeClient.GetAsync(url))
                    {
                        throttle.Release();
                        throttleReleased = true;

                        testsResponse.EnsureSuccessStatusCode();
                        var undeterminedCount = 0;
                        var additionalInfos   = await testsResponse.Content.ReadAsAsync <List <AdditionalInfo> >();

                        foreach (var additionalInfo in additionalInfos)
                        {
                            if (matchesDictionary.TryGetValue(additionalInfo.TestGuid, out var match))
                            {
                                match.TreeSize = additionalInfo.TreeSize ?? 0;
                                match.TreeType =
                                    additionalInfo.PrivateTree == true ? TreeType.Private   // might also be unlinked
                                    : additionalInfo.UnlinkedTree == true ? TreeType.Unlinked
                                    : additionalInfo.PublicTree == true && match.TreeSize > 0 ? TreeType.Public
                                    : additionalInfo.NoTrees == true ? TreeType.None
                                    : TreeType.Undetermined;
                                if (match.TreeType == TreeType.Undetermined)
                                {
                                    ++undeterminedCount;
                                }
                                match.HasCommonAncestors = additionalInfo.CommonAncestors ?? false;
                            }
                        }

                        return;
                    }
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    if (!throttleReleased)
                    {
                        throttle.Release();
                    }
                }
            }
        }
        public async Task AddTagAsync(string guid, string testGuid, int tagId, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url     = $"/discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}/tags/{tagId}";
                var request = new
                {
                    headers = new
                    {
                        normalizedNames = new { },
                        lazyUpdate      = (bool?)null,
                        lazyInit        = (bool?)null,
                        headers         = new { },
                    }
                };
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.PutAsJsonAsync(url, request))
                {
                    testsResponse.EnsureSuccessStatusCode();
                }
            }
            finally
            {
                throttle.Release();
            }
        }
        private async Task GetParentsAsync(string guid, IEnumerable <Match> matches, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url = $"/discoveryui-matchesservice/api/samples/{guid}/matchesv2/parents";
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync(url))
                {
                    testsResponse.EnsureSuccessStatusCode();
                    var parentsInfo = await testsResponse.Content.ReadAsAsync <ParentsInfo>();

                    if (!string.IsNullOrEmpty(parentsInfo.FatherSampleId) || !string.IsNullOrEmpty(parentsInfo.MotherSampleId))
                    {
                        foreach (var match in matches)
                        {
                            if (match.TestGuid == parentsInfo.FatherSampleId)
                            {
                                match.IsFather = true;
                            }
                            if (match.TestGuid == parentsInfo.MotherSampleId)
                            {
                                match.IsMother = true;
                            }
                        }
                    }
                }
            }
            finally
            {
                throttle.Release();
            }
        }
예제 #5
0
        private async Task <(IEnumerable <Match>, int)> GetMatchesInCommonPageAsync(string guid, string guidInCommon, int pageNumber, Throttle throttle)
        {
            if (guid == guidInCommon)
            {
                return(Enumerable.Empty <Match>(), 0);
            }

            var nameUnavailableCount = 0;
            var nameUnavailableMax   = 60;
            var retryCount           = 0;
            var retryMax             = 5;

            while (true)
            {
                await throttle.WaitAsync();

                try
                {
                    using (var testsResponse = await _dnaHomeClient.GetAsync($"dna/secure/tests/{guid}/matchesInCommon?filterBy=ALL&sortBy=RELATIONSHIP&page={pageNumber}&matchTestGuid={guidInCommon}"))
                    {
                        if (testsResponse.StatusCode == System.Net.HttpStatusCode.Gone)
                        {
                            return(Enumerable.Empty <Match>(), 0);
                        }
                        if (testsResponse.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable)
                        {
                            await Task.Delay(120000);

                            continue;
                        }
                        testsResponse.EnsureSuccessStatusCode();
                        var matches = await testsResponse.Content.ReadAsAsync <Matches>();

                        var matchesInCommon = matches.MatchGroups.SelectMany(matchGroup => matchGroup.Matches);

                        if (matchesInCommon.Any(match => match.Name == "name unavailable") && ++nameUnavailableCount < nameUnavailableMax)
                        {
                            await Task.Delay(3000);

                            continue;
                        }

                        return(matchesInCommon, matches.PageCount);
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        throw;
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    throttle.Release();
                }
            }
        }
예제 #6
0
        private async Task GetPublicTreeAsync(string guid, Match match, Throttle throttle, bool doThrow)
        {
            var retryCount = 0;
            var retryMax   = 5;

            while (true)
            {
                try
                {
                    await throttle.WaitAsync();

                    using (var testsResponse = await _dnaHomeClient.GetAsync($"dna/secure/tests/{guid}/matches/{match.TestGuid}/treeDetails"))
                    {
                        testsResponse.EnsureSuccessStatusCode();
                        var treeDetails = await testsResponse.Content.ReadAsAsync <TreeDetails>();

                        if (treeDetails.MatchTestHasTree)
                        {
                            match.TreeType = TreeType.Public;
                            match.TreeSize = treeDetails.MatchTreeNodeCount;
                        }
                        else if (treeDetails.PublicTreeInformationList?.Any(info => info.IsPublic) == true)
                        {
                            match.TreeType = TreeType.Unlinked;
                        }
                        else if (treeDetails.PublicTreeInformationList?.Any() == true && treeDetails.MatchTreeNodeCount > 0)
                        {
                            match.TreeType = TreeType.Private;
                        }
                        else
                        {
                            match.TreeType = TreeType.None;
                        }
                        return;
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        if (doThrow)
                        {
                            throw;
                        }
                        return;
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    throttle.Release();
                }
            }
        }
        private async Task <List <string> > GetCommonAncestorsAsync(string guid, string testGuid, Throttle throttle)
        {
            while (true)
            {
                await throttle.WaitAsync();

                var throttleReleased = false;

                try
                {
                    var url = $"/discoveryui-matchesservice/api/compare/{guid}/with/{testGuid}/commonancestors/";
                    using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync(url))
                    {
                        throttle.Release();
                        throttleReleased = true;

                        testsResponse.EnsureSuccessStatusCode();
                        var ancestorCouples = await testsResponse.Content.ReadAsAsync <Ancestors>();

                        var result = ancestorCouples.AncestorCouples.SelectMany(couple => new[] { couple.Father, couple.Mother })
                                     .Select(ancestor => ancestor?.PersonData?.DisplayName)
                                     .Where(name => !string.IsNullOrEmpty(name))
                                     .ToList();
                        return(result.Count > 0 ? result : null);
                    }
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    if (!throttleReleased)
                    {
                        throttle.Release();
                    }
                }
            }
        }
        public async Task UpdateNotesAsync(string guid, string testGuid, string note, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url = $"/discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}";
                using (var testsResponse = await _dnaHomeClient.PutAsJsonAsync(url, new { note }))
                {
                    testsResponse.EnsureSuccessStatusCode();
                }
            }
            finally
            {
                throttle.Release();
            }
        }
        public async Task DeleteTagAsync(string guid, string testGuid, int tagId, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url = $"/discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}/tags/{tagId}";
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.DeleteAsync(url))
                {
                    testsResponse.EnsureSuccessStatusCode();
                }
            }
            finally
            {
                throttle.Release();
            }
        }
        public async Task UpdateStarredAsync(string guid, string testGuid, bool starred, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url = $"/discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}";
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.PutAsJsonAsync(url, new { starred }))
                {
                    testsResponse.EnsureSuccessStatusCode();
                }
            }
            finally
            {
                throttle.Release();
            }
        }
        public async Task <Match> GetMatchAsync(string guid, string testGuid, Throttle throttle, ProgressData progressData)
        {
            await throttle.WaitAsync();

            try
            {
                using (var testsResponse = await _dnaHomeClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}/details"))
                {
                    return(testsResponse.IsSuccessStatusCode ? await testsResponse.Content.ReadAsAsync <Match>() : null);
                }
            }
            finally
            {
                progressData.Increment();
                throttle.Release();
            }
        }
        public async Task <List <Tag> > GetTagsAsync(string guid, Throttle throttle)
        {
            await throttle.WaitAsync();

            try
            {
                var url = $"/discoveryui-matchesservice/api/samples/{guid}/tags";
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync(url))
                {
                    testsResponse.EnsureSuccessStatusCode();
                    return(await testsResponse.Content.ReadAsAsync <List <Tag> >());
                }
            }
            finally
            {
                throttle.Release();
            }
        }
        public async Task <Match> GetMatchAsync(string guid, string testGuid, HashSet <int> tagIds, Throttle throttle, ProgressData progressData)
        {
            await throttle.WaitAsync();

            try
            {
                using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}/details"))
                {
                    if (!testsResponse.IsSuccessStatusCode)
                    {
                        return(null);
                    }

                    return(ConvertMatch(await testsResponse.Content.ReadAsAsync <MatchV2>(), tagIds));
                }
            }
            finally
            {
                progressData.Increment();
                throttle.Release();
            }
        }
        public async Task <Match> GetMatchAsync(string guid, string testGuid, HashSet <int> tagIds, Throttle throttle, ProgressData progressData)
        {
            var retryCount = 0;
            var retryMax   = 5;

            while (true)
            {
                await throttle.WaitAsync();

                try
                {
                    using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matches/{testGuid}/details"))
                    {
                        if (!testsResponse.IsSuccessStatusCode)
                        {
                            return(null);
                        }

                        return(ConvertMatch(await testsResponse.Content.ReadAsAsync <MatchV2>(), tagIds));
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        FileUtils.LogException(ex, true);
                        await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);

                        return(null);
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    progressData.Increment();
                    throttle.Release();
                }
            }
        }
예제 #15
0
        private async Task GetLinkedTreesAsync(string guid, IEnumerable <Match> matches, Throttle throttle)
        {
            if (!matches.Any())
            {
                return;
            }

            while (true)
            {
                try
                {
                    await throttle.WaitAsync();

                    var matchesDictionary = matches.ToDictionary(match => match.TestGuid);
                    var url = $"/discoveryui-matchesservice/api/samples/{guid}/matchesv2/additionalInfo?ids=[{"%22" + string.Join("%22,%22", matchesDictionary.Keys) + "%22"}]&tree=true";
                    using (var testsResponse = await _dnaHomeClient.GetAsync(url))
                    {
                        testsResponse.EnsureSuccessStatusCode();
                        var treeInfos = await testsResponse.Content.ReadAsAsync <List <TreeInfoV2> >();

                        foreach (var treeInfo in treeInfos)
                        {
                            if (matchesDictionary.TryGetValue(treeInfo.TestGuid, out var match))
                            {
                                match.TreeSize = treeInfo.TreeSize ?? 0;
                                match.TreeType = treeInfo.UnlinkedTree == true ? TreeType.Unlinked
                                    : treeInfo.PrivateTree == true ? TreeType.Private
                                    : treeInfo.PublicTree == true && match.TreeSize > 0 ? TreeType.Public
                                    : treeInfo.NoTrees == true ? TreeType.None
                                    : TreeType.Undetermined;
                            }
                        }
                        return;
                    }
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    throttle.Release();
                }

/*
 *              var retryCount = 0;
 *              var retryMax = 5;
 *              try
 *              {
 *                  await throttle.WaitAsync();
 *                  var matchesDictionary = matches.ToDictionary(match => match.TestGuid);
 *                  using (var testsResponse = await _dnaHomeClient.PostAsJsonAsync($"dna/secure/tests/{guid}/treeAncestors", matchesDictionary.Keys))
 *                  {
 *                      testsResponse.EnsureSuccessStatusCode();
 *                      var treeDetails = await testsResponse.Content.ReadAsAsync<Dictionary<string, LinkedTreeDetails>>();
 *                      foreach (var kvp in treeDetails)
 *                      {
 *                          if (matchesDictionary.TryGetValue(kvp.Key, out var match))
 *                          {
 *                              match.TreeSize = kvp.Value.PersonCount;
 *                              if (match.TreeSize > 0)
 *                              {
 *                                  match.TreeType = kvp.Value.PrivateTree ? TreeType.Private : TreeType.Public;
 *                              }
 *                          }
 *                      }
 *                      return;
 *                  }
 *              }
 *              catch (Exception ex)
 *              {
 *                  if (++retryCount >= retryMax)
 *                  {
 *                      throw;
 *                  }
 *                  await Task.Delay(ex is UnsupportedMediaTypeException ? 30000 : 3000);
 *              }
 *              finally
 *              {
 *                  throttle.Release();
 *              }
 */
            }
        }
예제 #16
0
        private async Task <IEnumerable <Match> > GetMatchesPageAsync(string guid, int pageNumber, bool includeTreeInfo, Throttle throttle, ProgressData progressData)
        {
            var nameUnavailableCount = 0;
            var nameUnavailableMax   = 60;
            var retryCount           = 0;
            var retryMax             = 5;

            while (true)
            {
                await throttle.WaitAsync();

                var throttleReleased = false;

                try
                {
                    using (var testsResponse = await _dnaHomeClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matchesv2?page={pageNumber}&bookmarkdata={{\"moreMatchesAvailable\":true,\"lastMatchesServicePageIdx\":{pageNumber - 1}}}"))
                    {
                        throttle.Release();
                        throttleReleased = true;

                        testsResponse.EnsureSuccessStatusCode();
                        var matches = await testsResponse.Content.ReadAsAsync <MatchesV2>();

                        var result = matches.MatchGroups.SelectMany(matchGroup => matchGroup.Matches)
                                     .Select(match => new Match
                        {
                            MatchTestAdminDisplayName = match.AdminDisplayName,
                            MatchTestDisplayName      = match.DisplayName,
                            TestGuid           = match.TestGuid,
                            SharedCentimorgans = match.Relationship?.SharedCentimorgans ?? 0,
                            SharedSegments     = match.Relationship?.SharedSegments ?? 0,
                            Starred            = match.Starred,
                            Note = match.Note,
                        })
                                     .ToList();

                        // Sometimes Ancestry returns matches with partial data.
                        // If that happens, retry and hope to get full data the next time.
                        if (result.Any(match => match.Name == "name unavailable") && ++nameUnavailableCount < nameUnavailableMax)
                        {
                            await Task.Delay(3000);

                            continue;
                        }

                        progressData.Increment();
                        if (includeTreeInfo)
                        {
                            try
                            {
                                await GetLinkedTreesAsync(guid, result, throttle);
                            }
                            catch
                            {
                                // non-fatal if unable to download trees
                            }
                        }

                        progressData.Increment();
                        return(result);
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        throw;
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    if (!throttleReleased)
                    {
                        throttle.Release();
                    }
                }
            }
        }
        public async Task <IEnumerable <Match> > GetMatchesPageAsync(string guid, HashSet <int> tagIds, int pageNumber, bool includeAdditionalInfo, Throttle throttle, ProgressData progressData)
        {
            var nameUnavailableCount = 0;
            var nameUnavailableMax   = 60;
            var retryCount           = 0;
            var retryMax             = 5;

            while (true)
            {
                await throttle.WaitAsync();

                var throttleReleased = false;

                try
                {
                    using (var testsResponse = await _ancestryLoginHelper.AncestryClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matches/list?page={pageNumber}&bookmarkdata={{\"moreMatchesAvailable\":true,\"lastMatchesServicePageIdx\":{pageNumber - 1}}}"))
                    {
                        throttle.Release();
                        throttleReleased = true;

                        testsResponse.EnsureSuccessStatusCode();
                        var matches = await testsResponse.Content.ReadAsAsync <MatchesV2>();

                        var result = matches.MatchGroups.SelectMany(matchGroup => matchGroup.Matches)
                                     .Select(match => ConvertMatch(match, tagIds))
                                     .ToList();

                        // Sometimes Ancestry returns matches with partial data.
                        // If that happens, retry and hope to get full data the next time.
                        if (result.Any(match => match.Name == "name unavailable") && ++nameUnavailableCount < nameUnavailableMax)
                        {
                            await Task.Delay(3000);

                            continue;
                        }

                        progressData.Increment();
                        if (includeAdditionalInfo)
                        {
                            try
                            {
                                await GetAdditionalInfoAsync(guid, result, throttle);
                            }
                            catch
                            {
                                // non-fatal if unable to download trees
                            }

                            if (pageNumber == 1)
                            {
                                try
                                {
                                    await GetParentsAsync(guid, result, throttle);
                                }
                                catch
                                {
                                    // non-fatal if unable to download parents
                                }
                            }
                        }

                        progressData.Increment();
                        return(result);
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        FileUtils.LogException(ex, true);
                        await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);

                        return(Enumerable.Empty <Match>());
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    if (!throttleReleased)
                    {
                        throttle.Release();
                    }
                }
            }
        }
예제 #18
0
        private async Task <(IEnumerable <Match>, bool)> GetMatchesInCommonPageAsync(string guid, string guidInCommon, int pageNumber, Throttle throttle)
        {
            if (guid == guidInCommon)
            {
                return(Enumerable.Empty <Match>(), false);
            }

            var nameUnavailableCount = 0;
            var nameUnavailableMax   = 60;
            var retryCount           = 0;
            var retryMax             = 5;

            while (true)
            {
                await throttle.WaitAsync();

                var throttleReleased = false;

                try
                {
                    using (var testsResponse = await _dnaHomeClient.GetAsync($"discoveryui-matchesservice/api/samples/{guid}/matchesv2?page={pageNumber}&relationguid={guidInCommon}&bookmarkdata={{\"moreMatchesAvailable\":true,\"lastMatchesServicePageIdx\":{pageNumber - 1}}}"))
                    {
                        throttle.Release();
                        throttleReleased = true;

                        if (testsResponse.StatusCode == System.Net.HttpStatusCode.Gone)
                        {
                            return(Enumerable.Empty <Match>(), false);
                        }
                        if (testsResponse.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable)
                        {
                            await Task.Delay(120000);

                            continue;
                        }
                        testsResponse.EnsureSuccessStatusCode();
                        var matches = await testsResponse.Content.ReadAsAsync <MatchesV2>();

                        var matchesInCommon = matches.MatchGroups.SelectMany(matchGroup => matchGroup.Matches)
                                              .Select(match => new Match
                        {
                            MatchTestAdminDisplayName = match.AdminDisplayName,
                            MatchTestDisplayName      = match.DisplayName,
                            TestGuid           = match.TestGuid,
                            SharedCentimorgans = match.Relationship?.SharedCentimorgans ?? 0,
                            SharedSegments     = match.Relationship?.SharedSegments ?? 0,
                            Starred            = match.Starred,
                            Note = match.Note,
                        })
                                              .ToList();

                        if (matchesInCommon.Any(match => match.Name == "name unavailable") && ++nameUnavailableCount < nameUnavailableMax)
                        {
                            await Task.Delay(3000);

                            continue;
                        }

                        return(matchesInCommon, matches.BookmarkData.moreMatchesAvailable);
                    }
                }
                catch (Exception ex)
                {
                    if (++retryCount >= retryMax)
                    {
                        throw;
                    }
                    await Task.Delay(ex is UnsupportedMediaTypeException? 30000 : 3000);
                }
                finally
                {
                    if (!throttleReleased)
                    {
                        throttle.Release();
                    }
                }
            }
        }