Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 4.3.1 #37

Merged
merged 1 commit into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ launchSettings.json
UpgradeLog.htm
*.*.ini
*.*.json
src/Documentation/python

# Public repo ignores
.github/pull_request_template.md
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Version>4.3.0</Version>
<Version>4.3.1</Version>
<Authors>Salesforce, Inc.</Authors>
<Company>Salesforce, Inc.</Company>
<Copyright>Copyright (c) 2024, Salesforce, Inc. and its licensors</Copyright>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
using Tableau.Migration.Api.Rest;
using Tableau.Migration.Api.Rest.Models;
using Tableau.Migration.Content;
using Tableau.Migration.Content.Schedules;
using Tableau.Migration.Content.Search;
using Tableau.Migration.Resources;

Expand Down Expand Up @@ -126,19 +125,6 @@ internal static class IContentReferenceFinderFactoryExtensions
cancel)
.ConfigureAwait(false);

public static async Task<IContentReference> FindExtractRefreshContentAsync(
this IContentReferenceFinderFactory finderFactory,
ExtractRefreshContentType contentType,
Guid contentId,
CancellationToken cancel)
{
var finder = finderFactory.ForExtractRefreshContent(contentType);

var content = await finder.FindByIdAsync(contentId, cancel).ConfigureAwait(false);

return Guard.AgainstNull(content, nameof(content));
}

