Add key value store

This commit is contained in:
Raymond den Haan 2024-02-02 11:21:29 +01:00
parent 3b66d7edbb
commit f1ddea1c95
27 changed files with 1663 additions and 6 deletions

View file

@ -0,0 +1,25 @@
using FluentMigrator;
using JetBrains.Annotations;
namespace Elsa.Dapper.Migrations.Runtime;
/// <inheritdoc />
[Migration(20002, "Elsa:Runtime:AddKeyValueStore")]
[PublicAPI]
public class AddKeyValueStore : Migration
{
/// <inheritdoc />
public override void Up()
{
Create
.Table("KeyValuePairs")
.WithColumn("Key").AsString().PrimaryKey()
.WithColumn("Value").AsString().NotNullable();
}
/// <inheritdoc />
public override void Down()
{
Delete.Table("KeyValuePairs");
}
}

View file

@ -31,6 +31,7 @@ public class DapperWorkflowRuntimePersistenceFeature : FeatureBase
feature.WorkflowInboxStore = sp => sp.GetRequiredService<DapperWorkflowInboxMessageStore>();
feature.WorkflowExecutionLogStore = sp => sp.GetRequiredService<DapperWorkflowExecutionLogStore>();
feature.ActivityExecutionLogStore = sp => sp.GetRequiredService<DapperActivityExecutionRecordStore>();
feature.KeyValueStore = sp => sp.GetRequiredService<DapperKeyValueStore>();
});
}
@ -44,5 +45,6 @@ public class DapperWorkflowRuntimePersistenceFeature : FeatureBase
Services.AddScoped<DapperWorkflowInboxMessageStore>();
Services.AddScoped<DapperWorkflowExecutionLogStore>();
Services.AddScoped<DapperActivityExecutionRecordStore>();
Services.AddScoped<DapperKeyValueStore>();
}
}

View file

@ -0,0 +1,7 @@
namespace Elsa.Dapper.Modules.Runtime.Records;
public class KeyValuePairRecord
{
public string Key { get; set; } = default!;
public string Value { get; set; } = default!;
}

View file

@ -0,0 +1,64 @@
using Elsa.Dapper.Contracts;
using Elsa.Dapper.Extensions;
using Elsa.Dapper.Modules.Runtime.Records;
using Elsa.Dapper.Services;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Dapper.Modules.Runtime.Stores;
/// <summary>
/// A Dapper implementation of <see cref="IKeyValueStore"/>.
/// </summary>
public class DapperKeyValueStore : IKeyValueStore
{
private const string TableName = "Users";
private const string PrimaryKeyName = "Key";
private readonly Store<KeyValuePairRecord> _store;
/// <summary>
/// Initializes a new instance of <see cref="DapperKeyValueStore"/>.
/// </summary>
public DapperKeyValueStore(IDbConnectionProvider dbConnectionProvider)
{
_store = new Store<KeyValuePairRecord>(dbConnectionProvider, TableName, PrimaryKeyName);
}
/// <inheritdoc />
public Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken)
{
var record = Map(keyValuePair);
return _store.SaveAsync(record, PrimaryKeyName, cancellationToken);
}
/// <inheritdoc />
public async Task<SerializedKeyValuePair?> GetValue(string key, CancellationToken cancellationToken)
{
var record = await _store.FindAsync(query => query.Is(nameof(KeyValuePairRecord.Key), key), cancellationToken);
return record == null ? null : Map(record);
}
/// <inheritdoc />
public Task DeleteAsync(string key, CancellationToken cancellationToken)
{
return _store.DeleteAsync(query => query.Is(nameof(KeyValuePairRecord.Key), key), cancellationToken);
}
private KeyValuePairRecord Map(SerializedKeyValuePair kvp)
{
return new()
{
Key = kvp.Key,
Value = kvp.SerializedValue
};
}
private SerializedKeyValuePair Map(KeyValuePairRecord kvp)
{
return new()
{
Key = kvp.Key,
SerializedValue = kvp.Value
};
}
}

View file

