Permalink
Browse files

V2 autocomplete endpoints utilize V3 autocomplete service instead of …

…SQL Database
  • Loading branch information...
maartenba committed Aug 26, 2015
1 parent dca1625 commit 764ce67c1680df04ee570c9156eaac9d20cb5550
@@ -247,22 +247,14 @@ protected override void Load(ContainerBuilder builder)
.As<IAutomaticallyCuratePackageCommand>()
.InstancePerLifetimeScope();

builder.RegisterType<PackageIdsQuery>()
.AsSelf()
.As<IPackageIdsQuery>()
.InstancePerLifetimeScope();

builder.RegisterType<PackageVersionsQuery>()
.AsSelf()
.As<IPackageVersionsQuery>()
.InstancePerLifetimeScope();
ConfigureAutocomplete(builder, configuration);

builder.RegisterType<DiagnosticsService>()
.AsSelf()
.As<IDiagnosticsService>()
.SingleInstance();
}

private static void ConfigureSearch(ContainerBuilder builder, ConfigurationService configuration)
{
if (configuration.Current.ServiceDiscoveryUri == null)
@@ -285,6 +277,34 @@ private static void ConfigureSearch(ContainerBuilder builder, ConfigurationServi
.InstancePerLifetimeScope();
}
}
private void ConfigureAutocomplete(ContainerBuilder builder, ConfigurationService configuration)
{
if (configuration.Current.ServiceDiscoveryUri != null &&
!string.IsNullOrEmpty(configuration.Current.AutocompleteServiceResourceType))
{
builder.RegisterType<AutocompleteServicePackageIdsQuery>()
.AsSelf()
.As<IPackageIdsQuery>()
.SingleInstance();

builder.RegisterType<AutocompleteServicePackageVersionsQuery>()
.AsSelf()
.As<IPackageVersionsQuery>()
.InstancePerLifetimeScope();
}
else
{
builder.RegisterType<PackageIdsQuery>()
.AsSelf()
.As<IPackageIdsQuery>()
.InstancePerLifetimeScope();

builder.RegisterType<PackageVersionsQuery>()
.AsSelf()
.As<IPackageVersionsQuery>()
.InstancePerLifetimeScope();
}
}