private static async Task<IContentReference?> FindAsync<TResponse, TContent>(
this IContentReferenceFinderFactory finderFactory,
[NotNull] TResponse? response,
Expand Down
42 changes: 17 additions & 25 deletions src/Tableau.Migration/Api/TasksApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using Tableau.Migration.Net.Rest;
using Tableau.Migration.Paging;
using Tableau.Migration.Resources;

using CloudResponses = Tableau.Migration.Api.Rest.Models.Responses.Cloud;
using ServerResponses = Tableau.Migration.Api.Rest.Models.Responses.Server;

Expand Down Expand Up @@ -70,17 +71,11 @@ public TasksApiClient(

/// <inheritdoc />
public IServerTasksApiClient ForServer()
=> ExecuteForInstanceType(
TableauInstanceType.Server,
_sessionProvider.InstanceType,
() => this);
=> ExecuteForInstanceType(TableauInstanceType.Server, _sessionProvider.InstanceType, () => this);

/// <inheritdoc />
public ICloudTasksApiClient ForCloud()
=> ExecuteForInstanceType(
TableauInstanceType.Cloud,
_sessionProvider.InstanceType,
() => this);
=> ExecuteForInstanceType(TableauInstanceType.Cloud, _sessionProvider.InstanceType, () => this);

#endregion

Expand All @@ -105,10 +100,7 @@ public async Task<IResult> DeleteExtractRefreshTaskAsync(
async Task<IResult<IImmutableList<ICloudExtractRefreshTask>>> ICloudTasksApiClient.GetAllExtractRefreshTasksAsync(
CancellationToken cancel)
=> await GetAllExtractRefreshTasksAsync<CloudResponses.ExtractRefreshTasksResponse, ICloudExtractRefreshTask, ICloudSchedule>(
(r, c) => CloudExtractRefreshTask.CreateManyAsync(
r,
ContentFinderFactory,
c),
(r, c) => CloudExtractRefreshTask.CreateManyAsync(r, ContentFinderFactory, Logger, SharedResourcesLocalizer, c),
cancel)
.ConfigureAwait(false);

Expand All @@ -122,14 +114,18 @@ async Task<IResult<ICloudExtractRefreshTask>> ICloudTasksApiClient.CreateExtract
.ForPostRequest()
.WithXmlContent(new CreateExtractRefreshTaskRequest(options))
.SendAsync<CloudResponses.CreateExtractRefreshTaskResponse>(cancel)
.ToResultAsync((r, c) =>
CloudExtractRefreshTask.CreateAsync(
r.Item,
r.Schedule,
ContentFinderFactory,
c),
SharedResourcesLocalizer,
cancel)
.ToResultAsync(async (r, c) =>
{
var task = Guard.AgainstNull(r.Item, () => r.Item);
var finder = ContentFinderFactory.ForExtractRefreshContent(task.GetContentType());

var contentReference = await finder.FindByIdAsync(task.GetContentId(), cancel).ConfigureAwait(false);

// Since we published with a content reference, we expect the reference returned is valid/knowable.
Guard.AgainstNull(contentReference, () => contentReference);

return CloudExtractRefreshTask.Create(task, r.Schedule, contentReference);
}, SharedResourcesLocalizer, cancel)
.ConfigureAwait(false);

return result;
Expand Down Expand Up @@ -158,11 +154,7 @@ public async Task<IResult<ICloudExtractRefreshTask>> PublishAsync(
/// <inheritdoc />
async Task<IResult<IImmutableList<IServerExtractRefreshTask>>> IServerTasksApiClient.GetAllExtractRefreshTasksAsync(CancellationToken cancel)
=> await GetAllExtractRefreshTasksAsync<ServerResponses.ExtractRefreshTasksResponse, IServerExtractRefreshTask, IServerSchedule>(
(r, c) => ServerExtractRefreshTask.CreateManyAsync(
r,
ContentFinderFactory,
_contentCacheFactory,
c),
(r, c) => ServerExtractRefreshTask.CreateManyAsync(r, ContentFinderFactory, _contentCacheFactory, Logger, SharedResourcesLocalizer, c),
cancel)
.ConfigureAwait(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Tableau.Migration.Api.Rest.Models.Responses;
using Tableau.Migration.Api.Rest.Models.Responses.Cloud;
using Tableau.Migration.Content.Search;
using Tableau.Migration.Resources;

namespace Tableau.Migration.Content.Schedules.Cloud
{
Expand All @@ -34,54 +36,33 @@ internal CloudExtractRefreshTask(
ExtractRefreshContentType contentType,
IContentReference contentReference,
ICloudSchedule schedule)
: base(
extractRefreshId,
type,
contentType,
contentReference,
schedule)
: base(extractRefreshId, type, contentType, contentReference, schedule)
{ }

public static async Task<IImmutableList<ICloudExtractRefreshTask>> CreateManyAsync(
ExtractRefreshTasksResponse? response,
ExtractRefreshTasksResponse response,
IContentReferenceFinderFactory finderFactory,
ILogger logger, ISharedResourcesLocalizer localizer,
CancellationToken cancel)
=> await CreateManyAsync(
response,
response => response.Items.ExceptNulls(i => i.ExtractRefresh),
(r, c, cnl) => Task.FromResult(Create(r, r.Schedule, c)),
finderFactory,
finderFactory, logger, localizer,
cancel)
.ConfigureAwait(false);

public static async Task<ICloudExtractRefreshTask> CreateAsync(
ICloudExtractRefreshType? response,
ICloudScheduleType? schedule,
IContentReferenceFinderFactory finderFactory,
CancellationToken cancel)
=> await CreateAsync(
response,
finderFactory,
(r, c, cnl) => Task.FromResult(Create(r, schedule, c)),
cancel)
.ConfigureAwait(false);

private static ICloudExtractRefreshTask Create(
IExtractRefreshType? response,
ICloudScheduleType? schedule,
public static ICloudExtractRefreshTask Create(
IExtractRefreshType response,
ICloudScheduleType schedule,
IContentReference content)
{
Guard.AgainstNull(response, nameof(response));

return new CloudExtractRefreshTask(
response.Id,
response.Type!,
response.GetContentType(),
content,
new CloudSchedule(
Guard.AgainstNull(
schedule,
() => schedule)));
new CloudSchedule(schedule));
}
}
}
72 changes: 31 additions & 41 deletions src/Tableau.Migration/Content/Schedules/ExtractRefreshTaskBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Tableau.Migration.Api;
using Microsoft.Extensions.Logging;
using Tableau.Migration.Api.Rest.Models;
using Tableau.Migration.Api.Rest.Models.Responses;
using Tableau.Migration.Content.Search;
using Tableau.Migration.Resources;

namespace Tableau.Migration.Content.Schedules
{
Expand All @@ -32,8 +33,11 @@ internal abstract class ExtractRefreshTaskBase<TSchedule> :
where TSchedule : ISchedule
{
public string Type { get; set; }

public ExtractRefreshContentType ContentType { get; set; }

public IContentReference Content { get; set; }

public TSchedule Schedule { get; }

protected ExtractRefreshTaskBase(
Expand All @@ -54,57 +58,43 @@ protected ExtractRefreshTaskBase(
Schedule = schedule;
}

protected static async Task<TExtractRefreshTask> CreateAsync<TExtractRefreshType, TExtractRefreshTask>(
TExtractRefreshType? response,
IContentReferenceFinderFactory finderFactory,
Func<TExtractRefreshType, IContentReference, CancellationToken, Task<TExtractRefreshTask>> modelFactory,
CancellationToken cancel)
where TExtractRefreshType : class, IExtractRefreshType
where TExtractRefreshTask: IExtractRefreshTask<TSchedule>
{
Guard.AgainstNull(response, nameof(response));

var contentReference = await finderFactory
.FindExtractRefreshContentAsync(
response.GetContentType(),
response.GetContentId(),
cancel)
.ConfigureAwait(false);

var model = await modelFactory(
response,
contentReference,
cancel)
.ConfigureAwait(false);

return model;
}

protected static async Task<IImmutableList<TExtractRefreshTask>> CreateManyAsync<TResponse,TExtractRefreshType, TExtractRefreshTask>(
TResponse? response,
protected static async Task<IImmutableList<TExtractRefreshTask>> CreateManyAsync<TResponse, TExtractRefreshType, TExtractRefreshTask>(
TResponse response,
Func<TResponse, IEnumerable<TExtractRefreshType?>> responseItemFactory,
Func<TExtractRefreshType, IContentReference, CancellationToken, Task<TExtractRefreshTask>> modelFactory,
IContentReferenceFinderFactory finderFactory,
ILogger logger, ISharedResourcesLocalizer localizer,
CancellationToken cancel)
where TResponse : ITableauServerResponse
where TExtractRefreshType : class, IExtractRefreshType
where TExtractRefreshTask: IExtractRefreshTask<TSchedule>
{
Guard.AgainstNull(response, nameof(response));

var tasks = ImmutableArray.CreateBuilder<TExtractRefreshTask>();

var items = responseItemFactory(response).ExceptNulls();
var items = responseItemFactory(response).ExceptNulls().ToImmutableArray();
var tasks = ImmutableArray.CreateBuilder<TExtractRefreshTask>(items.Length);

foreach (var item in items)
{
tasks.Add(
await CreateAsync(
item,
finderFactory,
modelFactory,
cancel)
.ConfigureAwait(false));
var contentType = item.GetContentType();

if(contentType is ExtractRefreshContentType.Unknown)
{
logger.LogWarning(localizer[SharedResourceKeys.UnknownExtractRefreshContentTypeWarning], item.Id);
continue;
}

var finder = finderFactory.ForExtractRefreshContent(contentType);
var contentReference = await finder.FindByIdAsync(item.GetContentId(), cancel).ConfigureAwait(false);

/*
* Content reference is null when the referenced content item (e.g. workbook/data source)
* is in a private space or other "pre-manifest" filter.
*
* We similarly filter out those extract refresh tasks.
*/
if(contentReference is not null)
{
tasks.Add(await modelFactory(item, contentReference, cancel).ConfigureAwait(false));
}
}

return tasks.ToImmutable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Tableau.Migration.Api.Rest.Models.Responses;
using Tableau.Migration.Api.Rest.Models.Responses.Server;
using Tableau.Migration.Content.Search;
using Tableau.Migration.Resources;

namespace Tableau.Migration.Content.Schedules.Server
{
Expand All @@ -47,26 +49,25 @@ internal ServerExtractRefreshTask(
{ }

public static async Task<IImmutableList<IServerExtractRefreshTask>> CreateManyAsync(
ExtractRefreshTasksResponse? response,
ExtractRefreshTasksResponse response,
IContentReferenceFinderFactory finderFactory,
IContentCacheFactory contentCacheFactory,
ILogger logger, ISharedResourcesLocalizer localizer,
CancellationToken cancel)
=> await CreateManyAsync(
response,
response => response.Items.ExceptNulls(i => i.ExtractRefresh),
async (r, c, cnl) => await CreateAsync(r, c, contentCacheFactory, cnl).ConfigureAwait(false),
finderFactory,
finderFactory, logger, localizer,
cancel)
.ConfigureAwait(false);

private static async Task<IServerExtractRefreshTask> CreateAsync(
IServerExtractRefreshType? response,
IServerExtractRefreshType response,
IContentReference content,
IContentCacheFactory contentCacheFactory,
CancellationToken cancel)
{
Guard.AgainstNull(response, nameof(response));

var scheduleCache = contentCacheFactory.ForContentType<IServerSchedule>(true);

var schedule = await scheduleCache.ForIdAsync(response.Schedule.Id, cancel).ConfigureAwait(false);
Expand Down
2 changes: 2 additions & 0 deletions src/Tableau.Migration/Resources/SharedResourceKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,7 @@ internal static class SharedResourceKeys
public const string UserWithCustomViewDefaultSkippedMissingReferenceWarning = "UserWithCustomViewDefaultSkippedMissingReferenceWarning";

public const string DuplicateContentTypeConfigurationMessage = "DuplicateContentTypeConfigurationMessage";

public const string UnknownExtractRefreshContentTypeWarning = "UnknownExtractRefreshContentTypeWarning";
}
}
3 changes: 3 additions & 0 deletions src/Tableau.Migration/Resources/SharedResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,7 @@ Owner with ID {OwnerID}: {owner}</value>
<data name="DuplicateContentTypeConfigurationMessage" xml:space="preserve">
<value>Duplicate content type configuration found for content type {0}.</value>
</data>
<data name="UnknownExtractRefreshContentTypeWarning" xml:space="preserve">
<value>The extract refresh task with ID {TaskId} references an unknown content type. The task will be ignored.</value>
</data>
</root>
Loading
Loading