Skip to content

Commit

Permalink
PostgreSQL persistence plugin for both event journal and snapshot sto…
Browse files Browse the repository at this point in the history
…re. See issue akkadotnet#944

 -Largely ported from Akka.Persistence.SqlServer plugin

 -Event journal and snapshot store specs passing

 -Added separate build task for PostgreSql tests

 -Added initial draft of readme and nuspec file
  • Loading branch information
davidflerlage authored and Horusiath committed Jul 3, 2015
1 parent 8978857 commit 5e2cbdc
Show file tree
Hide file tree
Showing 24 changed files with 1,424 additions and 1 deletion.
11 changes: 10 additions & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ Target "RunTests" <| fun _ ->
let xunitTestAssemblies = !! "src/**/bin/Release/*.Tests.dll" --
"src/**/bin/Release/Akka.TestKit.VsTest.Tests.dll" --
"src/**/bin/Release/Akka.TestKit.NUnit.Tests.dll" --
"src/**/bin/Release/Akka.Persistence.SqlServer.Tests.dll"
"src/**/bin/Release/Akka.Persistence.SqlServer.Tests.dll" --
"src/**/bin/Release/Akka.Persistence.PostgreSql.Tests.dll"

mkdir testOutput

Expand Down Expand Up @@ -271,6 +272,14 @@ Target "RunSqlServerTests" <| fun _ ->
(fun p -> { p with OutputDir = testOutput; ToolPath = xunitToolPath })
sqlServerTests

Target "RunPostgreSqlTests" <| fun _ ->
let postgreSqlTests = !! "src/**/bin/Release/Akka.Persistence.PostgreSql.Tests.dll"
let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools"
printfn "Using XUnit runner: %s" xunitToolPath
xUnit2
(fun p -> { p with OutputDir = testOutput; ToolPath = xunitToolPath })
postgreSqlTests

//--------------------------------------------------------------------------------
// Nuget targets
//--------------------------------------------------------------------------------
Expand Down
22 changes: 22 additions & 0 deletions src/Akka.sln
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTests", "core
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sql.Common", "contrib\persistence\Akka.Persistence.Sql.Common\Akka.Persistence.Sql.Common.csproj", "{3B9E6211-9488-4DB5-B714-24248693B38F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.PostgreSql", "contrib\persistence\Akka.Persistence.PostgreSql\Akka.Persistence.PostgreSql.csproj", "{4B89227B-5AD1-4061-816F-570067C3727F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.PostgreSql.Tests", "contrib\persistence\Akka.Persistence.PostgreSql.Tests\Akka.Persistence.PostgreSql.Tests.csproj", "{2D1812FD-70C0-43EE-9C25-3980E41F30E1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Mono|Any CPU = Debug Mono|Any CPU
Expand Down Expand Up @@ -774,6 +778,22 @@ Global
{3B9E6211-9488-4DB5-B714-24248693B38F}.Release Mono|Any CPU.Build.0 = Release|Any CPU
{3B9E6211-9488-4DB5-B714-24248693B38F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B9E6211-9488-4DB5-B714-24248693B38F}.Release|Any CPU.Build.0 = Release|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Release Mono|Any CPU.Build.0 = Release|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B89227B-5AD1-4061-816F-570067C3727F}.Release|Any CPU.Build.0 = Release|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Release Mono|Any CPU.Build.0 = Release|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D1812FD-70C0-43EE-9C25-3980E41F30E1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -868,5 +888,7 @@ Global
{7DBD5C17-5E9D-40C4-9201-D092751532A7} = {7625FD95-4B2C-4A5B-BDD5-94B1493FAC8E}
{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5} = {01167D3C-49C4-4CDE-9787-C176D139ACDD}
{3B9E6211-9488-4DB5-B714-24248693B38F} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767}
{4B89227B-5AD1-4061-816F-570067C3727F} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767}
{2D1812FD-70C0-43EE-9C25-3980E41F30E1} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2D1812FD-70C0-43EE-9C25-3980E41F30E1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Akka.Persistence.PostgreSql.Tests</RootNamespace>
<AssemblyName>Akka.Persistence.PostgreSql.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Security">
<HintPath>..\..\..\packages\Npgsql.2.2.5\lib\net45\Mono.Security.dll</HintPath>
</Reference>
<Reference Include="Npgsql">
<HintPath>..\..\..\packages\Npgsql.2.2.5\lib\net45\Npgsql.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DbUtils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PostgreSqlJournalSpec.cs" />
<Compile Include="PostgreSqlSnapshotStoreSpec.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\testkits\Akka.TestKit.Xunit2\Akka.TestKit.Xunit2.csproj">
<Project>{7dbd5c17-5e9d-40c4-9201-d092751532a7}</Project>
<Name>Akka.TestKit.Xunit2</Name>
</ProjectReference>
<ProjectReference Include="..\Akka.Persistence.PostgreSql\Akka.Persistence.PostgreSql.csproj">
<Project>{4b89227b-5ad1-4061-816f-570067c3727f}</Project>
<Name>Akka.Persistence.PostgreSql</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\core\Akka.Persistence.TestKit\Akka.Persistence.TestKit.csproj">
<Project>{ad9418b6-c452-4169-94fb-d43de0bfa966}</Project>
<Name>Akka.Persistence.TestKit</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\core\Akka.Persistence\Akka.Persistence.csproj">
<Project>{fca84dea-c118-424b-9eb8-34375dfef18a}</Project>
<Name>Akka.Persistence</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\core\Akka.TestKit\Akka.TestKit.csproj">
<Project>{0d3cbad0-bbdb-43e5-afc4-ed1d3ecdc224}</Project>
<Name>Akka.TestKit</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\core\Akka\Akka.csproj">
<Project>{5deddf90-37f0-48d3-a0b0-a5cbd8a7e377}</Project>
<Name>Akka</Name>
</ProjectReference>
<ProjectReference Include="..\Akka.Persistence.Sql.Common\Akka.Persistence.Sql.Common.csproj">
<Project>{3b9e6211-9488-4db5-b714-24248693b38f}</Project>
<Name>Akka.Persistence.Sql.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Configuration;
using System.Data.SqlClient;
using Akka.Dispatch.SysMsg;
using Npgsql;