private static void ConfigureForLocalFileSystem(ContainerBuilder builder)
{
@@ -47,6 +47,11 @@ public class AppConfiguration : IAppConfiguration
/// </summary>
public string SearchServiceResourceType { get; set; }

/// <summary>
/// Gets the @type for the Autocomplete endpoint
/// </summary>
public string AutocompleteServiceResourceType { get; set; }

/// <summary>
/// Gets the URI to the metrics service
/// </summary>
@@ -53,6 +53,11 @@ public interface IAppConfiguration
/// </summary>
string SearchServiceResourceType { get; set; }

/// <summary>
/// Gets the @type for the Autocomplete endpoint
/// </summary>
string AutocompleteServiceResourceType { get; set; }

/// <summary>
/// Gets the URI to the metrics service
/// </summary>
@@ -451,24 +451,24 @@ protected internal virtual INupkg ReadPackageFromRequest()

[HttpGet]
[ActionName("PackageIDs")]
public virtual ActionResult GetPackageIds(string partialId, bool? includePrerelease)
public virtual async Task<ActionResult> GetPackageIds(string partialId, bool? includePrerelease)
{
var query = GetService<IPackageIdsQuery>();
return new JsonResult
{
Data = (query.Execute(partialId, includePrerelease).ToArray()),
Data = (await query.Execute(partialId, includePrerelease)).ToArray(),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

[HttpGet]
[ActionName("PackageVersions")]
public virtual ActionResult GetPackageVersions(string id, bool? includePrerelease)
public virtual async Task<ActionResult> GetPackageVersions(string id, bool? includePrerelease)
{
var query = GetService<IPackageVersionsQuery>();
return new JsonResult
{
Data = query.Execute(id, includePrerelease).ToArray(),
Data = (await query.Execute(id, includePrerelease)).ToArray(),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
@@ -1,19 +1,66 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NuGet.Services.Search.Client;
using NuGetGallery.Configuration;

namespace NuGetGallery
{
public interface IPackageIdsQuery
{
IEnumerable<string> Execute(
Task<IEnumerable<string>> Execute(
string partialId,
bool? includePrerelease = false);
}

public class AutocompleteServicePackageIdsQuery : IPackageIdsQuery
{
private readonly ServiceDiscoveryClient _serviceDiscoveryClient;
private readonly string _autocompleteServiceResourceType;
private readonly RetryingHttpClientWrapper _httpClient;

public AutocompleteServicePackageIdsQuery(IAppConfiguration configuration)
{
_serviceDiscoveryClient = new ServiceDiscoveryClient(configuration.ServiceDiscoveryUri);
_autocompleteServiceResourceType = configuration.AutocompleteServiceResourceType;
_httpClient = new RetryingHttpClientWrapper(new HttpClient());
}

public async Task<IEnumerable<string>> Execute(string partialId, bool? includePrerelease)
{
if (partialId == null)
{
partialId = string.Empty;
}

var queryString = "take=30&q=" + Uri.EscapeUriString(partialId);
if (!includePrerelease.HasValue)
{
queryString += "&prerelease=false";
}
else
{
queryString += "&prerelease=" + includePrerelease.Value;
}

var endpoints = await _serviceDiscoveryClient.GetEndpointsForResourceType(_autocompleteServiceResourceType);
endpoints = endpoints.Select(e => new Uri(e + "?" + queryString)).AsEnumerable();

var result = await _httpClient.GetStringAsync(endpoints);
var resultObject = JObject.Parse(result);

return resultObject["data"].Select(entry => entry.ToString());
}
}

public class PackageIdsQuery : IPackageIdsQuery
{
private const string PartialIdSqlFormat = @"SELECT TOP 30 pr.ID
@@ -37,24 +84,24 @@ public PackageIdsQuery(IEntitiesContext entities)
_entities = entities;
}

public IEnumerable<string> Execute(
public Task<IEnumerable<string>> Execute(
string partialId,
bool? includePrerelease = false)
{
var dbContext = (DbContext)_entities;

if (String.IsNullOrWhiteSpace(partialId))
{
return dbContext.Database.SqlQuery<string>(NoPartialIdSql);
return Task.FromResult(dbContext.Database.SqlQuery<string>(NoPartialIdSql));
}

var prereleaseFilter = String.Empty;
if (!includePrerelease.HasValue || !includePrerelease.Value)
{
prereleaseFilter = "AND p.IsPrerelease = {1}";
}
return dbContext.Database.SqlQuery<string>(
String.Format(CultureInfo.InvariantCulture, PartialIdSqlFormat, prereleaseFilter), partialId + "%", includePrerelease ?? false);
return Task.FromResult(dbContext.Database.SqlQuery<string>(
String.Format(CultureInfo.InvariantCulture, PartialIdSqlFormat, prereleaseFilter), partialId + "%", includePrerelease ?? false));
}
}
}
@@ -1,19 +1,66 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NuGet.Services.Search.Client;
using NuGetGallery.Configuration;

namespace NuGetGallery
{
public interface IPackageVersionsQuery
{
IEnumerable<string> Execute(
Task<IEnumerable<string>> Execute(
string id,
bool? includePrerelease = false);
}

public class AutocompleteServicePackageVersionsQuery : IPackageVersionsQuery
{
private readonly ServiceDiscoveryClient _serviceDiscoveryClient;
private readonly string _autocompleteServiceResourceType;
private readonly RetryingHttpClientWrapper _httpClient;

public AutocompleteServicePackageVersionsQuery(IAppConfiguration configuration)
{
_serviceDiscoveryClient = new ServiceDiscoveryClient(configuration.ServiceDiscoveryUri);
_autocompleteServiceResourceType = configuration.AutocompleteServiceResourceType;
_httpClient = new RetryingHttpClientWrapper(new HttpClient());
}

public async Task<IEnumerable<string>> Execute(string id, bool? includePrerelease)
{
if (string.IsNullOrWhiteSpace(id))
{
throw new ArgumentNullException("id");
}

var queryString = "take=30&id=" + Uri.EscapeUriString(id);
if (!includePrerelease.HasValue)
{
queryString += "&prerelease=false";
}
else
{
queryString += "&prerelease=" + includePrerelease.Value;
}

var endpoints = await _serviceDiscoveryClient.GetEndpointsForResourceType(_autocompleteServiceResourceType);
endpoints = endpoints.Select(e => new Uri(e + "?" + queryString)).AsEnumerable();

var result = await _httpClient.GetStringAsync(endpoints);
var resultObject = JObject.Parse(result);

return resultObject["data"].Select(entry => entry.ToString());
}
}

public class PackageVersionsQuery : IPackageVersionsQuery
{
private const string SqlFormat = @"SELECT p.[Version]
@@ -29,7 +76,7 @@ public PackageVersionsQuery(IEntitiesContext entities)
_entities = entities;
}

public IEnumerable<string> Execute(
public Task<IEnumerable<string>> Execute(
string id,
bool? includePrerelease = false)
{
@@ -45,8 +92,8 @@ public PackageVersionsQuery(IEntitiesContext entities)
{
prereleaseFilter = "AND p.IsPrerelease = 0";
}
return dbContext.Database.SqlQuery<string>(
String.Format(CultureInfo.InvariantCulture, SqlFormat, prereleaseFilter), id);
return Task.FromResult(dbContext.Database.SqlQuery<string>(
String.Format(CultureInfo.InvariantCulture, SqlFormat, prereleaseFilter), id));
}
}
}
@@ -76,9 +76,11 @@
<!-- Example:
<add key="Gallery.ServiceDiscoveryUri" value="https://api.nuget.org/v3/index.json" />
<add key="Gallery.SearchServiceResourceType" value="SearchGalleryQueryService/3.0.0-rc" />
<add key="Gallery.AutocompleteServiceResourceType" value="SearchAutocompleteService/3.0.0-rc" />
-->
<add key="Gallery.ServiceDiscoveryUri" value="" />
<add key="Gallery.SearchServiceResourceType" value="" />
<add key="Gallery.AutocompleteServiceResourceType" value="" />
<add key="Gallery.Brand" value="NuGet Gallery" />
<add key="Gallery.GalleryOwner" value="NuGet Gallery &lt;support@nuget.org&gt;" />
<add key="Gallery.ConfirmEmailAddresses" value="true" />
@@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Linq;
using System.Threading.Tasks;
using Moq;
using NuGetGallery.Configuration;
using Xunit;

namespace NuGetGallery
{
public class AutocompleteServicePackageIdsQueryFacts
{
private IAppConfiguration GetConfiguration()
{
var mockConfiguration = new Mock<IAppConfiguration>();
mockConfiguration.SetupGet(c => c.ServiceDiscoveryUri).Returns(new Uri("https://api.nuget.org/v3/index.json"));
mockConfiguration.SetupGet(c => c.AutocompleteServiceResourceType).Returns("SearchAutocompleteService/3.0.0-rc");
return mockConfiguration.Object;
}

[Fact]
public async Task ExecuteReturns30ResultsForEmptyQuery()
{
var query = new AutocompleteServicePackageIdsQuery(GetConfiguration());
var result = await query.Execute("", false);
Assert.NotEmpty(result);
Assert.True(result.Count() == 30);
}

[Fact]
public async Task ExecuteReturns30ResultsForNullQuery()
{
var query = new AutocompleteServicePackageIdsQuery(GetConfiguration());
var result = await query.Execute(null, false);
Assert.NotEmpty(result);
Assert.True(result.Count() == 30);
}

[Fact]
public async Task ExecuteReturnsResultsForSpecificQuery()
{
var query = new AutocompleteServicePackageIdsQuery(GetConfiguration());
var result = await query.Execute("jquery", false);
Assert.NotEmpty(result);
Assert.Contains("jquery", result, StringComparer.OrdinalIgnoreCase);
}
}
}
Oops, something went wrong.

0 comments on commit 764ce67

Please sign in to comment.