Skip to content

Commit

Permalink
[Client SDK] Separate search and autocomplete clients (loic-sharma#470)
Browse files Browse the repository at this point in the history
Addresses loic-sharma#468
  • Loading branch information
loic-sharma authored Feb 12, 2020
1 parent bd44019 commit 30aa9c2
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 91 deletions.
91 changes: 74 additions & 17 deletions src/BaGet.Protocol/NuGetClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class NuGetClient
private readonly IPackageContentClient _contentClient;
private readonly IPackageMetadataClient _metadataClient;
private readonly ISearchClient _searchClient;
private readonly IAutocompleteClient _autocompleteClient;

/// <summary>
/// Initializes a new instance of the <see cref="NuGetClient"/> class
Expand Down Expand Up @@ -48,6 +49,7 @@ public NuGetClient(string serviceIndexUrl)
_contentClient = clientFactory.CreatePackageContentClient();
_metadataClient = clientFactory.CreatePackageMetadataClient();
_searchClient = clientFactory.CreateSearchClient();
_autocompleteClient = clientFactory.CreateAutocompleteClient();
}

/// <summary>
Expand Down Expand Up @@ -303,6 +305,33 @@ public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
return response.Data;
}

/// <summary>
/// Search for packages. Includes prerelease packages.
/// </summary>
/// <param name="query">
/// The search query. If <see langword="null"/>, gets default search results.
/// </param>
/// <param name="skip">The number of results to skip.</param>
/// <param name="take">The number of results to include.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The search results, including prerelease packages.</returns>
public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
string query,
int skip,
int take,
CancellationToken cancellationToken = default)
{
var response = await _searchClient.SearchAsync(
query,
skip,
take,
includePrerelease: true,
includeSemVer2: true,
cancellationToken: cancellationToken);

return response.Data;
}

/// <summary>
/// Search for packages.
/// </summary>
Expand All @@ -326,53 +355,72 @@ public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
}

/// <summary>
/// Search for packages. Includes prerelease packages.
/// Search for packages.
/// </summary>
/// <param name="query">
/// The search query. If <see langword="null"/>, gets default search results.
/// </param>
/// <param name="skip">The number of results to skip.</param>
/// <param name="take">The number of results to include.</param>
/// <param name="includePrerelease">Whether to include prerelease packages.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The search results, including prerelease packages.</returns>
public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
string query,
int skip,
int take,
bool includePrerelease,
CancellationToken cancellationToken = default)
{
var response = await _searchClient.SearchAsync(
var response = await _searchClient.SearchAsync(
query,
skip,
take,
cancellationToken: cancellationToken);
includePrerelease,
includeSemVer2: true,
cancellationToken);

return response.Data;
}

/// <summary>
/// Search for packages.
/// Search for package IDs. Includes prerelease packages.
/// </summary>
/// <param name="query">
/// The search query. If <see langword="null"/>, gets default search results.
/// The search query. If <see langword="null"/>, gets default autocomplete results.
/// </param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The package IDs that matched the query.</returns>
public virtual async Task<IReadOnlyList<string>> AutocompleteAsync(
string query = null,
CancellationToken cancellationToken = default)
{
var response = await _autocompleteClient.AutocompleteAsync(query, cancellationToken: cancellationToken);

return response.Data;
}

