Merge branch 'feature/elsa-2.0' into elsa-2.0/stencil-workflow-instances-list

This commit is contained in:
Sipke Schoorstra 2021-04-09 17:01:51 +02:00
commit ed7eb136f5
8 changed files with 116 additions and 8 deletions

View file

@ -15,6 +15,7 @@ version: 2.0.0-preview7.{build}
services:
- mongodb
- postgresql101
init:
- cmd: git config --global core.autocrlf true
@ -89,6 +90,16 @@ build_script:
dotnet build
before_test:
- cmd: >-
SET PGUSER=postgres
SET PGPASSWORD=Password12!
PATH=C:\Program Files\PostgreSQL\10\bin\;%PATH%
createdb "elsa-yessql"
test_script:
- ps: dotnet test --collect:"XPlat Code Coverage" --logger:xunit -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover

View file

@ -15,14 +15,8 @@
<ItemGroup>
<PackageReference Include="YesSql.Core" Version="3.0.2" />
<PackageReference Include="YesSql.Provider.Sqlite" Version="3.0.2" />
<PackageReference Include="YesSql.Provider.PostgreSql" Version="3.0.2" />
</ItemGroup>
<!-- <ItemGroup>-->
<!-- <ProjectReference Include="..\..\..\..\..\..\yessql\src\YesSql.Abstractions\YesSql.Abstractions.csproj" />-->
<!-- <ProjectReference Include="..\..\..\..\..\..\yessql\src\YesSql.Core\YesSql.Core.csproj" />-->
<!-- <ProjectReference Include="..\..\..\..\..\..\yessql\src\YesSql.Provider.Common\YesSql.Provider.Common.csproj" />-->
<!-- <ProjectReference Include="..\..\..\..\..\..\yessql\src\YesSql.Provider.Sqlite\YesSql.Provider.Sqlite.csproj" />-->
<!-- </ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj" />

View file

@ -30,7 +30,7 @@ namespace Elsa.Persistence.YesSql
.Column<string?>(nameof(WorkflowInstanceIndex.ContextId))
.Column<string?>(nameof(WorkflowInstanceIndex.ContextType))
.Column<string?>(nameof(WorkflowInstanceIndex.Name))
.Column<string>(nameof(WorkflowInstanceIndex.WorkflowStatus))
.Column<int>(nameof(WorkflowInstanceIndex.WorkflowStatus))
.Column<DateTime>(nameof(WorkflowInstanceIndex.CreatedAt))
.Column<DateTime>(nameof(WorkflowInstanceIndex.LastExecutedAt))
.Column<DateTime>(nameof(WorkflowInstanceIndex.FinishedAt))

View file

@ -53,6 +53,25 @@ namespace Elsa.Persistence.YesSql.Services
_logger.LogError(ex, "Could not run migrations automatically on '{FeatureName}'", migration);
}
}
try
{
var commitTask = _session.CurrentTransaction?.CommitAsync() ?? Task.CompletedTask;
await commitTask;
}
catch(InvalidOperationException)
{
// TODO: Improve on this ugly hack/workaround!
//
// The commit can throw this exception because it's already been committed. But if
// we don't explicitly commit here then it never gets committed and it's as if the
// migrations never took place!
//
// I suspect that either this method is being called more than once, or perhaps (IMO
// more likely) an async operation (somewhere) isn't being awaited. That could mean
// that the connection is closed/killed-off before the commit actually completes,
// with the effect that it doesn't happen.
}
}
public async Task<IEnumerable<IDataMigration>> GetMigrationsThatNeedUpdateAsync()

View file

