Split common data model to its own project

This commit is contained in:
Gregorius Soedharmo 2022-11-03 01:14:04 +07:00
Родитель 786a42bdaf
Коммит 4585e03f71
21 изменённых файлов: 264 добавлений и 218 удалений

Просмотреть файл

@ -16,6 +16,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{8975719B
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostgreSql.Exporter", "src\PostgreSql.Exporter\PostgreSql.Exporter.csproj", "{6751E029-5644-4675-812A-4DF61CCD09EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sql.Compat.Common", "src\Akka.Persistence.Sql.Compat.Common\Akka.Persistence.Sql.Compat.Common.csproj", "{835E3257-495E-4C80-BB81-3C5D5F8BC285}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -42,5 +44,9 @@ Global
{6751E029-5644-4675-812A-4DF61CCD09EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6751E029-5644-4675-812A-4DF61CCD09EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6751E029-5644-4675-812A-4DF61CCD09EE}.Release|Any CPU.Build.0 = Release|Any CPU
{835E3257-495E-4C80-BB81-3C5D5F8BC285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{835E3257-495E-4C80-BB81-3C5D5F8BC285}.Debug|Any CPU.Build.0 = Debug|Any CPU
{835E3257-495E-4C80-BB81-3C5D5F8BC285}.Release|Any CPU.ActiveCfg = Release|Any CPU
{835E3257-495E-4C80-BB81-3C5D5F8BC285}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreLibraryFramework)</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
<PackageReference Include="Akka.Persistence" Version="$(AkkaVersion)" />
<PackageReference Include="Akka.Persistence.Query" Version="$(AkkaVersion)" />
<PackageReference Include="Akka.Persistence.Query.Sql" Version="$(AkkaVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,47 @@
// -----------------------------------------------------------------------
// <copyright file="CustomSerializer.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using System;
using Akka.Actor;
using Akka.Serialization;
namespace Akka.Persistence.Sql.Compat.Common
{
public sealed class CustomSerializer: SerializerWithStringManifest
{
public const string CustomShardedMessageManifest = "CSM";
public CustomSerializer(ExtendedActorSystem system) : base(system)
{
}
public override int Identifier => 999;
public override byte[] ToBinary(object obj)
{
if (obj is not CustomShardedMessage msg)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return BitConverter.GetBytes(msg.Message);
}
public override object FromBinary(byte[] bytes, string manifest)
{
if(manifest != CustomShardedMessageManifest)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return new CustomShardedMessage(BitConverter.ToInt32(bytes, 0));
}
public override string Manifest(object obj)
{
if (obj is not CustomShardedMessage)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return CustomShardedMessageManifest;
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
// -----------------------------------------------------------------------
// <copyright file="EventAdapter.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using System;
using Akka.Persistence.Journal;
namespace Akka.Persistence.Sql.Compat.Common
{
public sealed class EventAdapter: IWriteEventAdapter
{
public string Manifest(object evt) => string.Empty;
public object ToJournal(object evt)
{
var value = evt switch
{
int i => i,
string str => int.Parse(str),
_ => throw new Exception($"Unknown type: {evt.GetType()}")
};
return evt.ToTagged(value);
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
// -----------------------------------------------------------------------
// <copyright file="MessageExtractor.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using Akka.Cluster.Sharding;
namespace Akka.Persistence.Sql.Compat.Common
{
public sealed class MessageExtractor : HashCodeMessageExtractor
{
/// <summary>
/// We only ever run three nodes, so ~10 shards per node
/// </summary>
public MessageExtractor() : base(30)
{
}
public override string? EntityId(object message)
=> message switch
{
int i => i.ToEntityId(),
string str => int.Parse(str).ToEntityId(),
IHasEntityId msg => msg.EntityId,
ShardingEnvelope msg => msg.EntityId,
_ => null
};
}
}

Просмотреть файл

@ -0,0 +1,84 @@
// -----------------------------------------------------------------------
// <copyright file="Messages.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
namespace Akka.Persistence.Sql.Compat.Common
{
public interface IHasEntityId
{
public string EntityId { get; }
}
public sealed class Finish: IHasEntityId
{
public Finish(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class TakeSnapshotAndClear: IHasEntityId
{
public TakeSnapshotAndClear(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class TakeSnapshot: IHasEntityId
{
public TakeSnapshot(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class ShardedMessage: IHasEntityId
{
public ShardedMessage(int message)
{
EntityId = message.ToEntityId();
Message = message;
}
public string EntityId { get; }
public int Message { get; }
}
public sealed class CustomShardedMessage: IHasEntityId
{
public CustomShardedMessage(int message)
{
EntityId = message.ToEntityId();
Message = message;
}
public string EntityId { get; }
public int Message { get; }
}
public sealed class StateSnapshot
{
public static readonly StateSnapshot Empty = new StateSnapshot(0, 0);
public StateSnapshot(int total, int persisted)
{
Total = total;
Persisted = persisted;
}
public int Total { get; }
public int Persisted { get; }
}
}

Просмотреть файл

@ -0,0 +1,37 @@
// -----------------------------------------------------------------------
// <copyright file="Utils.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using System;
using Akka.Persistence.Journal;
namespace Akka.Persistence.Sql.Compat.Common
{
public static class Utils
{
// We're only doing 100 entities
public const int MaxEntities = 100;
private const int TaggedVariants = 3;
public const int MessagesPerType = MaxEntities * TaggedVariants;
public static readonly string[] Tags = { "Tag1", "Tag2", "Tag3", "Tag4" };
public static object ToTagged<T>(this T msg, int value)
{
if (msg is null)
throw new ArgumentNullException(nameof(msg));
return (value % TaggedVariants) switch
{
0 => msg,
1 => new Tagged(msg, new[] { Tags[0] }),
_ => new Tagged(msg, new[] { Tags[0], Tags[1] }),
};
}
public static string ToEntityId(this int msg)
=> ((msg / 3) % MaxEntities).ToString();
}
}

Просмотреть файл

@ -2,6 +2,8 @@
<PropertyGroup>
<TargetFramework>$(NetCoreFramework)</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
@ -14,4 +16,8 @@
<PackageReference Include="SharpCompress" Version="0.32.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Akka.Persistence.Sql.Compat.Common\Akka.Persistence.Sql.Compat.Common.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,45 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="CustomSerializer.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using Akka.Actor;
using Akka.Serialization;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
public sealed class CustomSerializer: SerializerWithStringManifest
{
public const string CustomShardedMessageManifest = "CSM";
public CustomSerializer(ExtendedActorSystem system) : base(system)
{
}
public override int Identifier => 999;
public override byte[] ToBinary(object obj)
{
if (obj is not CustomShardedMessage msg)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return BitConverter.GetBytes(msg.Message);
}
public override object FromBinary(byte[] bytes, string manifest)
{
if(manifest != CustomShardedMessageManifest)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return new CustomShardedMessage(BitConverter.ToInt32(bytes));
}
public override string Manifest(object obj)
{
if (obj is not CustomShardedMessage)
throw new Exception($"Can only process {nameof(CustomShardedMessage)}");
return CustomShardedMessageManifest;
}
}

Просмотреть файл

@ -4,6 +4,8 @@
// </copyright>
// -----------------------------------------------------------------------
using Akka.Persistence.Sql.Compat.Common;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
using Akka.Actor;

Просмотреть файл

@ -7,6 +7,7 @@
using Akka.Actor;
using Akka.Event;
using Akka.Persistence.Journal;
using Akka.Persistence.Sql.Compat.Common;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;

Просмотреть файл

@ -1,26 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="EventAdapter.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using Akka.Persistence.Journal;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
public sealed class EventAdapter: IWriteEventAdapter
{
public string Manifest(object evt) => string.Empty;
public object ToJournal(object evt)
{
var value = evt switch
{
int i => i,
string str => int.Parse(str),
_ => throw new Exception($"Unknown type: {evt.GetType()}")
};
return evt.ToTagged(value);
}
}

Просмотреть файл

@ -1,29 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="MessageExtractor.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using Akka.Cluster.Sharding;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
public sealed class MessageExtractor : HashCodeMessageExtractor
{
/// <summary>
/// We only ever run three nodes, so ~10 shards per node
/// </summary>
public MessageExtractor() : base(30)
{
}
public override string? EntityId(object message)
=> message switch
{
int i => i.ToEntityId(),
string str => int.Parse(str).ToEntityId(),
IHasEntityId msg => msg.EntityId,
ShardingEnvelope msg => msg.EntityId,
_ => null
};
}

Просмотреть файл

@ -1,82 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Messages.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
public interface IHasEntityId
{
public string EntityId { get; }
}
public sealed class Finish: IHasEntityId
{
public Finish(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class TakeSnapshotAndClear: IHasEntityId
{
public TakeSnapshotAndClear(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class TakeSnapshot: IHasEntityId
{
public TakeSnapshot(int entityId)
{
EntityId = (entityId % Utils.MaxEntities).ToString();
}
public string EntityId { get; }
}
public sealed class ShardedMessage: IHasEntityId
{
public ShardedMessage(int message)
{
EntityId = message.ToEntityId();
Message = message;
}
public string EntityId { get; }
public int Message { get; }
}
public sealed class CustomShardedMessage: IHasEntityId
{
public CustomShardedMessage(int message)
{
EntityId = message.ToEntityId();
Message = message;
}
public string EntityId { get; }
public int Message { get; }
}
public sealed class StateSnapshot
{
public static readonly StateSnapshot Empty = new StateSnapshot(0, 0);
public StateSnapshot(int total, int persisted)
{
Total = total;
Persisted = persisted;
}
public int Total { get; }
public int Persisted { get; }
}

Просмотреть файл

@ -12,6 +12,7 @@ using Akka.Cluster.Hosting;
using Akka.Cluster.Sharding;
using Akka.Hosting;
using Akka.Persistence.Hosting;
using Akka.Persistence.Sql.Compat.Common;
using Akka.Remote.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

Просмотреть файл

@ -1,35 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Utils.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------
using Akka.Persistence.Journal;
namespace Akka.Persistence.Sql.Exporter.Shared.Test;
public static class Utils
{
// We're only doing 100 entities
public const int MaxEntities = 100;
private const int TaggedVariants = 3;
public const int MessagesPerType = MaxEntities * TaggedVariants;
public static readonly string[] Tags = { "Tag1", "Tag2", "Tag3", "Tag4" };
public static object ToTagged<T>(this T msg, int value)
{
if (msg is null)
throw new ArgumentNullException(nameof(msg));
return (value % TaggedVariants) switch
{
0 => msg,
1 => new Tagged(msg, new[] { Tags[0] }),
_ => new Tagged(msg, new[] { Tags[0], Tags[1] }),
};
}
public static string ToEntityId(this int msg)
=> ((msg / 3) % MaxEntities).ToString();
}

Просмотреть файл

@ -213,11 +213,11 @@
</License>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageReadmeFile>README.md</PackageReadmeFile>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<NetCoreLibraryFramework>netstandard2.0</NetCoreLibraryFramework>
<NetCoreFramework>net6.0</NetCoreFramework>
<AkkaHostingVersion>0.5.0</AkkaHostingVersion>
<AkkaVersion>1.4.43</AkkaVersion>

Просмотреть файл

@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>$(NetCoreFramework)</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
</PropertyGroup>

Просмотреть файл

@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>$(NetCoreFramework)</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
</PropertyGroup>

Просмотреть файл

@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>$(NetCoreFramework)</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
</PropertyGroup>

Просмотреть файл

@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(NetCoreFramework)</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
</PropertyGroup>