tools/code/extractor/WorkspaceApi.cs (145 lines of code) (raw):

using Azure.Core.Pipeline; using common; using LanguageExt; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace extractor; public delegate ValueTask ExtractWorkspaceApis(WorkspaceName workspaceName, CancellationToken cancellationToken); public delegate IAsyncEnumerable<(ApiName Name, WorkspaceApiDto Dto, Option<(ApiSpecification Specification, BinaryData Contents)> SpecificationOption)> ListWorkspaceApis(WorkspaceName workspaceName, CancellationToken cancellationToken); public delegate ValueTask WriteWorkspaceApiArtifacts(ApiName name, WorkspaceApiDto dto, Option<(ApiSpecification Specification, BinaryData Contents)> specificationOption, WorkspaceName workspaceName, CancellationToken cancellationToken); public delegate ValueTask WriteWorkspaceApiInformationFile(ApiName name, WorkspaceApiDto dto, WorkspaceName workspaceName, CancellationToken cancellationToken); public delegate ValueTask WriteWorkspaceApiSpecificationFile(ApiName name, ApiSpecification specification, BinaryData contents, WorkspaceName workspaceName, CancellationToken cancellationToken); internal static class WorkspaceApiModule { public static void ConfigureExtractWorkspaceApis(IHostApplicationBuilder builder) { ConfigureListWorkspaceApis(builder); ConfigureWriteWorkspaceApiArtifacts(builder); builder.Services.TryAddSingleton(GetExtractWorkspaceApis); } private static ExtractWorkspaceApis GetExtractWorkspaceApis(IServiceProvider provider) { var list = provider.GetRequiredService<ListWorkspaceApis>(); var writeArtifacts = provider.GetRequiredService<WriteWorkspaceApiArtifacts>(); var activitySource = provider.GetRequiredService<ActivitySource>(); var logger = provider.GetRequiredService<ILogger>(); return async (workspaceName, cancellationToken) => { using var _ = activitySource.StartActivity(nameof(ExtractWorkspaceApis)); logger.LogInformation("Extracting APIs for workspace {WorkspaceName}...", workspaceName); await list(workspaceName, cancellationToken) // Group APIs by version set (https://github.com/Azure/apiops/issues/316). // We'll process each group in parallel, but each API within a group sequentially. .GroupBy(api => api.Dto.Properties.ApiVersionSetId ?? string.Empty) .IterParallel(async group => await group.Iter(async api => await extractApi(api.Name, api.Dto, api.SpecificationOption, workspaceName, cancellationToken), cancellationToken), cancellationToken); }; async ValueTask extractApi(ApiName name, WorkspaceApiDto dto, Option<(ApiSpecification Specification, BinaryData Contents)> specificationOption, WorkspaceName workspaceName, CancellationToken cancellationToken) { await writeArtifacts(name, dto, specificationOption, workspaceName, cancellationToken); } } private static void ConfigureListWorkspaceApis(IHostApplicationBuilder builder) { ApiSpecificationModule.ConfigureDefaultApiSpecification(builder); AzureModule.ConfigureManagementServiceUri(builder); AzureModule.ConfigureHttpPipeline(builder); builder.Services.TryAddSingleton(GetListWorkspaceApis); } private static ListWorkspaceApis GetListWorkspaceApis(IServiceProvider provider) { var defaultApiSpecification = provider.GetRequiredService<DefaultApiSpecification>(); var serviceUri = provider.GetRequiredService<ManagementServiceUri>(); var pipeline = provider.GetRequiredService<HttpPipeline>(); return (workspaceName, cancellationToken) => { var workspaceApisUri = WorkspaceApisUri.From(workspaceName, serviceUri); return workspaceApisUri.List(pipeline, cancellationToken) .SelectAwait(async api => { var (name, dto) = api; var specificationContentsOption = await tryGetSpecificationContents(name, dto, workspaceName, cancellationToken); return (name, dto, specificationContentsOption); }); }; async ValueTask<Option<(ApiSpecification, BinaryData)>> tryGetSpecificationContents(ApiName name, WorkspaceApiDto dto, WorkspaceName workspaceName, CancellationToken cancellationToken) { var specificationOption = tryGetSpecification(dto); return await specificationOption.BindTask(async specification => { var uri = WorkspaceApiUri.From(name, workspaceName, serviceUri); var contentsOption = await uri.TryGetSpecificationContents(specification, pipeline, cancellationToken); return from contents in contentsOption select (specification, contents); }); } Option<ApiSpecification> tryGetSpecification(WorkspaceApiDto dto) => (dto.Properties.Type ?? dto.Properties.ApiType) switch { "graphql" => new ApiSpecification.GraphQl(), "soap" => new ApiSpecification.Wsdl(), "http" => defaultApiSpecification.Value, null => defaultApiSpecification.Value, _ => Option<ApiSpecification>.None }; } private static void ConfigureWriteWorkspaceApiArtifacts(IHostApplicationBuilder builder) { ConfigureWriteWorkspaceApiInformationFile(builder); ConfigureWriteWorkspaceApiSpecificationFile(builder); builder.Services.TryAddSingleton(GetWriteWorkspaceApiArtifacts); } private static WriteWorkspaceApiArtifacts GetWriteWorkspaceApiArtifacts(IServiceProvider provider) { var writeInformationFile = provider.GetRequiredService<WriteWorkspaceApiInformationFile>(); var writeSpecificationFile = provider.GetRequiredService<WriteWorkspaceApiSpecificationFile>(); return async (name, dto, specificationContentsOption, workspaceName, cancellationToken) => { await writeInformationFile(name, dto, workspaceName, cancellationToken); await specificationContentsOption.IterTask(async x => { var (specification, contents) = x; await writeSpecificationFile(name, specification, contents, workspaceName, cancellationToken); }); }; } private static void ConfigureWriteWorkspaceApiInformationFile(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceDirectory(builder); builder.Services.TryAddSingleton(GetWriteWorkspaceApiInformationFile); } private static WriteWorkspaceApiInformationFile GetWriteWorkspaceApiInformationFile(IServiceProvider provider) { var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>(); var logger = provider.GetRequiredService<ILogger>(); return async (name, dto, workspaceName, cancellationToken) => { var informationFile = WorkspaceApiInformationFile.From(name, workspaceName, serviceDirectory); logger.LogInformation("Writing workspace API information file {WorkspaceApiInformationFile}...", informationFile); await informationFile.WriteDto(dto, cancellationToken); }; } private static void ConfigureWriteWorkspaceApiSpecificationFile(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceDirectory(builder); builder.Services.TryAddSingleton(GetWriteWorkspaceApiSpecificationFile); } private static WriteWorkspaceApiSpecificationFile GetWriteWorkspaceApiSpecificationFile(IServiceProvider provider) { var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>(); var logger = provider.GetRequiredService<ILogger>(); return async (name, specification, contents, workspaceName, cancellationToken) => { var specificationFile = WorkspaceApiSpecificationFile.From(specification, name, workspaceName, serviceDirectory); logger.LogInformation("Writing workspace API specification file {WorkspaceApiSpecificationFile}...", specificationFile); await specificationFile.WriteSpecification(contents, cancellationToken); }; } }