in tools/code/publisher/WorkspaceApi.cs [588:653]
private static DeleteWorkspaceApi GetDeleteWorkspaceApi(IServiceProvider provider)
{
var findDto = provider.GetRequiredService<FindWorkspaceApiDto>();
var deleteFromApim = provider.GetRequiredService<DeleteWorkspaceApiFromApim>();
var activitySource = provider.GetRequiredService<ActivitySource>();
var logger = provider.GetRequiredService<ILogger>();
var taskDictionary = new ConcurrentDictionary<(ApiName, WorkspaceName), AsyncLazy<Unit>>();
return async (name, workspaceName, cancellationToken) =>
{
using var _ = activitySource.StartActivity(nameof(DeleteWorkspaceApi))
?.AddTag("workspace.name", workspaceName)
?.AddTag("workspace_api.name", name);
await taskDictionary.GetOrAdd((name, workspaceName),
pair => new AsyncLazy<Unit>(async cancellationToken =>
{
var (name, workspaceName) = pair;
await deleteApiInner(name, workspaceName, cancellationToken);
return Unit.Default;
}))
.WithCancellation(cancellationToken);
};
async ValueTask deleteApiInner(ApiName name, WorkspaceName workspaceName, CancellationToken cancellationToken)
{
if (await isApiRevisionNumberCurrentInSourceControl(name, workspaceName, cancellationToken))
{
logger.LogInformation("API {ApiName} in workspace {WorkspaceName} is the current revision in source control. Skipping deletion...", name, workspaceName);
return;
}
await deleteFromApim(name, workspaceName, cancellationToken);
}
/// <summary>
/// We don't want to delete a revision if it was just made current. For instance:
/// 1. Dev has apiA with revision 1 (current) and revision 2. Artifacts folder has:
/// - /apis/apiA/apiInformation.json with revision 1 as current
/// - /apis/apiA;rev=2/apiInformation.json
/// 2. User makes revision 2 current in dev APIM.
/// 3. User runs extractor for dev APIM. Artifacts folder has:
/// - /apis/apiA/apiInformation.json with revision 2 as current
/// - /apis/apiA;rev=1/apiInformation.json
/// - /apis/apiA;rev=2 folder gets deleted.
/// 4. User runs publisher to prod APIM. We don't want to handle the deletion of folder /apis/apiA;rev=2, as it's the current revision.
async ValueTask<bool> isApiRevisionNumberCurrentInSourceControl(ApiName name, WorkspaceName workspaceName, CancellationToken cancellationToken) =>
await ApiName.TryParseRevisionedName(name)
.Match(async _ => await ValueTask.FromResult(false),
async api =>
{
var (rootName, revisionNumber) = api;
var sourceControlRevisionNumberOption = await tryGetRevisionNumberInSourceControl(rootName, workspaceName, cancellationToken);
return sourceControlRevisionNumberOption
.Map(sourceControlRevisionNumber => sourceControlRevisionNumber == revisionNumber)
.IfNone(false);
});
async ValueTask<Option<ApiRevisionNumber>> tryGetRevisionNumberInSourceControl(ApiName name, WorkspaceName workspaceName, CancellationToken cancellationToken)
{
var dtoOption = await findDto(name, workspaceName, cancellationToken);
return dtoOption.Map(Common.GetRevisionNumber);
}
}