@ -22,6 +22,7 @@ namespace Elsa.Persistence.YesSql.Services
await _store.InitializeCollectionAsync(CollectionNames.WorkflowDefinitions);
await _store.InitializeCollectionAsync(CollectionNames.WorkflowInstances);
await _store.InitializeCollectionAsync(CollectionNames.WorkflowExecutionLog);
await _store.InitializeCollectionAsync(CollectionNames.Bookmarks);
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using Elsa.Persistence.YesSql;
using Elsa.Testing.Shared.AutoFixture.Attributes;
using Elsa.Testing.Shared.Helpers;
using YesSql;
using YesSql.Provider.PostgreSql;
namespace Elsa.Core.IntegrationTests.Autofixture
{
public class WithPostgresYesSqlAttribute : ElsaHostBuilderBuilderCustomizeAttributeBase
{
/// <summary>
/// This password matches the password which is used by AppVeyor: https://www.appveyor.com/docs/services-databases/#postgresql
/// </summary>
/// <remarks>
/// <para>
/// We could do something more sophisticated with the password than keep it in a constant, but since
/// this is (so far) the only place where we configure Postgres. There aren't any plans to do anything
/// with it in the foreseeable future either, so we can defer that until then.
/// </para>
/// </remarks>
internal const string PostgresPassword = "Password12!";
public override Action<ElsaHostBuilderBuilder> GetBuilderCustomizer()
{
return builder => {
builder.ElsaCallbacks.Add(elsa => {
elsa.UseYesSqlPersistence((IServiceProvider services, IConfiguration config) => {
config.UsePostgreSql($"Host=localhost;Database=elsa-yessql;User ID=postgres;Password={PostgresPassword}");
});
});
};
}
}
}

View file

@ -25,6 +25,7 @@
</PackageReference>
<PackageReference Include="YesSql.Core" Version="3.0.2" />
<PackageReference Include="YesSql.Provider.Sqlite" Version="3.0.2" />
<PackageReference Include="YesSql.Provider.PostgreSql" Version="3.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.20" />
<PackageReference Include="Hangfire.InMemory" Version="0.3.4" />

View file

@ -0,0 +1,47 @@
using System.Threading;
using System.Threading.Tasks;
using Elsa.Core.IntegrationTests.Autofixture;
using Elsa.Core.IntegrationTests.Workflows;
using Elsa.Persistence;
using Elsa.Services;
using Elsa.Testing.Shared;
using Elsa.Testing.Shared.Helpers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Xunit;
namespace Elsa.Core.IntegrationTests.Persistence.YesSql
{
public class PostgresSqlYesSqlIntegrationTests
{
[Theory(DisplayName = "A persistable workflow instance with default persistence behaviour should be persisted-to and readable-from a YesSQL/PostgreSql store after being run"), AutoMoqData]
public async Task APersistableWorkflowInstanceWithDefaultPersistanceBehaviourShouldBeRoundTrippable([WithPersistableWorkflow,WithPostgresYesSql] ElsaHostBuilderBuilder hostBuilderBuilder)
{
var hostBuilder = hostBuilderBuilder.GetHostBuilder();
hostBuilder.ConfigureServices((ctx, services) => services.AddHostedService<HostedWorkflowRunner>());
var host = await hostBuilder.StartAsync();
}
class HostedWorkflowRunner : IHostedService
{
readonly IBuildsAndStartsWorkflow _workflowRunner;
readonly IWorkflowInstanceStore _instanceStore;
public async Task StartAsync(CancellationToken cancellationToken)
{
var instance = await _workflowRunner.BuildAndStartWorkflowAsync<PersistableWorkflow>(cancellationToken: cancellationToken);
var retrievedInstance = await _instanceStore.FindByIdAsync(instance.Id, cancellationToken);
Assert.NotNull(retrievedInstance);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public HostedWorkflowRunner(IBuildsAndStartsWorkflow workflowRunner, IWorkflowInstanceStore instanceStore)
{
_workflowRunner = workflowRunner ?? throw new System.ArgumentNullException(nameof(workflowRunner));
_instanceStore = instanceStore ?? throw new System.ArgumentNullException(nameof(instanceStore));
}
}
}
}