/// <summary>
/// Search for package IDs. Includes prerelease packages.
/// </summary>
/// <param name="query">
/// The search query. If <see langword="null"/>, gets default autocomplete results.
/// </param>
/// <param name="includePrerelease">Whether to include prerelease packages.</param>
/// <param name="skip">The number of results to skip.</param>
/// <param name="take">The number of results to include.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The search results, including prerelease packages.</returns>
public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
/// <returns>The package IDs that matched the query.</returns>
public virtual async Task<IReadOnlyList<string>> AutocompleteAsync(
string query,
bool includePrerelease,
int skip,
int take,
CancellationToken cancellationToken = default)
{
var response = await _searchClient.SearchAsync(
var response = await _autocompleteClient.AutocompleteAsync(
query,
skip,
take,
includePrerelease,
includePrerelease: true,
includeSemVer2: true,
cancellationToken);

Expand All @@ -385,13 +433,18 @@ public virtual async Task<IReadOnlyList<SearchResult>> SearchAsync(
/// <param name="query">
/// The search query. If <see langword="null"/>, gets default autocomplete results.
/// </param>
/// <param name="includePrerelease">Whether to include prerelease packages.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The package IDs that matched the query.</returns>
public virtual async Task<IReadOnlyList<string>> AutocompleteAsync(
string query = null,
string query,
bool includePrerelease,
CancellationToken cancellationToken = default)
{
var response = await _searchClient.AutocompleteAsync(query, cancellationToken: cancellationToken);
var response = await _autocompleteClient.AutocompleteAsync(
query,
includePrerelease: includePrerelease,
cancellationToken: cancellationToken);

return response.Data;
}
Expand All @@ -404,19 +457,23 @@ public virtual async Task<IReadOnlyList<string>> AutocompleteAsync(
/// </param>
/// <param name="skip">The number of results to skip.</param>
/// <param name="take">The number of results to include.</param>
/// <param name="includePrerelease">Whether to include prerelease packages.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The package IDs that matched the query.</returns>
public virtual async Task<IReadOnlyList<string>> AutocompleteAsync(
string query,
int skip,
int take,
bool includePrerelease,
CancellationToken cancellationToken = default)
{
var response = await _searchClient.AutocompleteAsync(
var response = await _autocompleteClient.AutocompleteAsync(
query,
skip: skip,
take: take,
cancellationToken: cancellationToken);
skip,
take,
includePrerelease,
includeSemVer2: true,
cancellationToken);

return response.Data;
}
Expand Down
21 changes: 20 additions & 1 deletion src/BaGet.Protocol/NuGetClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ public virtual ISearchClient CreateSearchClient()
return new SearchClient(this);
}

/// <summary>
/// Create a client to interact with the NuGet Autocomplete resource.
///
/// See https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource
/// </summary>
/// <returns>A client to interact with the NuGet Autocomplete resource.</returns>
public virtual IAutocompleteClient CreateAutocompleteClient()
{
return new AutocompleteClient(this);
}

/// <summary>
/// Create a client to interact with the NuGet catalog resource.
///
Expand Down Expand Up @@ -121,6 +132,11 @@ private Task<ISearchClient> GetSearchClientAsync(CancellationToken cancellationT
return GetAsync(c => c.SearchClient, cancellationToken);
}

private Task<IAutocompleteClient> GetAutocompleteClientAsync(CancellationToken cancellationToken = default)
{
return GetAsync(c => c.AutocompleteClient, cancellationToken);
}

private Task<ICatalogClient> GetCatalogClientAsync(CancellationToken cancellationToken = default)
{
return GetAsync(c => c.CatalogClient, cancellationToken);
Expand Down Expand Up @@ -148,7 +164,8 @@ private async Task<T> GetAsync<T>(Func<NuGetClients, T> clientFactory, Cancellat

var contentClient = new RawPackageContentClient(_httpClient, contentResourceUrl);
var metadataClient = new RawPackageMetadataClient(_httpClient, metadataResourceUrl);
var searchClient = new RawSearchClient(_httpClient, searchResourceUrl, autocompleteResourceUrl);
var searchClient = new RawSearchClient(_httpClient, searchResourceUrl);
var autocompleteClient = new RawAutocompleteClient(_httpClient, autocompleteResourceUrl);
var catalogClient = catalogResourceUrl == null
? new NullCatalogClient() as ICatalogClient
: new RawCatalogClient(_httpClient, catalogResourceUrl);
Expand All @@ -160,6 +177,7 @@ private async Task<T> GetAsync<T>(Func<NuGetClients, T> clientFactory, Cancellat
PackageContentClient = contentClient,
PackageMetadataClient = metadataClient,
SearchClient = searchClient,
AutocompleteClient = autocompleteClient,
CatalogClient = catalogClient,
};
}
Expand All @@ -181,6 +199,7 @@ private class NuGetClients
public IPackageContentClient PackageContentClient { get; set; }
public IPackageMetadataClient PackageMetadataClient { get; set; }
public ISearchClient SearchClient { get; set; }
public IAutocompleteClient AutocompleteClient { get; set; }
public ICatalogClient CatalogClient { get; set; }
}
}
Expand Down
48 changes: 48 additions & 0 deletions src/BaGet.Protocol/Search/AutocompleteClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using BaGet.Protocol.Models;

namespace BaGet.Protocol
{
public partial class NuGetClientFactory
{
private class AutocompleteClient : IAutocompleteClient
{
private readonly NuGetClientFactory _clientfactory;

public AutocompleteClient(NuGetClientFactory clientFactory)
{
_clientfactory = clientFactory ?? throw new ArgumentNullException(nameof(clientFactory));
}

public async Task<AutocompleteResponse> AutocompleteAsync(
string query = null,
int skip = 0,
int take = 20,
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default)
{
// TODO: Support search failover.
// See: https://github.com/loic-sharma/BaGet/issues/314
var client = await _clientfactory.GetAutocompleteClientAsync(cancellationToken);

return await client.AutocompleteAsync(query, skip, take, includePrerelease, includeSemVer2, cancellationToken);
}

public async Task<AutocompleteResponse> ListPackageVersionsAsync(
string packageId,
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default)
{
// TODO: Support search failover.
// See: https://github.com/loic-sharma/BaGet/issues/314
var client = await _clientfactory.GetAutocompleteClientAsync(cancellationToken);

return await client.ListPackageVersionsAsync(packageId, includePrerelease, includeSemVer2, cancellationToken);
}
}
}
}
48 changes: 48 additions & 0 deletions src/BaGet.Protocol/Search/IAutocompleteClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Threading;
using System.Threading.Tasks;
using BaGet.Protocol.Models;

namespace BaGet.Protocol
{
/// <summary>
/// The client used to search for packages.
///
/// See https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource
/// </summary>
public interface IAutocompleteClient
{
/// <summary>
/// Perform an autocomplete query on package IDs.
/// See: https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource#search-for-package-ids
/// </summary>
/// <param name="query">The autocomplete query.</param>
/// <param name="skip">How many results to skip.</param>
/// <param name="take">How many results to return.</param>
/// <param name="includePrerelease">Whether pre-release packages should be returned.</param>
/// <param name="includeSemVer2">Whether packages that require SemVer 2.0.0 compatibility should be returned.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The autocomplete response.</returns>
Task<AutocompleteResponse> AutocompleteAsync(
string query = null,
int skip = 0,
int take = 20,
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default);

/// <summary>
/// Enumerate listed package versions.
/// See: https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource#enumerate-package-versions
/// </summary>
/// <param name="packageId">The package ID.</param>
/// <param name="includePrerelease">Whether pre-release packages should be returned.</param>
/// <param name="includeSemVer2">Whether packages that require SemVer 2.0.0 compatibility should be returned.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The package versions that matched the request.</returns>
Task<AutocompleteResponse> ListPackageVersionsAsync(
string packageId,
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default);
}
}
21 changes: 0 additions & 21 deletions src/BaGet.Protocol/Search/ISearchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,5 @@ Task<SearchResponse> SearchAsync(
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default);

/// <summary>
/// Perform an autocomplete query.
/// See: https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource
/// </summary>
/// <param name="query">The autocomplete query.</param>
/// <param name="type">The autocomplete request type.</param>
/// <param name="skip">How many results to skip.</param>
/// <param name="take">How many results to return.</param>
/// <param name="includePrerelease">Whether pre-release packages should be returned.</param>
/// <param name="includeSemVer2">Whether packages that require SemVer 2.0.0 compatibility should be returned.</param>
/// <param name="cancellationToken">A token to cancel the task.</param>
/// <returns>The autocomplete response.</returns>
Task<AutocompleteResponse> AutocompleteAsync(
string query = null,
AutocompleteType type = AutocompleteType.PackageIds,
int skip = 0,
int take = 20,
bool includePrerelease = true,
bool includeSemVer2 = true,
CancellationToken cancellationToken = default);
}
}
Loading

0 comments on commit 30aa9c2

Please sign in to comment.