@ -0,0 +1,405 @@
// <auto-generated />
using System;
using Elsa.EntityFrameworkCore.Modules.Runtime;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime
{
[DbContext(typeof(RuntimeElsaDbContext))]
[Migration("20240202095704_AddKeyValueStore")]
partial class AddKeyValueStore
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("ActivityName")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityNodeId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("ActivityType")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("ActivityTypeVersion")
.HasColumnType("int");
b.Property<DateTimeOffset?>("CompletedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("HasBookmarks")
.HasColumnType("tinyint(1)");
b.Property<string>("SerializedActivityState")
.HasColumnType("longtext");
b.Property<string>("SerializedException")
.HasColumnType("longtext");
b.Property<string>("SerializedOutputs")
.HasColumnType("longtext");
b.Property<string>("SerializedPayload")
.HasColumnType("longtext");
b.Property<DateTimeOffset>("StartedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("ActivityId")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityId");
b.HasIndex("ActivityName")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityName");
b.HasIndex("ActivityNodeId")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId");
b.HasIndex("ActivityType")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityType");
b.HasIndex("ActivityTypeVersion")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion");
b.HasIndex("CompletedAt")
.HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt");
b.HasIndex("HasBookmarks")
.HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks");
b.HasIndex("StartedAt")
.HasDatabaseName("IX_ActivityExecutionRecord_StartedAt");
b.HasIndex("Status")
.HasDatabaseName("IX_ActivityExecutionRecord_Status");
b.HasIndex("WorkflowInstanceId")
.HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId");
b.HasIndex("ActivityType", "ActivityTypeVersion")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion");
b.ToTable("ActivityExecutionRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.SerializedKeyValuePair", b =>
{
b.Property<string>("Key")
.HasColumnType("varchar(255)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("SerializedValue")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Key");
b.ToTable("KeyValuePairs", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b =>
{
b.Property<string>("BookmarkId")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityInstanceId")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityTypeName")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("CorrelationId")
.HasColumnType("longtext");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Hash")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("SerializedMetadata")
.HasColumnType("longtext");
b.Property<string>("SerializedPayload")
.HasColumnType("longtext");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("BookmarkId");
b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId");
b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName");
b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash");
b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId");
b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt");
b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash");
b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId");
b.ToTable("Bookmarks", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Hash")
.HasColumnType("varchar(255)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("SerializedPayload")
.HasColumnType("longtext");
b.Property<string>("WorkflowDefinitionId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("WorkflowDefinitionVersionId")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Hash")
.HasDatabaseName("IX_StoredTrigger_Hash");
b.HasIndex("Name")
.HasDatabaseName("IX_StoredTrigger_Name");
b.HasIndex("WorkflowDefinitionId")
.HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId");
b.HasIndex("WorkflowDefinitionVersionId")
.HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId");
b.ToTable("Triggers", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("ActivityInstanceId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("ActivityName")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityNodeId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("ActivityType")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("ActivityTypeVersion")
.HasColumnType("int");
b.Property<string>("EventName")
.HasColumnType("varchar(255)");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<string>("ParentActivityInstanceId")
.HasColumnType("varchar(255)");
b.Property<long>("Sequence")
.HasColumnType("bigint");
b.Property<string>("SerializedActivityState")
.HasColumnType("longtext");
b.Property<string>("SerializedPayload")
.HasColumnType("longtext");
b.Property<string>("Source")
.HasColumnType("longtext");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetime(6)");
b.Property<string>("WorkflowDefinitionId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("WorkflowDefinitionVersionId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("WorkflowVersion")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ActivityId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId");
b.HasIndex("ActivityInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId");
b.HasIndex("ActivityName")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName");
b.HasIndex("ActivityNodeId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId");
b.HasIndex("ActivityType")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType");
b.HasIndex("ActivityTypeVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion");
b.HasIndex("EventName")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName");
b.HasIndex("ParentActivityInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId");
b.HasIndex("Sequence")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence");
b.HasIndex("Timestamp")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp");
b.HasIndex("WorkflowDefinitionId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId");
b.HasIndex("WorkflowDefinitionVersionId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId");
b.HasIndex("WorkflowInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId");
b.HasIndex("WorkflowVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion");
b.HasIndex("ActivityType", "ActivityTypeVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion");
b.HasIndex("Timestamp", "Sequence")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence");
b.ToTable("WorkflowExecutionLogRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityInstanceId")
.HasColumnType("varchar(255)");
b.Property<string>("ActivityTypeName")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("CorrelationId")
.HasColumnType("varchar(255)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetime(6)");
b.Property<string>("Hash")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<string>("SerializedBookmarkPayload")
.HasColumnType("longtext");
b.Property<string>("SerializedInput")
.HasColumnType("longtext");
b.Property<string>("WorkflowInstanceId")
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId");
b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName");
b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId");
b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt");
b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt");
b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash");
b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId");
b.ToTable("WorkflowInboxMessages", "Elsa");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,41 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime
{
/// <inheritdoc />
public partial class AddKeyValueStore : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "KeyValuePairs",
schema: "Elsa",
columns: table => new
{
Key = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
SerializedValue = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_KeyValuePairs", x => x.Key);
})
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "KeyValuePairs",
schema: "Elsa");
}
}
}

View file

@ -17,7 +17,7 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.11")
.HasAnnotation("ProductVersion", "7.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b =>
@ -110,6 +110,26 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Runtime
b.ToTable("ActivityExecutionRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.SerializedKeyValuePair", b =>
{
b.Property<string>("Key")
.HasColumnType("varchar(255)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("SerializedValue")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Key");
b.ToTable("KeyValuePairs", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b =>
{
b.Property<string>("BookmarkId")

View file

@ -0,0 +1,408 @@
// <auto-generated />
using System;
using Elsa.EntityFrameworkCore.Modules.Runtime;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime
{
[DbContext(typeof(RuntimeElsaDbContext))]
[Migration("20240202095953_AddKeyValueStore")]
partial class AddKeyValueStore
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.ActivityExecutionRecord", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ActivityName")
.HasColumnType("text");
b.Property<string>("ActivityNodeId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ActivityType")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ActivityTypeVersion")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("CompletedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("HasBookmarks")
.HasColumnType("boolean");
b.Property<string>("SerializedActivityState")
.HasColumnType("text");
b.Property<string>("SerializedException")
.HasColumnType("text");
b.Property<string>("SerializedOutputs")
.HasColumnType("text");
b.Property<string>("SerializedPayload")
.HasColumnType("text");
b.Property<DateTimeOffset>("StartedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("text");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ActivityId")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityId");
b.HasIndex("ActivityName")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityName");
b.HasIndex("ActivityNodeId")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityNodeId");
b.HasIndex("ActivityType")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityType");
b.HasIndex("ActivityTypeVersion")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityTypeVersion");
b.HasIndex("CompletedAt")
.HasDatabaseName("IX_ActivityExecutionRecord_CompletedAt");
b.HasIndex("HasBookmarks")
.HasDatabaseName("IX_ActivityExecutionRecord_HasBookmarks");
b.HasIndex("StartedAt")
.HasDatabaseName("IX_ActivityExecutionRecord_StartedAt");
b.HasIndex("Status")
.HasDatabaseName("IX_ActivityExecutionRecord_Status");
b.HasIndex("WorkflowInstanceId")
.HasDatabaseName("IX_ActivityExecutionRecord_WorkflowInstanceId");
b.HasIndex("ActivityType", "ActivityTypeVersion")
.HasDatabaseName("IX_ActivityExecutionRecord_ActivityType_ActivityTypeVersion");
b.ToTable("ActivityExecutionRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.SerializedKeyValuePair", b =>
{
b.Property<string>("Key")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("SerializedValue")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Key");
b.ToTable("KeyValuePairs", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b =>
{
b.Property<string>("BookmarkId")
.HasColumnType("text");
b.Property<string>("ActivityInstanceId")
.HasColumnType("text");
b.Property<string>("ActivityTypeName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Hash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SerializedMetadata")
.HasColumnType("text");
b.Property<string>("SerializedPayload")
.HasColumnType("text");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("text");
b.HasKey("BookmarkId");
b.HasIndex(new[] { "ActivityInstanceId" }, "IX_StoredBookmark_ActivityInstanceId");
b.HasIndex(new[] { "ActivityTypeName" }, "IX_StoredBookmark_ActivityTypeName");
b.HasIndex(new[] { "ActivityTypeName", "Hash" }, "IX_StoredBookmark_ActivityTypeName_Hash");
b.HasIndex(new[] { "ActivityTypeName", "Hash", "WorkflowInstanceId" }, "IX_StoredBookmark_ActivityTypeName_Hash_WorkflowInstanceId");
b.HasIndex(new[] { "CreatedAt" }, "IX_StoredBookmark_CreatedAt");
b.HasIndex(new[] { "Hash" }, "IX_StoredBookmark_Hash");
b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_StoredBookmark_WorkflowInstanceId");
b.ToTable("Bookmarks", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredTrigger", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Hash")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SerializedPayload")
.HasColumnType("text");
b.Property<string>("WorkflowDefinitionId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("WorkflowDefinitionVersionId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Hash")
.HasDatabaseName("IX_StoredTrigger_Hash");
b.HasIndex("Name")
.HasDatabaseName("IX_StoredTrigger_Name");
b.HasIndex("WorkflowDefinitionId")
.HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionId");
b.HasIndex("WorkflowDefinitionVersionId")
.HasDatabaseName("IX_StoredTrigger_WorkflowDefinitionVersionId");
b.ToTable("Triggers", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowExecutionLogRecord", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ActivityId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ActivityInstanceId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ActivityName")
.HasColumnType("text");
b.Property<string>("ActivityNodeId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ActivityType")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ActivityTypeVersion")
.HasColumnType("integer");
b.Property<string>("EventName")
.HasColumnType("text");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("ParentActivityInstanceId")
.HasColumnType("text");
b.Property<long>("Sequence")
.HasColumnType("bigint");
b.Property<string>("SerializedActivityState")
.HasColumnType("text");
b.Property<string>("SerializedPayload")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("timestamp with time zone");
b.Property<string>("WorkflowDefinitionId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("WorkflowDefinitionVersionId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("WorkflowInstanceId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("WorkflowVersion")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ActivityId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityId");
b.HasIndex("ActivityInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityInstanceId");
b.HasIndex("ActivityName")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityName");
b.HasIndex("ActivityNodeId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityNodeId");
b.HasIndex("ActivityType")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType");
b.HasIndex("ActivityTypeVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityTypeVersion");
b.HasIndex("EventName")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_EventName");
b.HasIndex("ParentActivityInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ParentActivityInstanceId");
b.HasIndex("Sequence")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Sequence");
b.HasIndex("Timestamp")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp");
b.HasIndex("WorkflowDefinitionId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionId");
b.HasIndex("WorkflowDefinitionVersionId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowDefinitionVersionId");
b.HasIndex("WorkflowInstanceId")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowInstanceId");
b.HasIndex("WorkflowVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_WorkflowVersion");
b.HasIndex("ActivityType", "ActivityTypeVersion")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_ActivityType_ActivityTypeVersion");
b.HasIndex("Timestamp", "Sequence")
.HasDatabaseName("IX_WorkflowExecutionLogRecord_Timestamp_Sequence");
b.ToTable("WorkflowExecutionLogRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.WorkflowInboxMessage", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ActivityInstanceId")
.HasColumnType("text");
b.Property<string>("ActivityTypeName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Hash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SerializedBookmarkPayload")
.HasColumnType("text");
b.Property<string>("SerializedInput")
.HasColumnType("text");
b.Property<string>("WorkflowInstanceId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex(new[] { "ActivityInstanceId" }, "IX_WorkflowInboxMessage_ActivityInstanceId");
b.HasIndex(new[] { "ActivityTypeName" }, "IX_WorkflowInboxMessage_ActivityTypeName");
b.HasIndex(new[] { "CorrelationId" }, "IX_WorkflowInboxMessage_CorrelationId");
b.HasIndex(new[] { "CreatedAt" }, "IX_WorkflowInboxMessage_CreatedAt");
b.HasIndex(new[] { "ExpiresAt" }, "IX_WorkflowInboxMessage_ExpiresAt");
b.HasIndex(new[] { "Hash" }, "IX_WorkflowInboxMessage_Hash");
b.HasIndex(new[] { "WorkflowInstanceId" }, "IX_WorkflowInboxMessage_WorkflowInstanceId");
b.ToTable("WorkflowInboxMessages", "Elsa");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime
{
/// <inheritdoc />
public partial class AddKeyValueStore : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "KeyValuePairs",
schema: "Elsa",
columns: table => new
{
Key = table.Column<string>(type: "text", nullable: false),
SerializedValue = table.Column<string>(type: "text", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_KeyValuePairs", x => x.Key);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "KeyValuePairs",
schema: "Elsa");
}
}
}

View file

@ -18,7 +18,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.11")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@ -113,6 +113,26 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Runtime
b.ToTable("ActivityExecutionRecords", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.SerializedKeyValuePair", b =>
{
b.Property<string>("Key")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("SerializedValue")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Key");
b.ToTable("KeyValuePairs", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Runtime.Entities.StoredBookmark", b =>
{
b.Property<string>("BookmarkId")

View file

@ -18,7 +18,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.11")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);

View file

@ -0,0 +1,196 @@
// <auto-generated />
using System;
using Elsa.EntityFrameworkCore.Modules.Management;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20240202100123_AddKeyValueStore")]
partial class AddKeyValueStore
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Elsa")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<byte[]>("BinaryData")
.HasColumnType("varbinary(max)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Data")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefinitionId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsLatest")
.HasColumnType("bit");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<bool>("IsReadonly")
.HasColumnType("bit");
b.Property<string>("MaterializerContext")
.HasColumnType("nvarchar(max)");
b.Property<string>("MaterializerName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderName")
.HasColumnType("nvarchar(max)");
b.Property<string>("StringData")
.HasColumnType("nvarchar(max)");
b.Property<string>("ToolVersion")
.HasColumnType("nvarchar(max)");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("bit");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("IsLatest")
.HasDatabaseName("IX_WorkflowDefinition_IsLatest");
b.HasIndex("IsPublished")
.HasDatabaseName("IX_WorkflowDefinition_IsPublished");
b.HasIndex("Name")
.HasDatabaseName("IX_WorkflowDefinition_Name");
b.HasIndex("UsableAsActivity")
.HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity");
b.HasIndex("Version")
.HasDatabaseName("IX_WorkflowDefinition_Version");
b.HasIndex("DefinitionId", "Version")
.IsUnique()
.HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version");
b.ToTable("WorkflowDefinitions", "Elsa");
});
modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("CorrelationId")
.HasColumnType("nvarchar(450)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Data")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefinitionId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<string>("DefinitionVersionId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset?>("FinishedAt")
.HasColumnType("datetimeoffset");
b.Property<int>("IncidentCount")
.HasColumnType("int");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<string>("SubStatus")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CorrelationId")
.HasDatabaseName("IX_WorkflowInstance_CorrelationId");
b.HasIndex("CreatedAt")
.HasDatabaseName("IX_WorkflowInstance_CreatedAt");
b.HasIndex("DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_DefinitionId");
b.HasIndex("FinishedAt")
.HasDatabaseName("IX_WorkflowInstance_FinishedAt");
b.HasIndex("Name")
.HasDatabaseName("IX_WorkflowInstance_Name");
b.HasIndex("Status")
.HasDatabaseName("IX_WorkflowInstance_Status");
b.HasIndex("SubStatus")
.HasDatabaseName("IX_WorkflowInstance_SubStatus");
b.HasIndex("UpdatedAt")
.HasDatabaseName("IX_WorkflowInstance_UpdatedAt");
b.HasIndex("Status", "DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId");
b.HasIndex("Status", "SubStatus")
.HasDatabaseName("IX_WorkflowInstance_Status_SubStatus");
b.HasIndex("SubStatus", "DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId");
b.HasIndex("Status", "SubStatus", "DefinitionId", "Version")
.HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version");
b.ToTable("WorkflowInstances", "Elsa");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Runtime
{
/// <inheritdoc />
public partial class AddKeyValueStore : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View file

@ -15,7 +15,7 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.11");
modelBuilder.HasAnnotation("ProductVersion", "7.0.14");
modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b =>
{

View file

@ -0,0 +1,193 @@
// <auto-generated />
using System;
using Elsa.EntityFrameworkCore.Modules.Management;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20240202100045_AddKeyValueStore")]
partial class AddKeyValueStore
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.14");
modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowDefinition", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<byte[]>("BinaryData")
.HasColumnType("BLOB");
b.Property<string>("CreatedAt")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Data")
.HasColumnType("TEXT");
b.Property<string>("DefinitionId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<bool>("IsLatest")
.HasColumnType("INTEGER");
b.Property<bool>("IsPublished")
.HasColumnType("INTEGER");
b.Property<bool>("IsReadonly")
.HasColumnType("INTEGER");
b.Property<string>("MaterializerContext")
.HasColumnType("TEXT");
b.Property<string>("MaterializerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<string>("ProviderName")
.HasColumnType("TEXT");
b.Property<string>("StringData")
.HasColumnType("TEXT");
b.Property<string>("ToolVersion")
.HasColumnType("TEXT");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("INTEGER");
b.Property<int>("Version")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("IsLatest")
.HasDatabaseName("IX_WorkflowDefinition_IsLatest");
b.HasIndex("IsPublished")
.HasDatabaseName("IX_WorkflowDefinition_IsPublished");
b.HasIndex("Name")
.HasDatabaseName("IX_WorkflowDefinition_Name");
b.HasIndex("UsableAsActivity")
.HasDatabaseName("IX_WorkflowDefinition_UsableAsActivity");
b.HasIndex("Version")
.HasDatabaseName("IX_WorkflowDefinition_Version");
b.HasIndex("DefinitionId", "Version")
.IsUnique()
.HasDatabaseName("IX_WorkflowDefinition_DefinitionId_Version");
b.ToTable("WorkflowDefinitions");
});
modelBuilder.Entity("Elsa.Workflows.Management.Entities.WorkflowInstance", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("CorrelationId")
.HasColumnType("TEXT");
b.Property<string>("CreatedAt")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Data")
.HasColumnType("TEXT");
b.Property<string>("DefinitionId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DefinitionVersionId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FinishedAt")
.HasColumnType("TEXT");
b.Property<int>("IncidentCount")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("SubStatus")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("UpdatedAt")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Version")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CorrelationId")
.HasDatabaseName("IX_WorkflowInstance_CorrelationId");
b.HasIndex("CreatedAt")
.HasDatabaseName("IX_WorkflowInstance_CreatedAt");
b.HasIndex("DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_DefinitionId");
b.HasIndex("FinishedAt")
.HasDatabaseName("IX_WorkflowInstance_FinishedAt");
b.HasIndex("Name")
.HasDatabaseName("IX_WorkflowInstance_Name");
b.HasIndex("Status")
.HasDatabaseName("IX_WorkflowInstance_Status");
b.HasIndex("SubStatus")
.HasDatabaseName("IX_WorkflowInstance_SubStatus");
b.HasIndex("UpdatedAt")
.HasDatabaseName("IX_WorkflowInstance_UpdatedAt");
b.HasIndex("Status", "DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_Status_DefinitionId");
b.HasIndex("Status", "SubStatus")
.HasDatabaseName("IX_WorkflowInstance_Status_SubStatus");
b.HasIndex("SubStatus", "DefinitionId")
.HasDatabaseName("IX_WorkflowInstance_SubStatus_DefinitionId");
b.HasIndex("Status", "SubStatus", "DefinitionId", "Version")
.HasDatabaseName("IX_WorkflowInstance_Status_SubStatus_DefinitionId_Version");
b.ToTable("WorkflowInstances");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Runtime
{
/// <inheritdoc />
public partial class AddKeyValueStore : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View file

@ -12,7 +12,8 @@ public class Configurations :
IEntityTypeConfiguration<WorkflowExecutionLogRecord>,
IEntityTypeConfiguration<ActivityExecutionRecord>,
IEntityTypeConfiguration<StoredBookmark>,
IEntityTypeConfiguration<WorkflowInboxMessage>
IEntityTypeConfiguration<WorkflowInboxMessage>,
IEntityTypeConfiguration<SerializedKeyValuePair>
{
/// <inheritdoc />
public void Configure(EntityTypeBuilder<StoredTrigger> builder)
@ -109,4 +110,10 @@ public class Configurations :
builder.HasIndex(x => x.CreatedAt, $"IX_{nameof(WorkflowInboxMessage)}_{nameof(WorkflowInboxMessage.CreatedAt)}");
builder.HasIndex(x => x.ExpiresAt, $"IX_{nameof(WorkflowInboxMessage)}_{nameof(WorkflowInboxMessage.ExpiresAt)}");
}
/// <inheritdoc />
public void Configure(EntityTypeBuilder<SerializedKeyValuePair> builder)
{
builder.HasKey(x => x.Key);
}
}

View file

@ -38,6 +38,11 @@ public class RuntimeElsaDbContext : ElsaDbContextBase
/// The workflow inbox messages.
/// </summary>
public DbSet<WorkflowInboxMessage> WorkflowInboxMessages { get; set; } = default!;
/// <summary>
/// The generic key value pairs.
/// </summary>
public DbSet<SerializedKeyValuePair> KeyValuePairs { get; set; } = default!;
/// <inheritdoc />
protected override void ApplyEntityConfigurations(ModelBuilder modelBuilder)
@ -48,6 +53,7 @@ public class RuntimeElsaDbContext : ElsaDbContextBase
modelBuilder.ApplyConfiguration<ActivityExecutionRecord>(config);
modelBuilder.ApplyConfiguration<StoredBookmark>(config);
modelBuilder.ApplyConfiguration<WorkflowInboxMessage>(config);
modelBuilder.ApplyConfiguration<SerializedKeyValuePair>(config);
}
/// <inheritdoc />
@ -71,5 +77,7 @@ public class RuntimeElsaDbContext : ElsaDbContextBase
modelBuilder.Entity<WorkflowInboxMessage>().Property("SerializedInput").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInboxMessage>().Property("SerializedBookmarkPayload").HasColumnType("NCLOB");
modelBuilder.Entity<SerializedKeyValuePair>().Property("Value").HasColumnType("NCLOB");
}
}

View file

@ -0,0 +1,36 @@
using Elsa.EntityFrameworkCore.Common;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.EntityFrameworkCore.Modules.Runtime;
/// <summary>
/// Entity Framework implementation of the <see cref="IKeyValueStore"/>
/// </summary>
public class EFCoreKeyValueStore : IKeyValueStore
{
private readonly Store<RuntimeElsaDbContext, SerializedKeyValuePair> _store;
public EFCoreKeyValueStore(Store<RuntimeElsaDbContext, SerializedKeyValuePair> store)
{
_store = store;
}
/// <inheritdoc />
public Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken)
{
return _store.SaveAsync(keyValuePair, x => x.Key, cancellationToken);
}
/// <inheritdoc />
public Task<SerializedKeyValuePair?> GetValue(string key, CancellationToken cancellationToken)
{
return _store.FindAsync(x => x.Key == key, cancellationToken);
}
/// <inheritdoc />
public Task DeleteAsync(string key, CancellationToken cancellationToken)
{
return _store.DeleteWhereAsync(x => x.Key == key, cancellationToken);
}
}

View file

@ -28,6 +28,7 @@ public class EFCoreWorkflowRuntimePersistenceFeature : PersistenceFeatureBase<Ru
feature.WorkflowInboxStore = sp => sp.GetRequiredService<EFCoreWorkflowInboxMessageStore>();
feature.WorkflowExecutionLogStore = sp => sp.GetRequiredService<EFCoreWorkflowExecutionLogStore>();
feature.ActivityExecutionLogStore = sp => sp.GetRequiredService<EFCoreActivityExecutionStore>();
feature.KeyValueStore = sp => sp.GetRequiredService<EFCoreKeyValueStore>();
});
}
@ -41,5 +42,6 @@ public class EFCoreWorkflowRuntimePersistenceFeature : PersistenceFeatureBase<Ru
AddEntityStore<WorkflowInboxMessage, EFCoreWorkflowInboxMessageStore>();
AddEntityStore<WorkflowExecutionLogRecord, EFCoreWorkflowExecutionLogStore>();
AddEntityStore<ActivityExecutionRecord, EFCoreActivityExecutionStore>();
AddStore<SerializedKeyValuePair, EFCoreKeyValueStore>();
}
}

View file

@ -1,3 +1,4 @@
using Elsa.Common.Entities;
using Elsa.MongoDb.Helpers;
using Elsa.Workflows.Runtime.Entities;
using Elsa.Workflows.State;
@ -23,7 +24,8 @@ internal class CreateIndices : IHostedService
CreateActivityExecutionLogIndices(cancellationToken),
CreateWorkflowBookmarkIndices(cancellationToken),
CreateWorkflowTriggerIndices(cancellationToken),
CreateWorkflowInboxIndices(cancellationToken)
CreateWorkflowInboxIndices(cancellationToken),
CreateKeyValueIndices(cancellationToken)
);
}
@ -181,4 +183,20 @@ internal class CreateIndices : IHostedService
},
cancellationToken));
}
private Task CreateKeyValueIndices(CancellationToken cancellationToken)
{
var keyValuePairCollection = _serviceProvider.GetService<IMongoCollection<SerializedKeyValuePair>>();
if (keyValuePairCollection == null) return Task.CompletedTask;
return IndexHelpers.CreateAsync(
keyValuePairCollection,
async (collection, indexBuilder) =>
await collection.Indexes.CreateManyAsync(
new List<CreateIndexModel<SerializedKeyValuePair>>
{
new(indexBuilder.Ascending(x => x.Key))
},
cancellationToken));
}
}

View file

@ -0,0 +1,39 @@
using Elsa.MongoDb.Common;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.MongoDb.Modules.Runtime;
/// <summary>
/// A MongoDB based store for <see cref="SerializedKeyValuePair"/>s.
/// </summary>
public class MongoKeyValueStore : IKeyValueStore
{
private readonly MongoDbStore<SerializedKeyValuePair> _keyValueMongoDbStore;
/// <summary>
/// Initializes a new instance of the <see cref="KeyValueStore"/> class.
/// </summary>
public MongoKeyValueStore(MongoDbStore<SerializedKeyValuePair> keyValueMongoDbStore)
{
_keyValueMongoDbStore = keyValueMongoDbStore;
}
/// <inheritdoc />
public Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken)
{
return _keyValueMongoDbStore.SaveAsync(keyValuePair, cancellationToken);
}
/// <inheritdoc />
public Task<SerializedKeyValuePair?> GetValue(string key, CancellationToken cancellationToken)
{
return _keyValueMongoDbStore.FindAsync(x => x.Key == key, cancellationToken);
}
/// <inheritdoc />
public Task DeleteAsync(string key, CancellationToken cancellationToken)
{
return _keyValueMongoDbStore.DeleteWhereAsync(x => x.Key == key, cancellationToken);
}
}

View file

@ -1,3 +1,4 @@
using Elsa.Common.Entities;
using Elsa.Features.Attributes;
using Elsa.Features.Services;
using Elsa.MongoDb.Common;
@ -28,6 +29,7 @@ public class MongoWorkflowRuntimePersistenceFeature : PersistenceFeatureBase
feature.WorkflowExecutionLogStore = sp => sp.GetRequiredService<MongoWorkflowExecutionLogStore>();
feature.ActivityExecutionLogStore = sp => sp.GetRequiredService<MongoActivityExecutionLogStore>();
feature.WorkflowInboxStore = sp => sp.GetRequiredService<MongoWorkflowInboxMessageStore>();
feature.KeyValueStore = sp => sp.GetRequiredService<MongoKeyValueStore>();
});
}
@ -41,12 +43,14 @@ public class MongoWorkflowRuntimePersistenceFeature : PersistenceFeatureBase
AddCollection<WorkflowExecutionLogRecord>("workflow_execution_logs");
AddCollection<ActivityExecutionRecord>("activity_execution_logs");
AddCollection<WorkflowInboxMessage>("workflow_inbox_messages");
AddCollection<SerializedKeyValuePair>("key_value_pairs");
AddStore<StoredTrigger, MongoTriggerStore>();
AddStore<StoredBookmark, MongoBookmarkStore>();
AddStore<WorkflowExecutionLogRecord, MongoWorkflowExecutionLogStore>();
AddStore<ActivityExecutionRecord, MongoActivityExecutionLogStore>();
AddStore<WorkflowInboxMessage, MongoWorkflowInboxMessageStore>();
AddStore<SerializedKeyValuePair, MongoKeyValueStore>();
Services.AddHostedService<CreateIndices>();
}

View file

@ -0,0 +1,25 @@
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Workflows.Runtime.Contracts;
/// <summary>
/// Store that holds key value entities not fit to store in specific stores.
/// </summary>
public interface IKeyValueStore
{
/// <summary>
/// Saves the key value pair.
/// </summary>
Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the key value pair from the store.
/// </summary>
/// <returns><see cref="SerializedKeyValuePair"/> if the key is found, otherwise null.</returns>
Task<SerializedKeyValuePair?> GetValue(string key, CancellationToken cancellationToken);
/// <summary>
/// If the key is found it deletes the record from the store.
/// </summary>
Task DeleteAsync(string key, CancellationToken cancellationToken);
}

View file

@ -0,0 +1,7 @@
namespace Elsa.Workflows.Runtime.Entities;
public class SerializedKeyValuePair
{
public string Key { get; set; }
public string SerializedValue { get; set; }
}

View file

@ -79,6 +79,11 @@ public class WorkflowRuntimeFeature : FeatureBase
/// </summary>
public Func<IServiceProvider, IWorkflowInboxMessageStore> WorkflowInboxStore { get; set; } = sp => sp.GetRequiredService<MemoryWorkflowInboxMessageStore>();
/// <summary>
/// A factory that instantiates an <see cref="IKeyValueStore"/>.
/// </summary>
public Func<IServiceProvider, IKeyValueStore> KeyValueStore { get; set; } = sp => ActivatorUtilities.CreateInstance<MemoryKeyValueStore>(sp);
/// <summary>
/// A factory that instantiates an <see cref="IWorkflowExecutionContextStore"/>.
/// </summary>
@ -174,6 +179,7 @@ public class WorkflowRuntimeFeature : FeatureBase
.AddScoped(WorkflowExecutionLogStore)
.AddScoped(ActivityExecutionLogStore)
.AddScoped(WorkflowInboxStore)
.AddScoped(KeyValueStore)
.AddScoped(WorkflowExecutionContextStore)
.AddSingleton(RunTaskDispatcher)
.AddSingleton(BackgroundActivityScheduler)

View file

@ -0,0 +1,42 @@
using Elsa.Common.Services;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Workflows.Runtime.Stores;
/// <summary>
/// Stores key value records in memory.
/// </summary>
public class MemoryKeyValueStore : IKeyValueStore
{
private readonly MemoryStore<SerializedKeyValuePair> _store;
/// <summary>
/// Initializes a new instance of the <see cref="MemoryActivityExecutionStore"/> class.
/// </summary>
public MemoryKeyValueStore(MemoryStore<SerializedKeyValuePair> store)
{
_store = store;
}
/// <inheritdoc />
public Task SaveAsync(SerializedKeyValuePair keyValuePair, CancellationToken cancellationToken)
{
_store.Save(keyValuePair, kv => kv.Key);
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<SerializedKeyValuePair?> GetValue(string key, CancellationToken cancellationToken)
{
var result = _store.Find(x => x.Key == key);
return Task.FromResult(result);
}
/// <inheritdoc />
public Task DeleteAsync(string key, CancellationToken cancellationToken)
{
_store.DeleteWhere(x => x.Key == key);
return Task.CompletedTask;
}
}