namespace Akka.Persistence.PostgreSql.Tests
{
public static class DbUtils
{
public static void Initialize()
{
var connectionString = ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString;
var connectionBuilder = new NpgsqlConnectionStringBuilder(connectionString);

//connect to postgres database to create a new database
var databaseName = connectionBuilder.Database;
connectionBuilder.Database = "postgres";
connectionString = connectionBuilder.ToString();

using (var conn = new NpgsqlConnection(connectionString))
{
conn.Open();

bool dbExists;
using (var cmd = new NpgsqlCommand())
{
cmd.CommandText = string.Format(@"SELECT TRUE FROM pg_database WHERE datname='{0}'", databaseName);
cmd.Connection = conn;

var result = cmd.ExecuteScalar();
dbExists = result != null && Convert.ToBoolean(result);
}

if (dbExists)
{
DoClean(conn);
}
else
{
DoCreate(conn, databaseName);
}
}
}

public static void Clean()
{
var connectionString = ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString;

using (var conn = new NpgsqlConnection(connectionString))
{
conn.Open();

DoClean(conn);
}
}

private static void DoCreate(NpgsqlConnection conn, string databaseName)
{
using (var cmd = new NpgsqlCommand())
{
cmd.CommandText = string.Format(@"CREATE DATABASE {0}", databaseName);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
}

private static void DoClean(NpgsqlConnection conn)
{
using (var cmd = new NpgsqlCommand())
{
cmd.CommandText = @"
DROP TABLE IF EXISTS public.event_journal;
DROP TABLE IF EXISTS public.snapshot_store";
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Configuration;
using Akka.Configuration;
using Akka.Persistence.TestKit.Journal;

namespace Akka.Persistence.PostgreSql.Tests
{
public class PostgreSqlJournalSpec : JournalSpec
{
private static readonly Config SpecConfig;

static PostgreSqlJournalSpec()
{
var connectionString = ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString;

var config = @"
akka.persistence {
publish-plugin-commands = on
journal {
plugin = ""akka.persistence.journal.postgresql""
postgresql {
class = ""Akka.Persistence.PostgreSql.Journal.PostgreSqlJournal, Akka.Persistence.PostgreSql""
plugin-dispatcher = ""akka.actor.default-dispatcher""
table-name = event_journal
schema-name = public
auto-initialize = on
connection-string = """ + connectionString + @"""
}
}
}";

SpecConfig = ConfigurationFactory.ParseString(config);

//need to make sure db is created before the tests start
DbUtils.Initialize();
}

public PostgreSqlJournalSpec()
: base(SpecConfig, "PostgreSqlJournalSpec")
{
Initialize();
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
DbUtils.Clean();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Configuration;
using Akka.Configuration;
using Akka.Persistence.TestKit.Snapshot;

namespace Akka.Persistence.PostgreSql.Tests
{
public class PostgreSqlSnapshotStoreSpec : SnapshotStoreSpec
{
private static readonly Config SpecConfig;

static PostgreSqlSnapshotStoreSpec()
{
var connectionString = ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString;

var config = @"
akka.persistence {
publish-plugin-commands = on
snapshot-store {
plugin = ""akka.persistence.snapshot-store.postgresql""
postgresql {
class = ""Akka.Persistence.PostgreSql.Snapshot.PostgreSqlSnapshotStore, Akka.Persistence.PostgreSql""
plugin-dispatcher = ""akka.actor.default-dispatcher""
table-name = snapshot_store
schema-name = public
auto-initialize = on
connection-string = """ + connectionString + @"""
}
}
}";

SpecConfig = ConfigurationFactory.ParseString(config);

//need to make sure db is created before the tests start
DbUtils.Initialize();
}

public PostgreSqlSnapshotStoreSpec()
: base(SpecConfig, "PostgreSqlSnapshotStoreSpec")
{
Initialize();
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
DbUtils.Clean();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Akka.Persistence.PostgreSql.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Akka.Persistence.PostgreSql.Tests")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8494fd8c-15ae-489e-83aa-1ac37b458964")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading

0 comments on commit 5e2cbdc

Please sign in to comment.