From 136d232fe2866431900c7eccd6e1c66672b1f7a7 Mon Sep 17 00:00:00 2001 From: Silv3rcircl3 Date: Tue, 5 Jan 2016 08:45:47 +0100 Subject: [PATCH 1/9] Added release note and fixed nuget tag --- RELEASE_NOTES.md | 3 ++- src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4fb649c..69c8168 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,5 @@ -#### 1.0.5 August 08 2015 #### +#### 1.0.5 January 05 2016 #### +Support for Akka 1.0.5 #### 1.0.4 August 07 2015 #### Initial release of Akka.Persistence.MongoDb \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec index 8ec8e0b..fc6276c 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec @@ -13,7 +13,7 @@ false @releaseNotes@ @copyright@ - @tags@ persistence eventsource sqlserver + @tags@ persistence eventsource mongodb @dependencies@ @references@ From cdacea285bf1699a419d4d07cff7bb608c6f9681 Mon Sep 17 00:00:00 2001 From: ravengerUA Date: Mon, 25 Jul 2016 13:37:06 +0300 Subject: [PATCH 2/9] Updated MongoDb provider to Akka 1.1.1 --- README.md | 55 ++++++- RELEASE_NOTES.md | 6 +- appveyor.yml | 8 + build.cmd | 7 +- build.fsx | 61 ++----- build.sh | 6 +- src/.nuget/NuGet.Config | 3 + src/.nuget/NuGet.Dev.Config | 6 +- .../Akka.Persistence.MongoDb.Tests.csproj | 91 ++++++---- src/Akka.Persistence.MongoDb.Tests/App.config | 12 +- .../MongoDbJournalSpec.cs | 43 ++--- .../MongoDbSettingsSpec.cs | 37 +++++ .../MongoDbSnapshotStoreSpec.cs | 42 ++--- .../packages.config | 36 ++-- src/Akka.Persistence.MongoDb.sln | 6 +- .../Akka.Persistence.MongoDb.csproj | 42 +++-- .../Akka.Persistence.MongoDb.nuspec | 4 +- .../Journal/JournalEntry.cs | 9 +- .../Journal/MetadataEntry.cs | 23 +++ .../Journal/MongoDbJournal.cs | 155 +++++++++++++----- .../MongoDbExtension.cs | 76 --------- .../MongoDbPersistence.cs | 54 ++++-- .../MongoDbPersistenceProvider.cs | 27 +++ .../MongoDbSettings.cs | 29 +++- .../Snapshot/MongoDbSnapshotStore.cs | 98 ++++++++--- .../Snapshot/SnapshotEntry.cs | 7 + src/Akka.Persistence.MongoDb/app.config | 11 ++ src/Akka.Persistence.MongoDb/packages.config | 15 +- src/Akka.Persistence.MongoDb/reference.conf | 28 +++- src/SharedAssemblyInfo.cs | 6 +- 30 files changed, 655 insertions(+), 348 deletions(-) create mode 100644 appveyor.yml create mode 100644 src/Akka.Persistence.MongoDb.Tests/MongoDbSettingsSpec.cs create mode 100644 src/Akka.Persistence.MongoDb/Journal/MetadataEntry.cs delete mode 100644 src/Akka.Persistence.MongoDb/MongoDbExtension.cs create mode 100644 src/Akka.Persistence.MongoDb/MongoDbPersistenceProvider.cs create mode 100644 src/Akka.Persistence.MongoDb/app.config diff --git a/README.md b/README.md index 025f52a..a46add4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Akka.Persistence.MongoDB +# Akka.Persistence.MongoDB Akka Persistence journal and snapshot store backed by MongoDB database. @@ -22,16 +22,56 @@ akka.persistence.snapshot-store.mongodb.connection-string = "An error occurred while deserializing the Payload property of class \: Unknown discriminator value '\' ### Notice -- The MongoDB operator to limit the number of documents in a query only accepts an integer while akka provides a long as maximum for the loading of events during the replay. Internally the long value is cast to an integer and if the value is higher then Int32.MaxValue, Int32.MaxValue is used. So if you have stored more then 2,147,483,647 events for a singel PersistenceId, you may have a problem :wink: -- If you call SaveSnapshot in your PersistanceActor twice, without persisting any events to the journal between the first and second call, the second call will not override the exising snapshot but rather send a SaveSnapshotFailure message back. Even if storing snapshots without persisting events in the meantime make no sense at all. +- The MongoDB operator to limit the number of documents in a query only accepts an integer while akka provides a long as maximum for the loading of events during the replay. Internally the long value is cast to an integer and if the value is higher then Int32.MaxValue, Int32.MaxValue is used. So if you have stored more then 2,147,483,647 events for a single PersistenceId, you may have a problem :wink: diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 69c8168..000cd2d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,7 @@ -#### 1.0.5 January 05 2016 #### -Support for Akka 1.0.5 +#### 1.1.0 July 30 2016 #### +Updated to Akka.Persistence 1.1.1 + +#### 1.0.5 August 08 2015 #### #### 1.0.4 August 07 2015 #### Initial release of Akka.Persistence.MongoDb \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..330da97 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,8 @@ +version: '1.0.{build}' +skip_tags: true +image: Visual Studio 2015 +configuration: Release +build_script: +- cmd: build.cmd Build +test_script: +- cmd: build.cmd RunTests diff --git a/build.cmd b/build.cmd index 55899b0..5457002 100644 --- a/build.cmd +++ b/build.cmd @@ -4,13 +4,12 @@ pushd %~dp0 src\.nuget\NuGet.exe update -self -src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.1.0 +src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.35.0 -src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.0.0 -src\.nuget\NuGet.exe install nunit.runners -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.6.4 +src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.1.0 if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( - src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion + src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 1.1.0 ) rem cls diff --git a/build.fsx b/build.fsx index 8f569ea..f6f600a 100644 --- a/build.fsx +++ b/build.fsx @@ -19,7 +19,7 @@ cd __SOURCE_DIRECTORY__ let product = "Akka.NET" let authors = [ "Akka.NET Team" ] -let copyright = "Copyright © 2013-2015 Akka.NET Team" +let copyright = "Copyright © 2013-2016 Akka.NET Team" let company = "Akka.NET Team" let description = "Akka.NET is a port of the popular Java/Scala framework Akka to .NET" let tags = ["akka";"actors";"actor";"model";"Akka";"concurrency"] @@ -52,7 +52,7 @@ let nugetDir = binDir @@ "nuget" let workingDir = binDir @@ "build" let libDir = workingDir @@ @"lib\net45\" let nugetExe = FullName @"src\.nuget\NuGet.exe" -let slnFile = "./src/Akka.Persistence.MongoDb.sln" +let slnFile = "./src/Akka.Persistence.MongoDB.sln" open Fake.RestorePackageHelper Target "RestorePackages" (fun _ -> @@ -103,7 +103,7 @@ Target "CopyOutput" <| fun _ -> let src = "src" @@ project @@ @"bin/Release/" let dst = binDir @@ project CopyDir dst src allFiles - [ "Akka.Persistence.MongoDb" + [ "Akka.Persistence.MongoDB" ] |> List.iter copyOutput @@ -123,17 +123,22 @@ Target "CleanTests" <| fun _ -> //-------------------------------------------------------------------------------- // Run tests -open XUnit2Helper +open Fake.Testing Target "RunTests" <| fun _ -> let xunitTestAssemblies = !! "src/**/bin/Release/*.Tests.dll" mkdir testOutput - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" + let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/FAKE/xunit.runner.console*/tools" + printfn "Using XUnit runner: %s" xunitToolPath - xUnit2 - (fun p -> { p with OutputDir = testOutput; ToolPath = xunitToolPath }) - xunitTestAssemblies + let runSingleAssembly assembly = + let assemblyName = Path.GetFileNameWithoutExtension(assembly) + xUnit2 + (fun p -> { p with XmlOutputPath = Some (testOutput + @"\" + assemblyName + "_xunit.xml"); HtmlOutputPath = Some (testOutput + @"\" + assemblyName + "_xunit.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) + (Seq.singleton assembly) + + xunitTestAssemblies |> Seq.iter (runSingleAssembly) //-------------------------------------------------------------------------------- // Nuget targets @@ -153,46 +158,8 @@ module Nuget = | _ -> release.NugetVersion open Nuget - open NuGet.Update -//-------------------------------------------------------------------------------- -// Upgrade nuget package versions for dev and production - -let updateNugetPackages _ = - printfn "Updating NuGet dependencies" - - let getConfigFile preRelease = - match preRelease with - | true -> "src/.nuget/NuGet.Dev.Config" - | false -> "src/.nuget/NuGet.Config" - - let getPackages project = - match project with - | "Akka.Persistence.MongoDb" -> ["Akka.Persistence";] - | "Akka.Persistence.MongoDb.Tests" -> ["Akka.Persistence.TestKit";] - | _ -> [] - - for projectFile in !! "src/**/*.csproj" do - printfn "Updating packages for %s" projectFile - let project = Path.GetFileNameWithoutExtension projectFile - let projectDir = Path.GetDirectoryName projectFile - let config = projectDir @@ "packages.config" - - NugetUpdate - (fun p -> - { p with - ConfigFile = Some (getConfigFile isPreRelease) - Prerelease = true - ToolPath = nugetExe - RepositoryPath = "src/Packages" - Ids = getPackages project - }) config - -Target "UpdateDependencies" <| fun _ -> - printfn "Invoking updateNugetPackages" - updateNugetPackages() - //-------------------------------------------------------------------------------- // Clean nuget directory @@ -422,7 +389,7 @@ Target "HelpDocs" <| fun _ -> //-------------------------------------------------------------------------------- // build dependencies -"Clean" ==> "AssemblyInfo" ==> "RestorePackages" ==> "UpdateDependencies" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" +"Clean" ==> "AssemblyInfo" ==> "RestorePackages" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" // tests dependencies "CleanTests" ==> "RunTests" diff --git a/build.sh b/build.sh index cdfa7bc..84e65b6 100644 --- a/build.sh +++ b/build.sh @@ -11,12 +11,12 @@ popd > /dev/null mono $SCRIPT_PATH/src/.nuget/NuGet.exe update -self -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install FAKE -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 3.28.8 +mono $SCRIPT_PATH/src/.nuget/NuGet.exe install FAKE -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 4.35.0 -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install xunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.0.0 +mono $SCRIPT_PATH/src/.nuget/NuGet.exe install xunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.1.0 if ! [ -e $SCRIPT_PATH/src/packages/SourceLink.Fake/tools/SourceLink.fsx ] ; then - mono $SCRIPT_PATH/src/.nuget/NuGet.exe install SourceLink.Fake -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion + mono $SCRIPT_PATH/src/.nuget/NuGet.exe install SourceLink.Fake -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 1.1.0 fi diff --git a/src/.nuget/NuGet.Config b/src/.nuget/NuGet.Config index 67f8ea0..e99c073 100644 --- a/src/.nuget/NuGet.Config +++ b/src/.nuget/NuGet.Config @@ -3,4 +3,7 @@ + + + \ No newline at end of file diff --git a/src/.nuget/NuGet.Dev.Config b/src/.nuget/NuGet.Dev.Config index ccb961d..769631a 100644 --- a/src/.nuget/NuGet.Dev.Config +++ b/src/.nuget/NuGet.Dev.Config @@ -4,7 +4,9 @@ - - + + + + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj index 4349bdf..7ced513 100644 --- a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj +++ b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj @@ -1,6 +1,6 @@  - + Debug @@ -35,52 +35,67 @@ 4 - - ..\packages\Akka.1.0.5\lib\net45\Akka.dll + + ..\packages\Akka.1.1.1\lib\net45\Akka.dll True - - ..\Packages\Akka.Persistence.1.0.5.15-beta\lib\net45\Akka.Persistence.dll + + ..\packages\Akka.Persistence.1.1.1.28-beta\lib\net45\Akka.Persistence.dll + True + + + ..\packages\Akka.Persistence.TestKit.1.1.1.28-beta\lib\net45\Akka.Persistence.TestKit.dll + True - - ..\Packages\Akka.Persistence.TestKit.1.0.5.15-beta\lib\net45\Akka.Persistence.TestKit.dll + + ..\packages\Akka.TestKit.1.1.1\lib\net45\Akka.TestKit.dll + True - - ..\packages\Akka.TestKit.1.0.5\lib\net45\Akka.TestKit.dll + + ..\packages\Akka.TestKit.Xunit2.1.1.1\lib\net45\Akka.TestKit.Xunit2.dll True - - ..\packages\Akka.TestKit.Xunit2.1.0.5\lib\net45\Akka.TestKit.Xunit2.dll + + ..\packages\FluentAssertions.4.12.0\lib\net45\FluentAssertions.dll True - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + ..\packages\FluentAssertions.4.12.0\lib\net45\FluentAssertions.Core.dll True - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll True - - ..\packages\Mongo2Go.0.1.6\lib\net35\Mongo2Go.dll + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll True - - ..\packages\MongoDB.Bson.2.0.1\lib\net45\MongoDB.Bson.dll + + ..\packages\Mongo2Go.0.2.0\lib\net35\Mongo2Go.dll True - - ..\packages\MongoDB.Driver.2.0.1\lib\net45\MongoDB.Driver.dll + + ..\packages\MongoDB.Bson.2.2.4\lib\net45\MongoDB.Bson.dll True - - ..\packages\MongoDB.Driver.Core.2.0.1\lib\net45\MongoDB.Driver.Core.dll + + ..\packages\MongoDB.Driver.2.2.4\lib\net45\MongoDB.Driver.dll True - - ..\Packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\MongoDB.Driver.Core.2.2.4\lib\net45\MongoDB.Driver.Core.dll + True + + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -93,12 +108,16 @@ ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll True - - ..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + + ..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + True + + + ..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll True - - ..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + ..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll True @@ -107,6 +126,7 @@ Properties\SharedAssemblyInfo.cs + @@ -117,16 +137,23 @@ - - + + Designer + + + Designer + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - + + + + + + + + + diff --git a/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs b/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs index 0f6b1d5..3575e20 100644 --- a/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs +++ b/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs @@ -1,35 +1,40 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Configuration; using Akka.Persistence.TestKit.Journal; using Mongo2Go; using MongoDB.Driver; +using Xunit; namespace Akka.Persistence.MongoDb.Tests { + [Collection("MongoDbSpec")] public class MongoDbJournalSpec : JournalSpec { private static readonly MongoDbRunner Runner = MongoDbRunner.Start(ConfigurationManager.AppSettings[0]); + protected override bool SupportsRejectingNonSerializableObjects { get; } = false; + private static readonly string SpecConfig = @" - akka.persistence { - publish-plugin-commands = on - journal { - plugin = ""akka.persistence.journal.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb"" - connection-string = """" - collection = ""EventJournal"" - } - } - snapshot-store { - plugin = ""akka.persistence.snapshot-store.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb"" - connection-string = """" - collection = ""SnapshotStore"" + akka.test.single-expect-default = 3s + akka.persistence { + publish-plugin-commands = on + journal { + plugin = ""akka.persistence.journal.mongodb"" + mongodb { + class = ""Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb"" + connection-string = """" + auto-initialize = on + collection = ""EventJournal"" + } } - } - }"; + }"; public MongoDbJournalSpec() : base(CreateSpecConfig(), "MongoDbJournalSpec") { diff --git a/src/Akka.Persistence.MongoDb.Tests/MongoDbSettingsSpec.cs b/src/Akka.Persistence.MongoDb.Tests/MongoDbSettingsSpec.cs new file mode 100644 index 0000000..ce5f864 --- /dev/null +++ b/src/Akka.Persistence.MongoDb.Tests/MongoDbSettingsSpec.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using FluentAssertions; +using Xunit; + +namespace Akka.Persistence.MongoDb.Tests +{ + [Collection("MongoDbSpec")] + public class MongoDbSettingsSpec : Akka.TestKit.Xunit2.TestKit + { + [Fact] + public void Mongo_JournalSettings_must_have_default_values() + { + var mongoPersistence = MongoDbPersistence.Get(Sys); + + mongoPersistence.JournalSettings.ConnectionString.Should().Be(string.Empty); + mongoPersistence.JournalSettings.AutoInitialize.Should().BeFalse(); + mongoPersistence.JournalSettings.Collection.Should().Be("EventJournal"); + mongoPersistence.JournalSettings.MetadataCollection.Should().Be("Metadata"); + } + + [Fact] + public void Mongo_SnapshotStoreSettingsSettings_must_have_default_values() + { + var mongoPersistence = MongoDbPersistence.Get(Sys); + + mongoPersistence.SnapshotStoreSettings.ConnectionString.Should().Be(string.Empty); + mongoPersistence.SnapshotStoreSettings.AutoInitialize.Should().BeFalse(); + mongoPersistence.SnapshotStoreSettings.Collection.Should().Be("SnapshotStore"); + } + } +} diff --git a/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs b/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs index 643b521..a945894 100644 --- a/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs +++ b/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs @@ -1,36 +1,38 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Configuration; using Akka.Persistence.TestKit.Snapshot; using Mongo2Go; using MongoDB.Driver; +using Xunit; namespace Akka.Persistence.MongoDb.Tests { + [Collection("MongoDbSpec")] public class MongoDbSnapshotStoreSpec : SnapshotStoreSpec { private static readonly MongoDbRunner Runner = MongoDbRunner.Start(ConfigurationManager.AppSettings[0]); private static readonly string SpecConfig = @" - akka.persistence { - publish-plugin-commands = on - snapshot-store { - plugin = ""akka.persistence.snapshot-store.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb"" - connection-string = """" - collection = ""SnapshotStore"" - } - } - journal { - plugin = ""akka.persistence.journal.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb"" - connection-string = """" - collection = ""EventJournal"" + akka.test.single-expect-default = 3s + akka.persistence { + publish-plugin-commands = on + snapshot-store { + plugin = ""akka.persistence.snapshot-store.mongodb"" + mongodb { + class = ""Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb"" + connection-string = """" + auto-initialize = on + collection = ""SnapshotStore"" + } } - } - }"; - + }"; public MongoDbSnapshotStoreSpec() : base(CreateSpecConfig(), "MongoDbSnapshotStoreSpec") { diff --git a/src/Akka.Persistence.MongoDb.Tests/packages.config b/src/Akka.Persistence.MongoDb.Tests/packages.config index 4fff9e3..c1c634d 100644 --- a/src/Akka.Persistence.MongoDb.Tests/packages.config +++ b/src/Akka.Persistence.MongoDb.Tests/packages.config @@ -1,19 +1,23 @@  - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb.sln b/src/Akka.Persistence.MongoDb.sln index f722a70..6fdb083 100644 --- a/src/Akka.Persistence.MongoDb.sln +++ b/src/Akka.Persistence.MongoDb.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.MongoDb", "Akka.Persistence.MongoDb\Akka.Persistence.MongoDb.csproj", "{12E044EF-08A2-428B-AAF5-C3D328860C4E}" EndProject @@ -9,9 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.MongoDb.Te EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{86AAC379-3743-4D46-8B92-AE6A5ED80A44}" ProjectSection(SolutionItems) = preProject + ..\appveyor.yml = ..\appveyor.yml ..\build.cmd = ..\build.cmd ..\build.fsx = ..\build.fsx ..\build.sh = ..\build.sh + ..\README.md = ..\README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{65DAEEC3-80C7-42C5-B0AC-DFC928846EF6}" diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj index 87c686d..eb364be 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj @@ -32,37 +32,43 @@ 4 - - ..\packages\Akka.1.0.5\lib\net45\Akka.dll + + ..\packages\Akka.1.1.1\lib\net45\Akka.dll True - - ..\Packages\Akka.Persistence.1.0.5.15-beta\lib\net45\Akka.Persistence.dll + + ..\packages\Akka.Persistence.1.1.1.28-beta\lib\net45\Akka.Persistence.dll + True - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll True - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll True - - ..\packages\MongoDB.Bson.2.0.1\lib\net45\MongoDB.Bson.dll + + ..\packages\MongoDB.Bson.2.2.4\lib\net45\MongoDB.Bson.dll True - - ..\packages\MongoDB.Driver.2.0.1\lib\net45\MongoDB.Driver.dll + + ..\packages\MongoDB.Driver.2.2.4\lib\net45\MongoDB.Driver.dll True - - ..\packages\MongoDB.Driver.Core.2.0.1\lib\net45\MongoDB.Driver.Core.dll + + ..\packages\MongoDB.Driver.Core.2.2.4\lib\net45\MongoDB.Driver.Core.dll True - - ..\Packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -75,10 +81,11 @@ Properties\SharedAssemblyInfo.cs + - + @@ -87,6 +94,7 @@ + Designer diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec index fc6276c..4cd912f 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec @@ -8,12 +8,12 @@ @authors@ Akka.NET Persistence journal and snapshot store backed by MongoDB. https://github.com/akkadotnet/akka.net/blob/master/LICENSE - https://github.com/akkadotnet/akka.net + https://github.com/akkadotnet/Akka.Persistence.MongoDB http://getakka.net/images/AkkaNetLogo.Normal.png false @releaseNotes@ @copyright@ - @tags@ persistence eventsource mongodb + @tags@ persistence eventsource mongodb mongo @dependencies@ @references@ diff --git a/src/Akka.Persistence.MongoDb/Journal/JournalEntry.cs b/src/Akka.Persistence.MongoDb/Journal/JournalEntry.cs index d967500..3733428 100644 --- a/src/Akka.Persistence.MongoDb/Journal/JournalEntry.cs +++ b/src/Akka.Persistence.MongoDb/Journal/JournalEntry.cs @@ -1,4 +1,11 @@ -using MongoDB.Bson.Serialization.Attributes; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using MongoDB.Bson.Serialization.Attributes; namespace Akka.Persistence.MongoDb.Journal { diff --git a/src/Akka.Persistence.MongoDb/Journal/MetadataEntry.cs b/src/Akka.Persistence.MongoDb/Journal/MetadataEntry.cs new file mode 100644 index 0000000..1390752 --- /dev/null +++ b/src/Akka.Persistence.MongoDb/Journal/MetadataEntry.cs @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using MongoDB.Bson.Serialization.Attributes; + +namespace Akka.Persistence.MongoDb.Journal +{ + public class MetadataEntry + { + [BsonId] + public string Id { get; set; } + + [BsonElement("PersistenceId")] + public string PersistenceId { get; set; } + + [BsonElement("SequenceNr")] + public long SequenceNr { get; set; } + } +} diff --git a/src/Akka.Persistence.MongoDb/Journal/MongoDbJournal.cs b/src/Akka.Persistence.MongoDb/Journal/MongoDbJournal.cs index 028d9e7..ba97673 100644 --- a/src/Akka.Persistence.MongoDb/Journal/MongoDbJournal.cs +++ b/src/Akka.Persistence.MongoDb/Journal/MongoDbJournal.cs @@ -1,5 +1,13 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Akka.Actor; @@ -13,72 +21,128 @@ namespace Akka.Persistence.MongoDb.Journal /// public class MongoDbJournal : AsyncWriteJournal { - private readonly IMongoCollection _collection; + private readonly MongoDbJournalSettings _settings; + private Lazy _mongoDatabase; + private Lazy> _journalCollection; + private Lazy> _metadataCollection; public MongoDbJournal() { - _collection = MongoDbPersistence.Instance.Apply(Context.System).JournalCollection; + _settings = MongoDbPersistence.Get(Context.System).JournalSettings; } - public override Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, long toSequenceNr, long max, Action replayCallback) + protected override void PreStart() { - // Limit(0) doesn't work... - if (max == 0) - return Task.Run(() => {}); + base.PreStart(); + _mongoDatabase = new Lazy(() => + { + var connectionString = new MongoUrl(_settings.ConnectionString); + var client = new MongoClient(connectionString); + + return client.GetDatabase(connectionString.DatabaseName); + }); + + _journalCollection = new Lazy>(() => + { + var collection = _mongoDatabase.Value.GetCollection(_settings.Collection); + + if (_settings.AutoInitialize) + { + collection.Indexes.CreateOneAsync( + Builders.IndexKeys + .Ascending(entry => entry.PersistenceId) + .Descending(entry => entry.SequenceNr)) + .Wait(); + } + + return collection; + }); + + _metadataCollection = new Lazy>(() => + { + var collection = _mongoDatabase.Value.GetCollection(_settings.MetadataCollection); + + if (_settings.AutoInitialize) + { + collection.Indexes.CreateOneAsync( + Builders.IndexKeys + .Ascending(entry => entry.PersistenceId)) + .Wait(); + } + + return collection; + }); + } + + public override async Task ReplayMessagesAsync(IActorContext context, string persistenceId, long fromSequenceNr, long toSequenceNr, long max, Action recoveryCallback) + { // Limit allows only integer - var maxValue = max >= int.MaxValue ? int.MaxValue : (int)max; - var sender = Context.Sender; + var limitValue = max >= int.MaxValue ? int.MaxValue : (int)max; + + // Do not replay messages if limit equal zero + if (limitValue == 0) + return; + var builder = Builders.Filter; var filter = builder.Eq(x => x.PersistenceId, persistenceId); - var sort = Builders.Sort.Ascending(x => x.SequenceNr); - if (fromSequenceNr > 0) filter &= builder.Gte(x => x.SequenceNr, fromSequenceNr); - if (toSequenceNr != long.MaxValue) filter &= builder.Lte(x => x.SequenceNr, toSequenceNr); - return - _collection - .Find(filter) - .Sort(sort) - .Limit(maxValue) - .ForEachAsync(doc => replayCallback(ToPersistanceRepresentation(doc, sender))); + var sort = Builders.Sort.Ascending(x => x.SequenceNr); + + var collections = await _journalCollection.Value + .Find(filter) + .Sort(sort) + .Limit(limitValue) + .ToListAsync(); + + collections.ForEach(doc => + { + recoveryCallback(ToPersistenceRepresentation(doc, context.Sender)); + }); } - public override Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) + public override async Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) { - var builder = Builders.Filter; + var builder = Builders.Filter; var filter = builder.Eq(x => x.PersistenceId, persistenceId); - return - _collection - .Find(filter) - .Limit(1) - .Project(x => x.SequenceNr) - .FirstOrDefaultAsync(); + var highestSequenceNr = await _metadataCollection.Value.Find(filter).Project(x => x.SequenceNr).FirstOrDefaultAsync(); + + return highestSequenceNr; } - protected override Task WriteMessagesAsync(IEnumerable messages) + protected override async Task> WriteMessagesAsync(IEnumerable messages) { - var entries = messages.Select(ToJournalEntry).ToList(); - return _collection.InsertManyAsync(entries); + var messageList = messages.ToList(); + var writeTasks = messageList.Select(async message => + { + var persistentMessages = ((IImmutableList)message.Payload).ToArray(); + + var journalEntries = persistentMessages.Select(ToJournalEntry).ToList(); + await _journalCollection.Value.InsertManyAsync(journalEntries); + }); + + await SetHighSequenceId(messageList); + + return await Task> + .Factory + .ContinueWhenAll(writeTasks.ToArray(), + tasks => tasks.Select(t => t.IsFaulted ? TryUnwrapException(t.Exception) : null).ToImmutableList()); } - protected override Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr, bool isPermanent) + protected override Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr) { var builder = Builders.Filter; var filter = builder.Eq(x => x.PersistenceId, persistenceId); - var update = Builders.Update.Set(x => x.IsDeleted, true); if (toSequenceNr != long.MaxValue) filter &= builder.Lte(x => x.SequenceNr, toSequenceNr); - if (isPermanent) - return _collection.DeleteManyAsync(filter); - - return _collection.UpdateManyAsync(filter, update); + return _journalCollection.Value.DeleteManyAsync(filter); } private JournalEntry ToJournalEntry(IPersistentRepresentation message) @@ -94,9 +158,26 @@ private JournalEntry ToJournalEntry(IPersistentRepresentation message) }; } - private Persistent ToPersistanceRepresentation(JournalEntry entry, IActorRef sender) + private Persistent ToPersistenceRepresentation(JournalEntry entry, IActorRef sender) { - return new Persistent(entry.Payload, entry.SequenceNr, entry.Manifest, entry.PersistenceId, entry.IsDeleted, sender); + return new Persistent(entry.Payload, entry.SequenceNr, entry.PersistenceId, entry.Manifest, entry.IsDeleted, sender); + } + + private async Task SetHighSequenceId(IList messages) + { + var persistenceId = messages.Select(c => c.PersistenceId).First(); + var highSequenceId = messages.Max(c => c.HighestSequenceNr); + var builder = Builders.Filter; + var filter = builder.Eq(x => x.PersistenceId, persistenceId); + + var metadataEntry = new MetadataEntry + { + Id = persistenceId, + PersistenceId = persistenceId, + SequenceNr = highSequenceId + }; + + await _metadataCollection.Value.ReplaceOneAsync(filter, metadataEntry, new UpdateOptions() { IsUpsert = true }); } } } diff --git a/src/Akka.Persistence.MongoDb/MongoDbExtension.cs b/src/Akka.Persistence.MongoDb/MongoDbExtension.cs deleted file mode 100644 index a52e6ea..0000000 --- a/src/Akka.Persistence.MongoDb/MongoDbExtension.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using Akka.Actor; -using Akka.Persistence.MongoDb.Journal; -using Akka.Persistence.MongoDb.Snapshot; -using MongoDB.Driver; - -namespace Akka.Persistence.MongoDb -{ - /// - /// An actor system extension initializing support for MongoDB persistence layer. - /// - public class MongoDbExtension : IExtension - { - /// - /// The settings for the MongoDb journal. - /// - public MongoDbJournalSettings JournalSettings { get; private set; } - - /// - /// The collection for the MongoDb journal - /// - public IMongoCollection JournalCollection { get; private set; } - - /// - /// The settings for the MongoDB snapshot store. - /// - public MongoDbSnapshotSettings SnapshotStoreSettings { get; private set; } - - /// - /// The collection for the MongoDb snapshot store - /// - public IMongoCollection SnapshotCollection { get; private set; } - - - public MongoDbExtension(ExtendedActorSystem system) - { - if (system == null) - throw new ArgumentNullException("system"); - - // Initialize fallback configuration defaults - system.Settings.InjectTopLevelFallback(MongoDbPersistence.DefaultConfig()); - - // Read config - var journalConfig = system.Settings.Config.GetConfig("akka.persistence.journal.mongodb"); - JournalSettings = new MongoDbJournalSettings(journalConfig); - - var snapshotConfig = system.Settings.Config.GetConfig("akka.persistence.snapshot-store.mongodb"); - SnapshotStoreSettings = new MongoDbSnapshotSettings(snapshotConfig); - - // Create collections - var connectionString = new MongoUrl(JournalSettings.ConnectionString); - var client = new MongoClient(connectionString); - var journalDatabase = client.GetDatabase(connectionString.DatabaseName); - - JournalCollection = journalDatabase.GetCollection(JournalSettings.Collection); - JournalCollection.Indexes.CreateOneAsync( - Builders.IndexKeys.Ascending(entry => entry.PersistenceId) - .Descending(entry => entry.SequenceNr)).Wait(); - - var snapshotDatabase = journalDatabase; - // We only need another client if the connection strings aren't equal, - // because the MongoClient uses the same connection pool for all instances which have the same connection string - if (!JournalSettings.ConnectionString.Equals(SnapshotStoreSettings.ConnectionString)) - { - connectionString = new MongoUrl(SnapshotStoreSettings.ConnectionString); - client = new MongoClient(connectionString); - snapshotDatabase = client.GetDatabase(connectionString.DatabaseName); - } - - SnapshotCollection = snapshotDatabase.GetCollection(SnapshotStoreSettings.Collection); - SnapshotCollection.Indexes.CreateOneAsync( - Builders.IndexKeys.Ascending(entry => entry.PersistenceId) - .Descending(entry => entry.SequenceNr)).Wait(); - } - } -} diff --git a/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs b/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs index b53fb1f..c33e13d 100644 --- a/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs +++ b/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs @@ -1,25 +1,59 @@ -using Akka.Actor; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using Akka.Actor; using Akka.Configuration; namespace Akka.Persistence.MongoDb { /// - /// Extension Id provider for the MongoDB Persistence extension. + /// An actor system extension initializing support for MongoDb persistence layer. /// - public class MongoDbPersistence : ExtensionIdProvider + public class MongoDbPersistence : IExtension { - public static readonly MongoDbPersistence Instance = new MongoDbPersistence(); - - private MongoDbPersistence() { } - - public static Config DefaultConfig() + /// + /// Returns a default configuration for akka persistence MongoDb journal and snapshot store. + /// + /// + public static Config DefaultConfiguration() { return ConfigurationFactory.FromResource("Akka.Persistence.MongoDb.reference.conf"); } - public override MongoDbExtension CreateExtension(ExtendedActorSystem system) + public static MongoDbPersistence Get(ActorSystem system) + { + return system.WithExtension(); + } + + /// + /// The settings for the MongoDb journal. + /// + public MongoDbJournalSettings JournalSettings { get; } + + /// + /// The settings for the MongoDb snapshot store. + /// + public MongoDbSnapshotSettings SnapshotStoreSettings { get; } + + public MongoDbPersistence(ExtendedActorSystem system) { - return new MongoDbExtension(system); + if (system == null) + throw new ArgumentNullException(nameof(system)); + + // Initialize fallback configuration defaults + system.Settings.InjectTopLevelFallback(DefaultConfiguration()); + + // Read config + var journalConfig = system.Settings.Config.GetConfig("akka.persistence.journal.mongodb"); + JournalSettings = new MongoDbJournalSettings(journalConfig); + + var snapshotConfig = system.Settings.Config.GetConfig("akka.persistence.snapshot-store.mongodb"); + SnapshotStoreSettings = new MongoDbSnapshotSettings(snapshotConfig); } } } diff --git a/src/Akka.Persistence.MongoDb/MongoDbPersistenceProvider.cs b/src/Akka.Persistence.MongoDb/MongoDbPersistenceProvider.cs new file mode 100644 index 0000000..88795a2 --- /dev/null +++ b/src/Akka.Persistence.MongoDb/MongoDbPersistenceProvider.cs @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Actor; + +namespace Akka.Persistence.MongoDb +{ + /// + /// Extension Id provider for the MongoDb Persistence extension. + /// + public class MongoDbPersistenceProvider : ExtensionIdProvider + { + /// + /// Creates an actor system extension for akka persistence MongoDb support. + /// + /// + /// + public override MongoDbPersistence CreateExtension(ExtendedActorSystem system) + { + return new MongoDbPersistence(system); + } + } +} diff --git a/src/Akka.Persistence.MongoDb/MongoDbSettings.cs b/src/Akka.Persistence.MongoDb/MongoDbSettings.cs index 6213336..cce522f 100644 --- a/src/Akka.Persistence.MongoDb/MongoDbSettings.cs +++ b/src/Akka.Persistence.MongoDb/MongoDbSettings.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using Akka.Configuration; namespace Akka.Persistence.MongoDb @@ -9,10 +16,15 @@ namespace Akka.Persistence.MongoDb public abstract class MongoDbSettings { /// - /// Connection string used to access the MongoDB, also specifies the database. + /// Connection string used to access the MongoDb, also specifies the database. /// public string ConnectionString { get; private set; } + /// + /// Flag determining in in case of event journal or metadata table missing, they should be automatically initialized. + /// + public bool AutoInitialize { get; private set; } + /// /// Name of the collection for the event journal or snapshots /// @@ -22,6 +34,7 @@ protected MongoDbSettings(Config config) { ConnectionString = config.GetString("connection-string"); Collection = config.GetString("collection"); + AutoInitialize = config.GetBoolean("auto-initialize"); } } @@ -31,11 +44,15 @@ protected MongoDbSettings(Config config) /// public class MongoDbJournalSettings : MongoDbSettings { + public string MetadataCollection { get; private set; } + public MongoDbJournalSettings(Config config) : base(config) { if (config == null) - throw new ArgumentNullException("config", - "MongoDB journal settings cannot be initialized, because required HOCON section couldn't been found"); + throw new ArgumentNullException(nameof(config), + "MongoDb journal settings cannot be initialized, because required HOCON section couldn't been found"); + + MetadataCollection = config.GetString("metadata-collection"); } } @@ -48,8 +65,8 @@ public class MongoDbSnapshotSettings : MongoDbSettings public MongoDbSnapshotSettings(Config config) : base(config) { if (config == null) - throw new ArgumentNullException("config", - "MongoDB snapshot settings cannot be initialized, because required HOCON section couldn't been found"); + throw new ArgumentNullException(nameof(config), + "MongoDb snapshot settings cannot be initialized, because required HOCON section couldn't been found"); } } } diff --git a/src/Akka.Persistence.MongoDb/Snapshot/MongoDbSnapshotStore.cs b/src/Akka.Persistence.MongoDb/Snapshot/MongoDbSnapshotStore.cs index 25d50a9..8e702a5 100644 --- a/src/Akka.Persistence.MongoDb/Snapshot/MongoDbSnapshotStore.cs +++ b/src/Akka.Persistence.MongoDb/Snapshot/MongoDbSnapshotStore.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Threading.Tasks; using Akka.Persistence.Snapshot; using MongoDB.Driver; @@ -10,11 +17,37 @@ namespace Akka.Persistence.MongoDb.Snapshot /// public class MongoDbSnapshotStore : SnapshotStore { - private readonly IMongoCollection _collection; + private readonly MongoDbSnapshotSettings _settings; + private Lazy> _snapshotCollection; public MongoDbSnapshotStore() { - _collection = MongoDbPersistence.Instance.Apply(Context.System).SnapshotCollection; + _settings = MongoDbPersistence.Get(Context.System).SnapshotStoreSettings; + } + + protected override void PreStart() + { + base.PreStart(); + + _snapshotCollection = new Lazy>(() => + { + var connectionString = new MongoUrl(_settings.ConnectionString); + var client = new MongoClient(connectionString); + + var snapshot = client.GetDatabase(connectionString.DatabaseName); + + var collection = snapshot.GetCollection(_settings.Collection); + if (_settings.AutoInitialize) + { + collection.Indexes.CreateOneAsync( + Builders.IndexKeys + .Ascending(entry => entry.PersistenceId) + .Descending(entry => entry.SequenceNr)) + .Wait(); + } + + return collection; + }); } protected override Task LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) @@ -22,31 +55,24 @@ protected override Task LoadAsync(string persistenceId, Snapsh var filter = CreateRangeFilter(persistenceId, criteria); return - _collection + _snapshotCollection.Value .Find(filter) + .SortByDescending(x => x.SequenceNr) + .Limit(1) .Project(x => ToSelectedSnapshot(x)) .FirstOrDefaultAsync(); } - protected override Task SaveAsync(SnapshotMetadata metadata, object snapshot) + protected override async Task SaveAsync(SnapshotMetadata metadata, object snapshot) { - var snapshotEntry = new SnapshotEntry - { - Id = metadata.PersistenceId + "_" + metadata.SequenceNr, - PersistenceId = metadata.PersistenceId, - SequenceNr = metadata.SequenceNr, - Snapshot = snapshot, - Timestamp = metadata.Timestamp.Ticks - }; + var snapshotEntry = ToSnapshotEntry(metadata, snapshot); - // throws a MongoWriteException if s snapshot with the same PersistenceId and SequenceNr - // is inserted the second time. As @Horusiath pointed out, that's fine, because a second snapshot - // without any events in the meantime doesn't make any sense. - return _collection.InsertOneAsync(snapshotEntry); + await _snapshotCollection.Value.ReplaceOneAsync( + CreateSnapshotIdFilter(snapshotEntry.Id), + snapshotEntry, + new UpdateOptions { IsUpsert = true }); } - protected override void Saved(SnapshotMetadata metadata) { } - protected override Task DeleteAsync(SnapshotMetadata metadata) { var builder = Builders.Filter; @@ -58,14 +84,23 @@ protected override Task DeleteAsync(SnapshotMetadata metadata) if (metadata.Timestamp != DateTime.MinValue && metadata.Timestamp != DateTime.MaxValue) filter &= builder.Eq(x => x.Timestamp, metadata.Timestamp.Ticks); - return _collection.FindOneAndDeleteAsync(filter); + return _snapshotCollection.Value.FindOneAndDeleteAsync(filter); } protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); - return _collection.DeleteManyAsync(filter); + return _snapshotCollection.Value.DeleteManyAsync(filter); + } + + private static FilterDefinition CreateSnapshotIdFilter(string snapshotId) + { + var builder = Builders.Filter; + + var filter = builder.Eq(x => x.Id, snapshotId); + + return filter; } private static FilterDefinition CreateRangeFilter(string persistenceId, SnapshotSelectionCriteria criteria) @@ -81,13 +116,22 @@ private static FilterDefinition CreateRangeFilter(string persiste return filter; } - - private SelectedSnapshot ToSelectedSnapshot(SnapshotEntry entry) + + private static SnapshotEntry ToSnapshotEntry(SnapshotMetadata metadata, object snapshot) { - return - new SelectedSnapshot( - new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr, new DateTime(entry.Timestamp)), - entry.Snapshot); + return new SnapshotEntry + { + Id = metadata.PersistenceId + "_" + metadata.SequenceNr, + PersistenceId = metadata.PersistenceId, + SequenceNr = metadata.SequenceNr, + Snapshot = snapshot, + Timestamp = metadata.Timestamp.Ticks + }; + } + + private static SelectedSnapshot ToSelectedSnapshot(SnapshotEntry entry) + { + return new SelectedSnapshot(new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr, new DateTime(entry.Timestamp)), entry.Snapshot); } } } diff --git a/src/Akka.Persistence.MongoDb/Snapshot/SnapshotEntry.cs b/src/Akka.Persistence.MongoDb/Snapshot/SnapshotEntry.cs index 11f38eb..421b73e 100644 --- a/src/Akka.Persistence.MongoDb/Snapshot/SnapshotEntry.cs +++ b/src/Akka.Persistence.MongoDb/Snapshot/SnapshotEntry.cs @@ -1,3 +1,10 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + using MongoDB.Bson.Serialization.Attributes; namespace Akka.Persistence.MongoDb.Snapshot diff --git a/src/Akka.Persistence.MongoDb/app.config b/src/Akka.Persistence.MongoDb/app.config new file mode 100644 index 0000000..8460dd4 --- /dev/null +++ b/src/Akka.Persistence.MongoDb/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/packages.config b/src/Akka.Persistence.MongoDb/packages.config index 11ec680..30d01c6 100644 --- a/src/Akka.Persistence.MongoDb/packages.config +++ b/src/Akka.Persistence.MongoDb/packages.config @@ -1,10 +1,11 @@  - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/reference.conf b/src/Akka.Persistence.MongoDb/reference.conf index d045980..81e8b97 100644 --- a/src/Akka.Persistence.MongoDb/reference.conf +++ b/src/Akka.Persistence.MongoDb/reference.conf @@ -1,13 +1,23 @@ -akka.persistence{ +akka.persistence { journal { mongodb { - - # qualified type name of the MongoDB persistence journal actor + # qualified type name of the MongoDb persistence journal actor class = "Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb" - connection-string = "mongodb://localhost/akkanet" + # connection string used for database access + connection-string = "" + # should corresponding journal table's indexes be initialized automatically + auto-initialize = off + + # dispatcher used to drive journal actor + plugin-dispatcher = "akka.actor.default-dispatcher" + + # MongoDb collection corresponding with persistent journal collection = "EventJournal" + + # metadata collection + metadata-collection = "Metadata" } } @@ -16,8 +26,16 @@ # qualified type name of the MongoDB persistence snapshot actor class = "Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb" - connection-string = "mongodb://localhost/akkanet" + # connection string used for database access + connection-string = "" + + # should corresponding snapshot's indexes be initialized automatically + auto-initialize = off + + # dispatcher used to drive snapshot storage actor + plugin-dispatcher = "akka.actor.default-dispatcher" + # MongoDb collection corresponding with persistent snapshot store collection = "SnapshotStore" } } diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index fcb5f36..73a687b 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Reflection; [assembly: AssemblyCompanyAttribute("Akka.NET Team")] -[assembly: AssemblyCopyrightAttribute("Copyright © 2013-2015 Akka.NET Team")] +[assembly: AssemblyCopyrightAttribute("Copyright © 2013-2016 Akka.NET Team")] [assembly: AssemblyTrademarkAttribute("")] -[assembly: AssemblyVersionAttribute("1.0.5.0")] -[assembly: AssemblyFileVersionAttribute("1.0.5.0")] +[assembly: AssemblyVersionAttribute("1.1.0.0")] +[assembly: AssemblyFileVersionAttribute("1.1.0.0")] From 622c78b1d8c58c65dc1bef7609fc7c07a5272c28 Mon Sep 17 00:00:00 2001 From: ravengerUA Date: Mon, 25 Jul 2016 13:37:06 +0300 Subject: [PATCH 3/9] Updated MongoDb provider to Akka 1.1.1 From d65b991f89c2fb205505ecbfe80589ac9d2231c8 Mon Sep 17 00:00:00 2001 From: Jack Wild Date: Wed, 11 Oct 2017 18:30:20 +0100 Subject: [PATCH 4/9] Update akka packages to 1.3.2. Added .NET standard support. --- .gitignore | 3 + RELEASE_NOTES.md | 39 ++++ .../Akka.Persistence.MongoDb.Tests.csproj | 198 ++++-------------- src/Akka.Persistence.MongoDb.Tests/App.config | 18 -- .../DatabaseFixture.cs | 30 +++ .../MongoDbJournalSpec.cs | 65 ++---- .../MongoDbSnapshotStoreSpec.cs | 64 ++---- .../Properties/AssemblyInfo.cs | 20 -- .../packages.config | 23 -- .../Akka.Persistence.MongoDb.csproj | 129 ++---------- .../Akka.Persistence.MongoDb.nuspec | 20 -- .../Properties/AssemblyInfo.cs | 20 -- src/Akka.Persistence.MongoDb/app.config | 11 - src/Akka.Persistence.MongoDb/packages.config | 11 - src/SharedAssemblyInfo.cs | 8 - 15 files changed, 170 insertions(+), 489 deletions(-) delete mode 100644 src/Akka.Persistence.MongoDb.Tests/App.config create mode 100644 src/Akka.Persistence.MongoDb.Tests/DatabaseFixture.cs delete mode 100644 src/Akka.Persistence.MongoDb.Tests/Properties/AssemblyInfo.cs delete mode 100644 src/Akka.Persistence.MongoDb.Tests/packages.config delete mode 100644 src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec delete mode 100644 src/Akka.Persistence.MongoDb/Properties/AssemblyInfo.cs delete mode 100644 src/Akka.Persistence.MongoDb/app.config delete mode 100644 src/Akka.Persistence.MongoDb/packages.config delete mode 100644 src/SharedAssemblyInfo.cs diff --git a/.gitignore b/.gitignore index e30ee6c..fea72d9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ us.stackdump *.user *.sln.docstates +# Visual Studio 2015 cache/options directory +.vs/ + #MonoDevelop *.userprefs diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 000cd2d..2a3abfe 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,45 @@ +#### 1.3.1 October 11 2017 #### +Support for Akka.NET 1.3, .NET Standard 1.6, and the first stable RTM release of Akka.Persistence. + #### 1.1.0 July 30 2016 #### Updated to Akka.Persistence 1.1.1 +**Migration from 1.0.5 Up** +As of 1.1.0, the highest SequenceNr for each PersistenceId in the EventJournal collection is kept in a separate collection, Metadata. +This script creates the Metadata collection, then finds the highest SequenceNr for each persistence id from the EventJournal and adds it to the Metadata collection. + +To run, save this to a JavaScript file, update {your_database_address} e.g. 127.0.0.1:27017/events. Run: mongo {file_name}.js +```javascript +try { + var db = connect('{your_database_address}'); + + var persistenceIds = db.EventJournal.distinct('PersistenceId'); + + persistenceIds.forEach(persistenceId => { + print('Finding highest SequenceNr for PersistenceId: ' + persistenceId); + var highestSequenceNr = db.EventJournal + .find({ PersistenceId: persistenceId }, { SequenceNr: true }) + .sort({ SequenceNr: -1 }) + .limit(1) + .next() + .SequenceNr; + + print('Highest SequenceNr found ' + highestSequenceNr + ', inserting into Metadata table...'); + db.Metadata.insertOne( + { + _id: persistenceId, + PersistenceId: persistenceId, + SequenceNr: highestSequenceNr + } + ); + + print('Inserted successfully'); + }); +} catch(e) { + print(e); +} +``` + #### 1.0.5 August 08 2015 #### #### 1.0.4 August 07 2015 #### diff --git a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj index 7ced513..81b9d4a 100644 --- a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj +++ b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj @@ -1,166 +1,38 @@  - - - - - Debug - AnyCPU - {32A2ACBE-8A3C-4093-8C13-D65B113B3327} - Library - Properties - Akka.Persistence.MongoDb.Tests - Akka.Persistence.MongoDb.Tests - v4.5 - 512 - - - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Akka.1.1.1\lib\net45\Akka.dll - True - - - ..\packages\Akka.Persistence.1.1.1.28-beta\lib\net45\Akka.Persistence.dll - True - - - ..\packages\Akka.Persistence.TestKit.1.1.1.28-beta\lib\net45\Akka.Persistence.TestKit.dll - True - - - ..\packages\Akka.TestKit.1.1.1\lib\net45\Akka.TestKit.dll - True - - - ..\packages\Akka.TestKit.Xunit2.1.1.1\lib\net45\Akka.TestKit.Xunit2.dll - True - - - ..\packages\FluentAssertions.4.12.0\lib\net45\FluentAssertions.dll - True - - - ..\packages\FluentAssertions.4.12.0\lib\net45\FluentAssertions.Core.dll - True - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll - True - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - - - ..\packages\Mongo2Go.0.2.0\lib\net35\Mongo2Go.dll - True - - - ..\packages\MongoDB.Bson.2.2.4\lib\net45\MongoDB.Bson.dll - True - - - ..\packages\MongoDB.Driver.2.2.4\lib\net45\MongoDB.Driver.dll - True - - - ..\packages\MongoDB.Driver.Core.2.2.4\lib\net45\MongoDB.Driver.Core.dll - True - - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - - - - - - - - - - - ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True - - - ..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True - - - ..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - {12e044ef-08a2-428b-aaf5-c3d328860c4e} - Akka.Persistence.MongoDb - - - - - Designer - - - Designer - - - - - - - + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + Akka.Persistence.MongoDB.Tests + net461;netcoreapp1.1 + akka;actors;actor model;Akka;concurrency;MongoDB + Copyright © 2013-2017 + Akka.NET Contrib + 1.3.1 + http://getakka.net/images/akkalogo.png + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB/blob/master/LICENSE.md + true + $(NoWarn);CS1591 - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + $(DefineConstants);RELEASE + + + + + + diff --git a/src/Akka.Persistence.MongoDb.Tests/App.config b/src/Akka.Persistence.MongoDb.Tests/App.config deleted file mode 100644 index 408e986..0000000 --- a/src/Akka.Persistence.MongoDb.Tests/App.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Akka.Persistence.MongoDb.Tests/DatabaseFixture.cs b/src/Akka.Persistence.MongoDb.Tests/DatabaseFixture.cs new file mode 100644 index 0000000..ed08b7d --- /dev/null +++ b/src/Akka.Persistence.MongoDb.Tests/DatabaseFixture.cs @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using Mongo2Go; +using System; + +namespace Akka.Persistence.MongoDb.Tests +{ + public class DatabaseFixture : IDisposable + { + private MongoDbRunner _runner; + + public string ConnectionString { get; private set; } + + public DatabaseFixture() + { + _runner = MongoDbRunner.Start(); + ConnectionString = _runner.ConnectionString + "akkanet"; + } + + public void Dispose() + { + _runner.Dispose(); + } + } +} diff --git a/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs b/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs index 3575e20..38f059a 100644 --- a/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs +++ b/src/Akka.Persistence.MongoDb.Tests/MongoDbJournalSpec.cs @@ -5,63 +5,40 @@ // //----------------------------------------------------------------------- -using System; -using System.Configuration; -using Akka.Persistence.TestKit.Journal; -using Mongo2Go; -using MongoDB.Driver; +using Akka.Persistence.TCK.Journal; using Xunit; +using Akka.Configuration; namespace Akka.Persistence.MongoDb.Tests { [Collection("MongoDbSpec")] - public class MongoDbJournalSpec : JournalSpec + public class MongoDbJournalSpec : JournalSpec, IClassFixture { - private static readonly MongoDbRunner Runner = MongoDbRunner.Start(ConfigurationManager.AppSettings[0]); + protected override bool SupportsRejectingNonSerializableObjects { get; } = false; - protected override bool SupportsRejectingNonSerializableObjects { get; } = false; - - private static readonly string SpecConfig = @" - akka.test.single-expect-default = 3s - akka.persistence { - publish-plugin-commands = on - journal { - plugin = ""akka.persistence.journal.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb"" - connection-string = """" - auto-initialize = on - collection = ""EventJournal"" - } - } - }"; - - public MongoDbJournalSpec() : base(CreateSpecConfig(), "MongoDbJournalSpec") + public MongoDbJournalSpec(DatabaseFixture databaseFixture) : base(CreateSpecConfig(databaseFixture), "MongoDbJournalSpec") { - AppDomain.CurrentDomain.DomainUnload += (_, __) => - { - try - { - Runner.Dispose(); - } - catch { } - }; - Initialize(); } - private static string CreateSpecConfig() + private static Config CreateSpecConfig(DatabaseFixture databaseFixture) { - return SpecConfig.Replace("", Runner.ConnectionString + "akkanet"); - } + var specString = @" + akka.test.single-expect-default = 3s + akka.persistence { + publish-plugin-commands = on + journal { + plugin = ""akka.persistence.journal.mongodb"" + mongodb { + class = ""Akka.Persistence.MongoDb.Journal.MongoDbJournal, Akka.Persistence.MongoDb"" + connection-string = """ + databaseFixture.ConnectionString + @""" + auto-initialize = on + collection = ""EventJournal"" + } + } + }"; - protected override void Dispose(bool disposing) - { - new MongoClient(Runner.ConnectionString) - .GetDatabase("akkanet") - .DropCollectionAsync("EventJournal").Wait(); - - base.Dispose(disposing); + return ConfigurationFactory.ParseString(specString); } } } diff --git a/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs b/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs index a945894..87d9a4e 100644 --- a/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs +++ b/src/Akka.Persistence.MongoDb.Tests/MongoDbSnapshotStoreSpec.cs @@ -5,62 +5,38 @@ // //----------------------------------------------------------------------- -using System; -using System.Configuration; -using Akka.Persistence.TestKit.Snapshot; -using Mongo2Go; -using MongoDB.Driver; using Xunit; +using Akka.Persistence.TCK.Snapshot; +using Akka.Configuration; namespace Akka.Persistence.MongoDb.Tests { [Collection("MongoDbSpec")] - public class MongoDbSnapshotStoreSpec : SnapshotStoreSpec + public class MongoDbSnapshotStoreSpec : SnapshotStoreSpec, IClassFixture { - private static readonly MongoDbRunner Runner = MongoDbRunner.Start(ConfigurationManager.AppSettings[0]); - - private static readonly string SpecConfig = @" - akka.test.single-expect-default = 3s - akka.persistence { - publish-plugin-commands = on - snapshot-store { - plugin = ""akka.persistence.snapshot-store.mongodb"" - mongodb { - class = ""Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb"" - connection-string = """" - auto-initialize = on - collection = ""SnapshotStore"" - } - } - }"; - - public MongoDbSnapshotStoreSpec() : base(CreateSpecConfig(), "MongoDbSnapshotStoreSpec") + public MongoDbSnapshotStoreSpec(DatabaseFixture databaseFixture) : base(CreateSpecConfig(databaseFixture), "MongoDbSnapshotStoreSpec") { - AppDomain.CurrentDomain.DomainUnload += (_, __) => - { - try - { - Runner.Dispose(); - } - catch { } - }; - - Initialize(); } - private static string CreateSpecConfig() + private static Config CreateSpecConfig(DatabaseFixture databaseFixture) { - return SpecConfig.Replace("", Runner.ConnectionString + "akkanet"); - } - - protected override void Dispose(bool disposing) - { - new MongoClient(Runner.ConnectionString) - .GetDatabase("akkanet") - .DropCollectionAsync("SnapshotStore").Wait(); + var specString = @" + akka.test.single-expect-default = 3s + akka.persistence { + publish-plugin-commands = on + snapshot-store { + plugin = ""akka.persistence.snapshot-store.mongodb"" + mongodb { + class = ""Akka.Persistence.MongoDb.Snapshot.MongoDbSnapshotStore, Akka.Persistence.MongoDb"" + connection-string = """ + databaseFixture.ConnectionString + @""" + auto-initialize = on + collection = ""SnapshotStore"" + } + } + }"; - base.Dispose(disposing); + return ConfigurationFactory.ParseString(specString); } } } diff --git a/src/Akka.Persistence.MongoDb.Tests/Properties/AssemblyInfo.cs b/src/Akka.Persistence.MongoDb.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 5b563a9..0000000 --- a/src/Akka.Persistence.MongoDb.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("Akka.Persistence.MongoDb.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Akka.Persistence.MongoDb.Tests")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("32a2acbe-8a3c-4093-8c13-d65b113b3327")] diff --git a/src/Akka.Persistence.MongoDb.Tests/packages.config b/src/Akka.Persistence.MongoDb.Tests/packages.config deleted file mode 100644 index c1c634d..0000000 --- a/src/Akka.Persistence.MongoDb.Tests/packages.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj index eb364be..cddebaa 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj @@ -1,117 +1,32 @@  - - + - Debug - AnyCPU - {12E044EF-08A2-428B-AAF5-C3D328860C4E} - Library - Properties - Akka.Persistence.MongoDb - Akka.Persistence.MongoDb - v4.5 - 512 - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + Akka.Persistence.MongoDB + Akka Persistence journal and snapshot store backed by MongoDB database. + net45;netstandard1.6 + akka;actors;actor model;Akka;concurrency;MongoDB + Copyright © 2013-2017 + Akka.NET Contrib + 1.3.1 + http://getakka.net/images/akkalogo.png + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB/blob/master/LICENSE.md + Support for Akka.NET 1.3, .NET Standard 1.6, and the first stable RTM release of Akka.Persistence. + true + $(NoWarn);CS1591 - - ..\packages\Akka.1.1.1\lib\net45\Akka.dll - True - - - ..\packages\Akka.Persistence.1.1.1.28-beta\lib\net45\Akka.Persistence.dll - True - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll - True - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - - - ..\packages\MongoDB.Bson.2.2.4\lib\net45\MongoDB.Bson.dll - True - - - ..\packages\MongoDB.Driver.2.2.4\lib\net45\MongoDB.Driver.dll - True - - - ..\packages\MongoDB.Driver.Core.2.2.4\lib\net45\MongoDB.Driver.Core.dll - True - - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - - - - - - - - + - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - + - - - - - Designer - + + + - - - - - 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}. - - - - + + $(DefineConstants);RELEASE + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec deleted file mode 100644 index 4cd912f..0000000 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.nuspec +++ /dev/null @@ -1,20 +0,0 @@ - - - - @project@ - @project@@title@ - @build.number@ - @authors@ - @authors@ - Akka.NET Persistence journal and snapshot store backed by MongoDB. - https://github.com/akkadotnet/akka.net/blob/master/LICENSE - https://github.com/akkadotnet/Akka.Persistence.MongoDB - http://getakka.net/images/AkkaNetLogo.Normal.png - false - @releaseNotes@ - @copyright@ - @tags@ persistence eventsource mongodb mongo - @dependencies@ - @references@ - - diff --git a/src/Akka.Persistence.MongoDb/Properties/AssemblyInfo.cs b/src/Akka.Persistence.MongoDb/Properties/AssemblyInfo.cs deleted file mode 100644 index 8b4cdd1..0000000 --- a/src/Akka.Persistence.MongoDb/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("Akka.Persistence.MongoDb")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Akka.Persistence.MongoDb")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("12e044ef-08a2-428b-aaf5-c3d328860c4e")] diff --git a/src/Akka.Persistence.MongoDb/app.config b/src/Akka.Persistence.MongoDb/app.config deleted file mode 100644 index 8460dd4..0000000 --- a/src/Akka.Persistence.MongoDb/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb/packages.config b/src/Akka.Persistence.MongoDb/packages.config deleted file mode 100644 index 30d01c6..0000000 --- a/src/Akka.Persistence.MongoDb/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs deleted file mode 100644 index 73a687b..0000000 --- a/src/SharedAssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -// -using System.Reflection; - -[assembly: AssemblyCompanyAttribute("Akka.NET Team")] -[assembly: AssemblyCopyrightAttribute("Copyright © 2013-2016 Akka.NET Team")] -[assembly: AssemblyTrademarkAttribute("")] -[assembly: AssemblyVersionAttribute("1.1.0.0")] -[assembly: AssemblyFileVersionAttribute("1.1.0.0")] From d3ad6472af6d73220ee0a8d5941a78668c505c63 Mon Sep 17 00:00:00 2001 From: Maxim Date: Fri, 9 Feb 2018 15:57:46 +0100 Subject: [PATCH 5/9] upgrade akka to 1.3.4 --- .../Akka.Persistence.MongoDb.Tests.csproj | 6 +++--- .../Akka.Persistence.MongoDb.csproj | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj index 81b9d4a..e084707 100644 --- a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj +++ b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj @@ -16,10 +16,10 @@ - - + + - + diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj index cddebaa..04bd4f3 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj @@ -22,8 +22,8 @@ - - + + From 67a9c157ee8b9575e0d8b0c28e8e437f621e2711 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Fri, 16 Mar 2018 15:15:11 -0500 Subject: [PATCH 6/9] close #36 - build system upgrade --- .gitignore | 180 ++++-- Akka.Persistence.MongoDb.sln | 45 ++ RELEASE_NOTES.md | 3 + build.cmd | 20 +- build.fsx | 561 +++++++----------- build.ps1 | 162 +++++ build.sh | 103 +++- docs/api/index.md | 1 + docs/articles/index.md | 3 + docs/articles/toc.yml | 2 + docs/docfx.json | 67 +++ docs/images/icon.png | Bin 0 -> 841 bytes docs/index.md | 1 + docs/toc.yml | 6 + serve-docs.cmd | 1 + serve-docs.ps1 | 21 + ...rsistence.MongoDb.Tests.Performance.csproj | 18 + .../UnitTest1.cs | 26 + .../Akka.Persistence.MongoDb.Tests.csproj | 58 +- src/Akka.Persistence.MongoDb.sln | 45 -- .../Akka.Persistence.MongoDb.csproj | 21 +- src/common.props | 18 + 22 files changed, 839 insertions(+), 523 deletions(-) create mode 100644 Akka.Persistence.MongoDb.sln create mode 100644 build.ps1 create mode 100644 docs/api/index.md create mode 100644 docs/articles/index.md create mode 100644 docs/articles/toc.yml create mode 100644 docs/docfx.json create mode 100644 docs/images/icon.png create mode 100644 docs/index.md create mode 100644 docs/toc.yml create mode 100644 serve-docs.cmd create mode 100644 serve-docs.ps1 create mode 100644 src/Akka.Persistence.MongoDb.Tests.Performance/Akka.Persistence.MongoDb.Tests.Performance.csproj create mode 100644 src/Akka.Persistence.MongoDb.Tests.Performance/UnitTest1.cs delete mode 100644 src/Akka.Persistence.MongoDb.sln create mode 100644 src/common.props diff --git a/.gitignore b/.gitignore index fea72d9..3ae1c36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,23 @@ -# Akka - -# Fake directories -src/.build/** - - - -#GitExtensions -us.stackdump - -#KDiff3 and other git merge tools -*.orig - -#------------------------------------------------------------------------------- -#Based on https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# Custom +tools/ +build/ +.nuget/ +.dotnet/ +.idea/ +.[Dd][Ss]_[Ss]tore ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user +*.userosscache *.sln.docstates -# Visual Studio 2015 cache/options directory -.vs/ - -#MonoDevelop +# User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results @@ -35,19 +27,28 @@ us.stackdump [Rr]eleases/ x64/ x86/ -build/ bld/ [Bb]in/ [Oo]bj/ +[Ll]og/ + +#FAKE +.fake +tools/ + +#DocFx output +_site/ -# Roslyn cache directories -*.ide/ +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -#NUNIT +# NUNIT *.VisualState.xml TestResult.xml @@ -56,6 +57,12 @@ TestResult.xml [Rr]eleasePS/ dlldata.c +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + *_i.c *_p.c *_i.h @@ -88,14 +95,18 @@ _Chutzpah* ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap # TFS 2012 Local Workspace $tf/ @@ -108,7 +119,7 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding addin-in +# JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in @@ -117,9 +128,14 @@ _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch _NCrunch_* .*crunch*.local.xml +nCrunchTemp_* # MightyMoose *.mm.* @@ -147,8 +163,15 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment out the next line if you want to keep your passwords hidden +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted *.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ # NuGet Packages *.nupkg @@ -156,28 +179,46 @@ publish/ **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -!**/packages/repositories.config +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets -# Windows Azure Build Output +# Microsoft Azure Build Output csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview +*.jfm *.pfx *.publishsettings -node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ @@ -193,10 +234,7 @@ UpgradeLog*.htm # SQL Server files *.mdf *.ldf - -# make exception for Akka.Persistence.SqlServer database file -!AkkaPersistenceSqlServerSpecDb.mdf -!AkkaPersistenceSqlServerSpecDb_log.ldf +*.ndf # Business Intelligence projects *.rdl.data @@ -205,15 +243,61 @@ UpgradeLog*.htm # Microsoft Fakes FakesAssemblies/ -/src/.Akka.boltdata/NCover/Executions/0.jf -/src/.Akka.boltdata/NCover/Executions/ProjectId/0.jf -/src/.Akka.boltdata/NCover/Executions/ProjectOrderIndex/0.jf -/src/.Akka.boltdata/NCover/Projects/0.jf -/src/.Akka.boltdata/NCover/Projects/Name/0.jf -/src/.Akka.boltdata/Settings.json -/src/.Akka.boltdata/TestResults.json -resetdev.bat -/src/packages/repositories.config - -# FAKE build folder + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make .fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs diff --git a/Akka.Persistence.MongoDb.sln b/Akka.Persistence.MongoDb.sln new file mode 100644 index 0000000..9498ffa --- /dev/null +++ b/Akka.Persistence.MongoDb.sln @@ -0,0 +1,45 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.MongoDb", "src\Akka.Persistence.MongoDb\Akka.Persistence.MongoDb.csproj", "{E945AABA-2779-41E8-9B43-8898FFD64F22}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.MongoDb.Tests", "src\Akka.Persistence.MongoDb.Tests\Akka.Persistence.MongoDb.Tests.csproj", "{0F9B9BC6-9F86-40E8-BA9B-D27BF3AC7970}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.MongoDb.Tests.Performance", "src\Akka.Persistence.MongoDb.Tests.Performance\Akka.Persistence.MongoDb.Tests.Performance.csproj", "{CAE7CA7C-0D0C-4FDA-BDE9-BE16A27343EF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{BE1178E1-2069-4762-82E5-43805913DCB8}" + ProjectSection(SolutionItems) = preProject + build.cmd = build.cmd + build.fsx = build.fsx + build.ps1 = build.ps1 + build.sh = build.sh + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E945AABA-2779-41E8-9B43-8898FFD64F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E945AABA-2779-41E8-9B43-8898FFD64F22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E945AABA-2779-41E8-9B43-8898FFD64F22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E945AABA-2779-41E8-9B43-8898FFD64F22}.Release|Any CPU.Build.0 = Release|Any CPU + {0F9B9BC6-9F86-40E8-BA9B-D27BF3AC7970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F9B9BC6-9F86-40E8-BA9B-D27BF3AC7970}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F9B9BC6-9F86-40E8-BA9B-D27BF3AC7970}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F9B9BC6-9F86-40E8-BA9B-D27BF3AC7970}.Release|Any CPU.Build.0 = Release|Any CPU + {CAE7CA7C-0D0C-4FDA-BDE9-BE16A27343EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAE7CA7C-0D0C-4FDA-BDE9-BE16A27343EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAE7CA7C-0D0C-4FDA-BDE9-BE16A27343EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAE7CA7C-0D0C-4FDA-BDE9-BE16A27343EF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D4F3F966-EB9C-443A-8158-419703A68B92} + EndGlobalSection +EndGlobal diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2a3abfe..fd192ab 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +#### 1.3.5 March 16 2018 #### +Support for Akka.NET 1.3.5 and upgraded MongoDb drivers et al. + #### 1.3.1 October 11 2017 #### Support for Akka.NET 1.3, .NET Standard 1.6, and the first stable RTM release of Akka.Persistence. diff --git a/build.cmd b/build.cmd index 5457002..3cb534e 100644 --- a/build.cmd +++ b/build.cmd @@ -1,19 +1 @@ -@echo off - -pushd %~dp0 - -src\.nuget\NuGet.exe update -self - -src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.35.0 - -src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.1.0 - -if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( - src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 1.1.0 -) -rem cls - -set encoding=utf-8 -src\packages\FAKE\tools\FAKE.exe build.fsx %* - -popd +PowerShell.exe -file "build.ps1" %* \ No newline at end of file diff --git a/build.fsx b/build.fsx index f6f600a..892e3b8 100644 --- a/build.fsx +++ b/build.fsx @@ -1,291 +1,232 @@ -#I @"src/packages/FAKE/tools" +#I @"tools/FAKE/tools" #r "FakeLib.dll" -#r "System.Xml.Linq" open System open System.IO open System.Text -open Fake -open Fake.FileUtils -open Fake.TaskRunnerHelper -open Fake.ProcessHelper -cd __SOURCE_DIRECTORY__ +open Fake +open Fake.DotNetCli +open Fake.DocFxHelper -//-------------------------------------------------------------------------------- // Information about the project for Nuget and Assembly info files -//-------------------------------------------------------------------------------- - - -let product = "Akka.NET" -let authors = [ "Akka.NET Team" ] -let copyright = "Copyright © 2013-2016 Akka.NET Team" -let company = "Akka.NET Team" -let description = "Akka.NET is a port of the popular Java/Scala framework Akka to .NET" -let tags = ["akka";"actors";"actor";"model";"Akka";"concurrency"] +let product = "Akka.Persistence.MongoDb" +let authors = [ "Your name here" ] +let copyright = "Copyright © 2017" +let company = "Your name here" +let description = "Your description here" +let tags = ["";] let configuration = "Release" // Read release notes and version - -let parsedRelease = - File.ReadLines "RELEASE_NOTES.md" +let solutionFile = FindFirstMatchingFile "*.sln" __SOURCE_DIRECTORY__ // dynamically look up the solution +let buildNumber = environVarOrDefault "BUILD_NUMBER" "0" +let hasTeamCity = (not (buildNumber = "0")) // check if we have the TeamCity environment variable for build # set +let preReleaseVersionSuffix = (if (not (buildNumber = "0")) then (buildNumber) else "") + "-beta" +let versionSuffix = + match (getBuildParam "nugetprerelease") with + | "dev" -> preReleaseVersionSuffix + | _ -> "" + +let releaseNotes = + File.ReadLines "./RELEASE_NOTES.md" |> ReleaseNotesHelper.parseReleaseNotes -let envBuildNumber = System.Environment.GetEnvironmentVariable("BUILD_NUMBER") -let buildNumber = if String.IsNullOrWhiteSpace(envBuildNumber) then "0" else envBuildNumber - -let version = parsedRelease.AssemblyVersion + "." + buildNumber -let preReleaseVersion = version + "-beta" - -let isUnstableDocs = hasBuildParam "unstable" -let isPreRelease = hasBuildParam "nugetprerelease" -let release = if isPreRelease then ReleaseNotesHelper.ReleaseNotes.New(version, version + "-beta", parsedRelease.Notes) else parsedRelease - -printfn "Assembly version: %s\nNuget version; %s\n" release.AssemblyVersion release.NugetVersion -//-------------------------------------------------------------------------------- // Directories - -let binDir = "bin" -let testOutput = "TestResults" - -let nugetDir = binDir @@ "nuget" -let workingDir = binDir @@ "build" -let libDir = workingDir @@ @"lib\net45\" -let nugetExe = FullName @"src\.nuget\NuGet.exe" -let slnFile = "./src/Akka.Persistence.MongoDB.sln" - -open Fake.RestorePackageHelper -Target "RestorePackages" (fun _ -> - slnFile - |> RestoreMSSolutionPackages (fun p -> - { p with - OutputPath = "./src/packages" - Retries = 4 }) - ) - -//-------------------------------------------------------------------------------- -// Clean build results - -Target "Clean" <| fun _ -> - DeleteDir binDir - -//-------------------------------------------------------------------------------- -// Generate AssemblyInfo files with the version for release notes - -open AssemblyInfoFile - -Target "AssemblyInfo" <| fun _ -> - CreateCSharpAssemblyInfoWithConfig "src/SharedAssemblyInfo.cs" [ - Attribute.Company company - Attribute.Copyright copyright - Attribute.Trademark "" - Attribute.Version version - Attribute.FileVersion version ] <| AssemblyInfoFileConfig(false) - - -//-------------------------------------------------------------------------------- -// Build the solution - -Target "Build" <| fun _ -> - - !! slnFile - |> MSBuildRelease "" "Rebuild" - |> ignore - +let toolsDir = __SOURCE_DIRECTORY__ @@ "tools" +let output = __SOURCE_DIRECTORY__ @@ "bin" +let outputTests = __SOURCE_DIRECTORY__ @@ "TestResults" +let outputPerfTests = __SOURCE_DIRECTORY__ @@ "PerfResults" +let outputNuGet = output @@ "nuget" + +// Copied from original NugetCreate target +let nugetDir = output @@ "nuget" +let workingDir = output @@ "build" +let nugetExe = FullName @"./tools/nuget.exe" + +Target "Clean" (fun _ -> + CleanDir output + CleanDir outputTests + CleanDir outputPerfTests + CleanDir outputNuGet + CleanDir "docs/_site" + CleanDirs !! "./**/bin" + CleanDirs !! "./**/obj" +) + +Target "AssemblyInfo" (fun _ -> + XmlPokeInnerText "./src/common.props" "//Project/PropertyGroup/VersionPrefix" releaseNotes.AssemblyVersion + XmlPokeInnerText "./src/common.props" "//Project/PropertyGroup/PackageReleaseNotes" (releaseNotes.Notes |> String.concat "\n") +) + +Target "RestorePackages" (fun _ -> + DotNetCli.Restore + (fun p -> + { p with + Project = solutionFile + NoCache = false }) +) + +Target "Build" (fun _ -> + let runSingleProject project = + DotNetCli.Build + (fun p -> + { p with + Project = project + Configuration = configuration + AdditionalArgs = ["--no-incremental"]}) // "Rebuild" + + let assemblies = !! "./src/**/*.csproj" + + assemblies |> Seq.iter (runSingleProject) +) //-------------------------------------------------------------------------------- -// Copy the build output to bin directory +// Tests targets //-------------------------------------------------------------------------------- - -Target "CopyOutput" <| fun _ -> +module internal ResultHandling = + let (|OK|Failure|) = function + | 0 -> OK + | x -> Failure x + + let buildErrorMessage = function + | OK -> None + | Failure errorCode -> + Some (sprintf "xUnit2 reported an error (Error Code %d)" errorCode) + + let failBuildWithMessage = function + | DontFailBuild -> traceError + | _ -> (fun m -> raise(FailedTestsException m)) + + let failBuildIfXUnitReportedError errorLevel = + buildErrorMessage + >> Option.iter (failBuildWithMessage errorLevel) + +Target "RunTests" (fun _ -> + let projects = + match (isWindows) with + | true -> !! "./src/**/*.Tests.csproj" + | _ -> !! "./src/**/*.Tests.csproj" // if you need to filter specs for Linux vs. Windows, do it here + + let runSingleProject project = + let arguments = + match (hasTeamCity) with + | true -> (sprintf "xunit -c Release -nobuild -parallel none -teamcity -xml %s_xunit.xml" (outputTests @@ fileNameWithoutExt project)) + | false -> (sprintf "xunit -c Release -nobuild -parallel none -xml %s_xunit.xml" (outputTests @@ fileNameWithoutExt project)) + + let result = ExecProcess(fun info -> + info.FileName <- "dotnet" + info.WorkingDirectory <- (Directory.GetParent project).FullName + info.Arguments <- arguments) (TimeSpan.FromMinutes 30.0) + + ResultHandling.failBuildIfXUnitReportedError TestRunnerErrorLevel.DontFailBuild result + + projects |> Seq.iter (log) + projects |> Seq.iter (runSingleProject) +) + +Target "NBench" <| fun _ -> + let nbenchTestPath = findToolInSubPath "NBench.Runner.exe" (toolsDir @@ "NBench.Runner*") + printfn "Using NBench.Runner: %s" nbenchTestPath + + let nbenchTestAssemblies = !! "./src/**/*Tests.Performance.dll" // doesn't support .NET Core at the moment + + let runNBench assembly = + let includes = getBuildParam "include" + let excludes = getBuildParam "exclude" + let teamcityStr = (getBuildParam "teamcity") + let enableTeamCity = + match teamcityStr with + | null -> false + | "" -> false + | _ -> bool.Parse teamcityStr + + let args = StringBuilder() + |> append assembly + |> append (sprintf "output-directory=\"%s\"" outputPerfTests) + |> append (sprintf "concurrent=\"%b\"" true) + |> append (sprintf "trace=\"%b\"" true) + |> append (sprintf "teamcity=\"%b\"" enableTeamCity) + |> appendIfNotNullOrEmpty includes "include=" + |> appendIfNotNullOrEmpty excludes "include=" + |> toText + + let result = ExecProcess(fun info -> + info.FileName <- nbenchTestPath + info.WorkingDirectory <- (Path.GetDirectoryName (FullName nbenchTestPath)) + info.Arguments <- args) (System.TimeSpan.FromMinutes 45.0) (* Reasonably long-running task. *) + if result <> 0 then failwithf "NBench.Runner failed. %s %s" nbenchTestPath args - let copyOutput project = - let src = "src" @@ project @@ @"bin/Release/" - let dst = binDir @@ project - CopyDir dst src allFiles - [ "Akka.Persistence.MongoDB" - ] - |> List.iter copyOutput - -Target "BuildRelease" DoNothing - + nbenchTestAssemblies |> Seq.iter runNBench -//-------------------------------------------------------------------------------- -// Tests targets -//-------------------------------------------------------------------------------- - -//-------------------------------------------------------------------------------- -// Clean test output - -Target "CleanTests" <| fun _ -> - DeleteDir testOutput -//-------------------------------------------------------------------------------- -// Run tests - -open Fake.Testing -Target "RunTests" <| fun _ -> - let xunitTestAssemblies = !! "src/**/bin/Release/*.Tests.dll" - - mkdir testOutput - - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/FAKE/xunit.runner.console*/tools" - - printfn "Using XUnit runner: %s" xunitToolPath - let runSingleAssembly assembly = - let assemblyName = Path.GetFileNameWithoutExtension(assembly) - xUnit2 - (fun p -> { p with XmlOutputPath = Some (testOutput + @"\" + assemblyName + "_xunit.xml"); HtmlOutputPath = Some (testOutput + @"\" + assemblyName + "_xunit.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) - (Seq.singleton assembly) - - xunitTestAssemblies |> Seq.iter (runSingleAssembly) - //-------------------------------------------------------------------------------- // Nuget targets //-------------------------------------------------------------------------------- -module Nuget = - // add Akka dependency for other projects - let getAkkaDependency project = - match project with - | _ -> [] - - // used to add -pre suffix to pre-release packages - let getProjectVersion project = - match project with - | "Akka.Cluster" -> preReleaseVersion - | persistence when persistence.StartsWith("Akka.Persistence") -> preReleaseVersion - | _ -> release.NugetVersion - -open Nuget -open NuGet.Update +let overrideVersionSuffix (project:string) = + match project with + | _ -> versionSuffix // add additional matches to publish different versions for different projects in solution +Target "CreateNuget" (fun _ -> + let projects = !! "src/**/*.csproj" + -- "src/**/*Tests.csproj" // Don't publish unit tests + -- "src/**/*Tests*.csproj" + + let runSingleProject project = + DotNetCli.Pack + (fun p -> + { p with + Project = project + Configuration = configuration + AdditionalArgs = ["--include-symbols"] + VersionSuffix = overrideVersionSuffix project + OutputPath = outputNuGet }) + + projects |> Seq.iter (runSingleProject) +) + +Target "PublishNuget" (fun _ -> + let projects = !! "./bin/nuget/*.nupkg" -- "./bin/nuget/*.symbols.nupkg" + let apiKey = getBuildParamOrDefault "nugetkey" "" + let source = getBuildParamOrDefault "nugetpublishurl" "" + let symbolSource = getBuildParamOrDefault "symbolspublishurl" "" + let shouldPublishSymbolsPackages = not (symbolSource = "") + + if (not (source = "") && not (apiKey = "") && shouldPublishSymbolsPackages) then + let runSingleProject project = + DotNetCli.RunCommand + (fun p -> + { p with + TimeOut = TimeSpan.FromMinutes 10. }) + (sprintf "nuget push %s --api-key %s --source %s --symbol-source %s" project apiKey source symbolSource) + + projects |> Seq.iter (runSingleProject) + else if (not (source = "") && not (apiKey = "") && not shouldPublishSymbolsPackages) then + let runSingleProject project = + DotNetCli.RunCommand + (fun p -> + { p with + TimeOut = TimeSpan.FromMinutes 10. }) + (sprintf "nuget push %s --api-key %s --source %s" project apiKey source) + + projects |> Seq.iter (runSingleProject) +) //-------------------------------------------------------------------------------- -// Clean nuget directory - -Target "CleanNuget" <| fun _ -> - CleanDir nugetDir - -//-------------------------------------------------------------------------------- -// Pack nuget for all projects -// Publish to nuget.org if nugetkey is specified - -let createNugetPackages _ = - let removeDir dir = - let del _ = - DeleteDir dir - not (directoryExists dir) - runWithRetries del 3 |> ignore - - ensureDirectory nugetDir - for nuspec in !! "src/**/*.nuspec" do - printfn "Creating nuget packages for %s" nuspec - - CleanDir workingDir - - let project = Path.GetFileNameWithoutExtension nuspec - let projectDir = Path.GetDirectoryName nuspec - let projectFile = (!! (projectDir @@ project + ".*sproj")) |> Seq.head - let releaseDir = projectDir @@ @"bin\Release" - let packages = projectDir @@ "packages.config" - let packageDependencies = if (fileExists packages) then (getDependencies packages) else [] - let dependencies = packageDependencies @ getAkkaDependency project - let releaseVersion = getProjectVersion project - - let pack outputDir symbolPackage = - NuGetHelper.NuGet - (fun p -> - { p with - Description = description - Authors = authors - Copyright = copyright - Project = project - Properties = ["Configuration", "Release"] - ReleaseNotes = release.Notes |> String.concat "\n" - Version = releaseVersion - Tags = tags |> String.concat " " - OutputPath = outputDir - WorkingDir = workingDir - SymbolPackage = symbolPackage - Dependencies = dependencies }) - nuspec - - // Copy dll, pdb and xml to libdir = workingDir/lib/net45/ - ensureDirectory libDir - !! (releaseDir @@ project + ".dll") - ++ (releaseDir @@ project + ".pdb") - ++ (releaseDir @@ project + ".xml") - ++ (releaseDir @@ project + ".ExternalAnnotations.xml") - |> CopyFiles libDir - - // Copy all src-files (.cs and .fs files) to workingDir/src - let nugetSrcDir = workingDir @@ @"src/" - // CreateDir nugetSrcDir - - let isCs = hasExt ".cs" - let isFs = hasExt ".fs" - let isAssemblyInfo f = (filename f).Contains("AssemblyInfo") - let isSrc f = (isCs f || isFs f) && not (isAssemblyInfo f) - CopyDir nugetSrcDir projectDir isSrc - - //Remove workingDir/src/obj and workingDir/src/bin - removeDir (nugetSrcDir @@ "obj") - removeDir (nugetSrcDir @@ "bin") - - // Create both normal nuget package and symbols nuget package. - // Uses the files we copied to workingDir and outputs to nugetdir - pack nugetDir NugetSymbolPackage.Nuspec - - -let publishNugetPackages _ = - let rec publishPackage url accessKey trialsLeft packageFile = - let tracing = enableProcessTracing - enableProcessTracing <- false - let args p = - match p with - | (pack, key, "") -> sprintf "push \"%s\" %s" pack key - | (pack, key, url) -> sprintf "push \"%s\" %s -source %s" pack key url - - tracefn "Pushing %s Attempts left: %d" (FullName packageFile) trialsLeft - try - let result = ExecProcess (fun info -> - info.FileName <- nugetExe - info.WorkingDirectory <- (Path.GetDirectoryName (FullName packageFile)) - info.Arguments <- args (packageFile, accessKey,url)) (System.TimeSpan.FromMinutes 1.0) - enableProcessTracing <- tracing - if result <> 0 then failwithf "Error during NuGet symbol push. %s %s" nugetExe (args (packageFile, accessKey,url)) - with exn -> - if (trialsLeft > 0) then (publishPackage url accessKey (trialsLeft-1) packageFile) - else raise exn - let shouldPushNugetPackages = hasBuildParam "nugetkey" - let shouldPushSymbolsPackages = (hasBuildParam "symbolspublishurl") && (hasBuildParam "symbolskey") - - if (shouldPushNugetPackages || shouldPushSymbolsPackages) then - printfn "Pushing nuget packages" - if shouldPushNugetPackages then - let normalPackages= - !! (nugetDir @@ "*.nupkg") - -- (nugetDir @@ "*.symbols.nupkg") |> Seq.sortBy(fun x -> x.ToLower()) - for package in normalPackages do - publishPackage (getBuildParamOrDefault "nugetpublishurl" "") (getBuildParam "nugetkey") 3 package - - if shouldPushSymbolsPackages then - let symbolPackages= !! (nugetDir @@ "*.symbols.nupkg") |> Seq.sortBy(fun x -> x.ToLower()) - for package in symbolPackages do - publishPackage (getBuildParam "symbolspublishurl") (getBuildParam "symbolskey") 3 package - - -Target "Nuget" <| fun _ -> - createNugetPackages() - publishNugetPackages() - -Target "CreateNuget" <| fun _ -> - createNugetPackages() - -Target "PublishNuget" <| fun _ -> - publishNugetPackages() +// Documentation +//-------------------------------------------------------------------------------- +Target "DocFx" (fun _ -> + DotNetCli.Restore (fun p -> { p with Project = solutionFile }) + DotNetCli.Build (fun p -> { p with Project = solutionFile; Configuration = configuration }) + let docsPath = "./docs" + DocFx (fun p -> + { p with + Timeout = TimeSpan.FromMinutes 30.0; + WorkingDirectory = docsPath; + DocFxJson = docsPath @@ "docfx.json" }) +) //-------------------------------------------------------------------------------- // Help @@ -294,113 +235,43 @@ Target "PublishNuget" <| fun _ -> Target "Help" <| fun _ -> List.iter printfn [ "usage:" - "build [target]" + "./build.ps1 [target]" "" " Targets for building:" " * Build Builds" " * Nuget Create and optionally publish nugets packages" " * RunTests Runs tests" " * All Builds, run tests, creates and optionally publish nuget packages" + " * DocFx Creates a DocFx-based website for this solution" "" " Other Targets" " * Help Display this help" - " * HelpNuget Display help about creating and pushing nuget packages" - " * HelpDocs Display help about creating and pushing API docs" - ""] - -Target "HelpNuget" <| fun _ -> - List.iter printfn [ - "usage: " - "build Nuget [nugetkey= [nugetpublishurl=]] " - " [symbolskey= symbolspublishurl=] " - " [nugetprerelease=]" - "" - "Arguments for Nuget target:" - " nugetprerelease= Creates a pre-release package." - " The version will be version-prefix" - " Example: nugetprerelease=dev =>" - " 0.6.3-dev1408191917" - "" - "In order to publish a nuget package, keys must be specified." - "If a key is not specified the nuget packages will only be created on disk" - "After a build you can find them in bin/nuget" - "" - "For pushing nuget packages to nuget.org and symbols to symbolsource.org" - "you need to specify nugetkey=" - " build Nuget nugetKey=" - "" - "For pushing the ordinary nuget packages to another place than nuget.org specify the url" - " nugetkey= nugetpublishurl= " - "" - "For pushing symbols packages specify:" - " symbolskey= symbolspublishurl= " - "" - "Examples:" - " build Nuget Build nuget packages to the bin/nuget folder" - "" - " build Nuget nugetprerelease=dev Build pre-release nuget packages" - "" - " build Nuget nugetkey=123 Build and publish to nuget.org and symbolsource.org" - "" - " build Nuget nugetprerelease=dev nugetkey=123 nugetpublishurl=http://abc" - " symbolskey=456 symbolspublishurl=http://xyz" - " Build and publish pre-release nuget packages to http://abc" - " and symbols packages to http://xyz" - ""] - -Target "HelpDocs" <| fun _ -> - List.iter printfn [ - "usage: " - "build Docs" - "Just builds the API docs for Akka.NET locally. Does not attempt to publish." - "" - "build PublishDocs azureKey= " - " azureUrl= " - " [unstable=true]" - "" - "Arguments for PublishDocs target:" - " azureKey= Azure blob storage key." - " Used to authenticate to the storage account." - "" - " azureUrl= Base URL for Azure storage container." - " FAKE will automatically set container" - " names based on build parameters." - "" - " [unstable=true] Indicates that we'll publish to an Azure" - " container named 'unstable'. If this param" - " is not present we'll publish to containers" - " 'stable' and the 'release.version'" - "" - "In order to publish documentation all of these values must be provided." - "Examples:" - " build PublishDocs azureKey=1s9HSAHA+..." - " azureUrl=http://fooaccount.blob.core.windows.net/docs" - " Build and publish docs to http://fooaccount.blob.core.windows.net/docs/stable" - " and http://fooaccount.blob.core.windows.net/docs/{release.version}" - "" - " build PublishDocs azureKey=1s9HSAHA+..." - " azureUrl=http://fooaccount.blob.core.windows.net/docs" - " unstable=true" - " Build and publish docs to http://fooaccount.blob.core.windows.net/docs/unstable" ""] //-------------------------------------------------------------------------------- // Target dependencies //-------------------------------------------------------------------------------- +Target "BuildRelease" DoNothing +Target "All" DoNothing +Target "Nuget" DoNothing + // build dependencies -"Clean" ==> "AssemblyInfo" ==> "RestorePackages" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" +"Clean" ==> "RestorePackages" ==> "AssemblyInfo" ==> "Build" ==> "BuildRelease" // tests dependencies -"CleanTests" ==> "RunTests" // nuget dependencies -"CleanNuget" ==> "CreateNuget" -"CleanNuget" ==> "BuildRelease" ==> "Nuget" +"Clean" ==> "RestorePackages" ==> "Build" ==> "CreateNuget" +"CreateNuget" ==> "PublishNuget" ==> "Nuget" -Target "All" DoNothing +// docs +"BuildRelease" ==> "Docfx" + +// all "BuildRelease" ==> "All" "RunTests" ==> "All" +//"NBench" ==> "All" "Nuget" ==> "All" -RunTargetOrDefault "Help" +RunTargetOrDefault "Help" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..f2180fc --- /dev/null +++ b/build.ps1 @@ -0,0 +1,162 @@ +<# +.SYNOPSIS +This is a Powershell script to bootstrap a Fake build. +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Fake) +and execute your Fake build script with the parameters you provide. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER ScriptArgs +Remaining arguments are added here. +#> + +[CmdletBinding()] +Param( + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Release", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Verbose", + [switch]$WhatIf, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +$FakeVersion = "4.61.2" +$NBenchVersion = "1.0.1" +$DotNetChannel = "LTS"; +$DotNetVersion = "2.0.0"; +$DotNetInstallerUri = "https://raw.githubusercontent.com/dotnet/cli/v$DotNetVersion/scripts/obtain/dotnet-install.ps1"; +$NugetVersion = "4.1.0"; +$NugetUrl = "https://dist.nuget.org/win-x86-commandline/v$NugetVersion/nuget.exe" +$ProtobufVersion = "3.2.0" +$DocfxVersion = "2.21.1" + +# Make sure tools folder exists +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +$ToolPath = Join-Path $PSScriptRoot "tools" +if (!(Test-Path $ToolPath)) { + Write-Verbose "Creating tools directory..." + New-Item -Path $ToolPath -Type directory | out-null +} + +########################################################################### +# INSTALL .NET CORE CLI +########################################################################### + +Function Remove-PathVariable([string]$VariableToRemove) +{ + $path = [Environment]::GetEnvironmentVariable("PATH", "User") + if ($path -ne $null) + { + $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove } + [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "User") + } + + $path = [Environment]::GetEnvironmentVariable("PATH", "Process") + if ($path -ne $null) + { + $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove } + [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "Process") + } +} + +# Get .NET Core CLI path if installed. +$FoundDotNetCliVersion = $null; +if (Get-Command dotnet -ErrorAction SilentlyContinue) { + $FoundDotNetCliVersion = dotnet --version; + $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + $env:DOTNET_CLI_TELEMETRY_OPTOUT=1 +} + +if($FoundDotNetCliVersion -ne $DotNetVersion) { + $InstallPath = Join-Path $PSScriptRoot ".dotnet" + if (!(Test-Path $InstallPath)) { + mkdir -Force $InstallPath | Out-Null; + } + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, "$InstallPath\dotnet-install.ps1"); + & $InstallPath\dotnet-install.ps1 -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath -Architecture x64; + + Remove-PathVariable "$InstallPath" + $env:PATH = "$InstallPath;$env:PATH" + $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + $env:DOTNET_CLI_TELEMETRY_OPTOUT=1 +} + +########################################################################### +# INSTALL NUGET +########################################################################### + +# Make sure nuget.exe exists. +$NugetPath = Join-Path $ToolPath "nuget.exe" +if (!(Test-Path $NugetPath)) { + Write-Host "Downloading NuGet.exe..." + (New-Object System.Net.WebClient).DownloadFile($NugetUrl, $NugetPath); +} + +########################################################################### +# INSTALL FAKE +########################################################################### +# Make sure Fake has been installed. + +$FakeExePath = Join-Path $ToolPath "FAKE/tools/FAKE.exe" +if (!(Test-Path $FakeExePath)) { + Write-Host "Installing Fake..." + Invoke-Expression "&`"$NugetPath`" install Fake -ExcludeVersion -Version $FakeVersion -OutputDirectory `"$ToolPath`"" | Out-Null; + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring Fake from NuGet." + } +} + +########################################################################### +# INSTALL NBench Runner +########################################################################### + +# Make sure NBench Runner has been installed. +$NBenchDllPath = Join-Path $ToolPath "NBench.Runner/lib/net45/NBench.Runner.exe" +if (!(Test-Path $NBenchDllPath)) { + Write-Host "Installing NBench..." + Invoke-Expression "&`"$NugetPath`" install NBench.Runner -ExcludeVersion -Version $NBenchVersion -OutputDirectory `"$ToolPath`"" | Out-Null; + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NBench.Runner from NuGet." + } +} + +########################################################################### +# Docfx +########################################################################### + +# Make sure Docfx has been installed. +$DocfxExePath = Join-Path $ToolPath "docfx.console/tools/docfx.exe" +if (!(Test-Path $DocfxExePath)) { + Write-Host "Installing Docfx..." + Invoke-Expression "&`"$NugetPath`" install docfx.console -ExcludeVersion -Version $DocfxVersion -OutputDirectory `"$ToolPath`"" | Out-Null; + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring docfx.console from NuGet." + } +} + +########################################################################### +# RUN BUILD SCRIPT +########################################################################### + +# Build the argument list. +$Arguments = @{ + target=$Target; + configuration=$Configuration; + verbosity=$Verbosity; + dryrun=$WhatIf; +}.GetEnumerator() | %{"--{0}=`"{1}`"" -f $_.key, $_.value }; + +# Start Fake +Write-Host "Running build script..." +Invoke-Expression "$FakeExePath `"build.fsx`" $ScriptArgs $Arguments" + +exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh index 84e65b6..8e70878 100644 --- a/build.sh +++ b/build.sh @@ -1,25 +1,98 @@ -#!/bin/bash +#!/usr/bin/env bash +########################################################################## +# This is the Fake bootstrapper script for Linux and OS X. +########################################################################## -SCRIPT_PATH="${BASH_SOURCE[0]}"; -if ([ -h "${SCRIPT_PATH}" ]) then - while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +NUGET_EXE=$TOOLS_DIR/nuget.exe +NUGET_URL=https://dist.nuget.org/win-x86-commandline/v4.0.0/nuget.exe +FAKE_VERSION=4.61.2 +FAKE_EXE=$TOOLS_DIR/FAKE/tools/FAKE.exe +DOTNET_VERSION=2.0.0 +DOTNET_INSTALLER_URL=https://raw.githubusercontent.com/dotnet/cli/2.0.0/scripts/obtain/dotnet-install.sh +# Define default arguments. +TARGET="Default" +CONFIGURATION="Release" +VERBOSITY="verbose" +DRYRUN= +SCRIPT_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -t|--target) TARGET="$2"; shift ;; + -c|--configuration) CONFIGURATION="$2"; shift ;; + -v|--verbosity) VERBOSITY="$2"; shift ;; + -d|--dryrun) DRYRUN="-dryrun" ;; + --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; + *) SCRIPT_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +########################################################################### +# INSTALL .NET CORE CLI +########################################################################### + +echo "Installing .NET CLI..." +if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then + mkdir "$SCRIPT_DIR/.dotnet" fi -pushd . > /dev/null -cd `dirname ${SCRIPT_PATH}` > /dev/null -SCRIPT_PATH=`pwd`; -popd > /dev/null +curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" $DOTNET_INSTALLER_URL +bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path +export PATH="$SCRIPT_DIR/.dotnet":$PATH +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +chmod -R 0755 ".dotnet" +"$SCRIPT_DIR/.dotnet/dotnet" --info -mono $SCRIPT_PATH/src/.nuget/NuGet.exe update -self +########################################################################### +# INSTALL NUGET +########################################################################### -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install FAKE -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 4.35.0 +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" $NUGET_URL + if [ $? -ne 0 ]; then + echo "An error occured while downloading nuget.exe." + exit 1 + fi +fi -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install xunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.1.0 +########################################################################### +# INSTALL FAKE +########################################################################### -if ! [ -e $SCRIPT_PATH/src/packages/SourceLink.Fake/tools/SourceLink.fsx ] ; then - mono $SCRIPT_PATH/src/.nuget/NuGet.exe install SourceLink.Fake -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 1.1.0 +if [ ! -f "$FAKE_EXE" ]; then + mono "$NUGET_EXE" install Fake -ExcludeVersion -Version $FAKE_VERSION -OutputDirectory "$TOOLS_DIR" + if [ $? -ne 0 ]; then + echo "An error occured while installing Cake." + exit 1 + fi +fi +# Make sure that Fake has been installed. +if [ ! -f "$FAKE_EXE" ]; then + echo "Could not find Fake.exe at '$FAKE_EXE'." + exit 1 fi -export encoding=utf-8 +########################################################################### +# WORKAROUND FOR MONO +########################################################################### +export FrameworkPathOverride=/usr/lib/mono/4.5/ + +########################################################################### +# RUN BUILD SCRIPT +########################################################################### -mono $SCRIPT_PATH/src/packages/FAKE/tools/FAKE.exe build.fsx "$@" +# Start Fake +exec mono "$FAKE_EXE" build.fsx "${SCRIPT_ARGUMENTS[@]}" --verbosity=$VERBOSITY --configuration=$CONFIGURATION --target=$TARGET $DRYRUN diff --git a/docs/api/index.md b/docs/api/index.md new file mode 100644 index 0000000..9e0155b --- /dev/null +++ b/docs/api/index.md @@ -0,0 +1 @@ +# API Docs \ No newline at end of file diff --git a/docs/articles/index.md b/docs/articles/index.md new file mode 100644 index 0000000..9d45024 --- /dev/null +++ b/docs/articles/index.md @@ -0,0 +1,3 @@ +# Introduction + +Article text goes here. \ No newline at end of file diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml new file mode 100644 index 0000000..4262931 --- /dev/null +++ b/docs/articles/toc.yml @@ -0,0 +1,2 @@ +- name: Introduction + href: index.md \ No newline at end of file diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 0000000..7d75f8d --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,67 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ "**/*.csproj" ], + "exclude": [ + "**/obj/**", + "**/bin/**", + "_site/**", + "**/*Tests*.csproj", + "**/*Tests.*.csproj" + ], + "src": "../src" + } + ], + "dest": "api" + } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md" + ] + }, + { + "files": [ + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + }, + ], + "resource": [ + { + "files": [ + "images/**" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "dest": "_site", + "globalMetadata": { + "_appTitle": "Akka.Persistence.MongoDb", + "_disableContribution": "true", + "_appLogoPath": "/images/icon.png", + }, + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default", + "template" + ], + "postProcessors": [], + "noLangKeyword": false + } +} \ No newline at end of file diff --git a/docs/images/icon.png b/docs/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..86698cd6d92eabd00b206f56d4ffbfa59be23a15 GIT binary patch literal 841 zcmeAS@N?(olHy`uVBq!ia0vp^Q6S901|%(3I5Gh##^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DjSL74G){)!Z!pk#?_L`iUdT1k0gQ7S`0VrE{6US4X6f{C7i zo}syM-uz?+2Bw{!E{-7;ac{5NW`{UR9Q`O@&}AkS*rKqawL^u4m9yj61Mk#C(Wa)K zY?*KVF#Y1>;fVT?C&0Z?pjmLSMwgh|h7B9GZr&_7@vF`09-p@2-IG@roM*N-`aJ)% z*kiTbd|#?;vl)Arxi5ZsF{8?4mK<%FH`vbjNn~0`H#%?F_^`&<=fJ(T&tEqzf7tVF zt6Q?P!S@HLSNjfzcleg=x46&NAAG*<@X=SLc}q6`Ts7Z!?my;rs#3QbB1Y>BqevxWR9=1&bDQ>F<*);m<9co+`hyQ%-Z><4bDGE zJABi#!{&OqV{rl#NtG}bpBkK>0H~5x6Wd8C$xvBI04f%&0JO}G`a1~bUs93w>MX3Co z8QKEf7w&fZy|t)ms!_cEAgFL3>m#9hhq`CFGHc?Vi(L`7< + + + + + net461 + + + + + + + + + + + + diff --git a/src/Akka.Persistence.MongoDb.Tests.Performance/UnitTest1.cs b/src/Akka.Persistence.MongoDb.Tests.Performance/UnitTest1.cs new file mode 100644 index 0000000..dba4a5b --- /dev/null +++ b/src/Akka.Persistence.MongoDb.Tests.Performance/UnitTest1.cs @@ -0,0 +1,26 @@ +using System; +using NBench; + +namespace Akka.Persistence.MongoDb.Tests.Performance +{ + public class UnitTest1 + { + public const string CounterName = "Operations"; + private Counter _opsCounter; + + [PerfSetup] + public void Setup(BenchmarkContext context) + { + _opsCounter = context.GetCounter(CounterName); + } + + [PerfBenchmark(NumberOfIterations = 5, RunMode = RunMode.Throughput, RunTimeMilliseconds = 1000)] + [CounterMeasurement(CounterName)] + [GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)] + [MemoryMeasurement(MemoryMetric.TotalBytesAllocated)] + public void TestMethod1() + { + _opsCounter.Increment(); + } + } +} diff --git a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj index e084707..90bddeb 100644 --- a/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj +++ b/src/Akka.Persistence.MongoDb.Tests/Akka.Persistence.MongoDb.Tests.csproj @@ -1,38 +1,28 @@ - - - - Akka.Persistence.MongoDB.Tests - net461;netcoreapp1.1 - akka;actors;actor model;Akka;concurrency;MongoDB - Copyright © 2013-2017 - Akka.NET Contrib - 1.3.1 - http://getakka.net/images/akkalogo.png - https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB - https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB/blob/master/LICENSE.md - true - $(NoWarn);CS1591 - + + - - - - - - - - - - - - - + + netcoreapp2.0 + + - + + + + + + + + + + + + + + + + $(DefineConstants);RELEASE - + - - - - + \ No newline at end of file diff --git a/src/Akka.Persistence.MongoDb.sln b/src/Akka.Persistence.MongoDb.sln deleted file mode 100644 index 6fdb083..0000000 --- a/src/Akka.Persistence.MongoDb.sln +++ /dev/null @@ -1,45 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.MongoDb", "Akka.Persistence.MongoDb\Akka.Persistence.MongoDb.csproj", "{12E044EF-08A2-428B-AAF5-C3D328860C4E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.MongoDb.Tests", "Akka.Persistence.MongoDb.Tests\Akka.Persistence.MongoDb.Tests.csproj", "{32A2ACBE-8A3C-4093-8C13-D65B113B3327}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{86AAC379-3743-4D46-8B92-AE6A5ED80A44}" - ProjectSection(SolutionItems) = preProject - ..\appveyor.yml = ..\appveyor.yml - ..\build.cmd = ..\build.cmd - ..\build.fsx = ..\build.fsx - ..\build.sh = ..\build.sh - ..\README.md = ..\README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{65DAEEC3-80C7-42C5-B0AC-DFC928846EF6}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\NuGet.Dev.Config = .nuget\NuGet.Dev.Config - .nuget\NuGet.exe = .nuget\NuGet.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {12E044EF-08A2-428B-AAF5-C3D328860C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {12E044EF-08A2-428B-AAF5-C3D328860C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {12E044EF-08A2-428B-AAF5-C3D328860C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {12E044EF-08A2-428B-AAF5-C3D328860C4E}.Release|Any CPU.Build.0 = Release|Any CPU - {32A2ACBE-8A3C-4093-8C13-D65B113B3327}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {32A2ACBE-8A3C-4093-8C13-D65B113B3327}.Debug|Any CPU.Build.0 = Debug|Any CPU - {32A2ACBE-8A3C-4093-8C13-D65B113B3327}.Release|Any CPU.ActiveCfg = Release|Any CPU - {32A2ACBE-8A3C-4093-8C13-D65B113B3327}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj index 04bd4f3..d0be12f 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj @@ -1,28 +1,15 @@ - + + + - Akka.Persistence.MongoDB - Akka Persistence journal and snapshot store backed by MongoDB database. net45;netstandard1.6 - akka;actors;actor model;Akka;concurrency;MongoDB - Copyright © 2013-2017 - Akka.NET Contrib - 1.3.1 - http://getakka.net/images/akkalogo.png - https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB - https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB/blob/master/LICENSE.md - Support for Akka.NET 1.3, .NET Standard 1.6, and the first stable RTM release of Akka.Persistence. - true - $(NoWarn);CS1591 - - - + - diff --git a/src/common.props b/src/common.props new file mode 100644 index 0000000..041fe55 --- /dev/null +++ b/src/common.props @@ -0,0 +1,18 @@ + + + Copyright © 2013-2018 Akka.NET Project + Akka.NET Contrib + 1.3.5 + http://getakka.net/images/akkalogo.png + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB + https://github.com/AkkaNetContrib/Akka.Persistence.MongoDB/blob/master/LICENSE.md + Support for Akka.NET 1.3.5 and upgraded MongoDb drivers et al. + true + Akka Persistence journal and snapshot store backed by MongoDB database. + $(NoWarn);CS1591 + + + 2.3.0 + 15.3.0 + + \ No newline at end of file From 2ea6f724ea5aa1cc7645b9abfa25195ae16a2c14 Mon Sep 17 00:00:00 2001 From: maxx1337 Date: Sun, 18 Mar 2018 20:57:34 +0100 Subject: [PATCH 7/9] upgrade mongo driver to 2.5.0 (#33) --- src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj index d0be12f..d62c621 100644 --- a/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj +++ b/src/Akka.Persistence.MongoDb/Akka.Persistence.MongoDb.csproj @@ -1,7 +1,6 @@ - net45;netstandard1.6 @@ -10,8 +9,8 @@ - - + + $(DefineConstants);RELEASE From bea1fa1cb76aba5755001caa8b2df9eeb4013841 Mon Sep 17 00:00:00 2001 From: Lealand Vettleson Date: Thu, 22 Mar 2018 11:52:32 -0500 Subject: [PATCH 8/9] Merge pull request #28 Auto-register BsonClassMaps --- README.md | 5 +- .../FullTypeNameDiscriminatorConvention.cs | 37 +++++++++ .../FullTypeNameObjectSerializer.cs | 81 +++++++++++++++++++ .../MongoDbPersistence.cs | 8 ++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/Akka.Persistence.MongoDb/FullTypeNameDiscriminatorConvention.cs create mode 100644 src/Akka.Persistence.MongoDb/FullTypeNameObjectSerializer.cs diff --git a/README.md b/README.md index a46add4..d41d45c 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,10 @@ akka.persistence { ``` ### Serialization -The events and snapshots are stored as BsonDocument, so you need to register you types with the BsonClassMap before you can use your persistence actor. -Otherwise the recovery will fail and you receive a RecoveryFailure with the message: +The events and snapshots are stored as BsonDocument. On the previous version of this driver you needed to register your types with BsonClassMap before you could use your persistence actor, otherwise the recovery would fail and you'd receive a RecoveryFailure with the message: >An error occurred while deserializing the Payload property of class \: Unknown discriminator value '\' +#### **Since now, all types are registered automatically for you so you don't need to use BsonClassMap to serialize/deserialize your types!** + ### Notice - The MongoDB operator to limit the number of documents in a query only accepts an integer while akka provides a long as maximum for the loading of events during the replay. Internally the long value is cast to an integer and if the value is higher then Int32.MaxValue, Int32.MaxValue is used. So if you have stored more then 2,147,483,647 events for a single PersistenceId, you may have a problem :wink: diff --git a/src/Akka.Persistence.MongoDb/FullTypeNameDiscriminatorConvention.cs b/src/Akka.Persistence.MongoDb/FullTypeNameDiscriminatorConvention.cs new file mode 100644 index 0000000..e923b48 --- /dev/null +++ b/src/Akka.Persistence.MongoDb/FullTypeNameDiscriminatorConvention.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- +using System; +using System.Reflection; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Conventions; + +namespace Akka.Persistence.MongoDb +{ + /// + /// Our discriminator is the type's full name with the assembly name. + /// Additional assembly information is excluded for forward compatibility. + /// + class FullTypeNameDiscriminatorConvention : StandardDiscriminatorConvention + { + public static readonly FullTypeNameDiscriminatorConvention Instance = new FullTypeNameDiscriminatorConvention("_t"); + + public FullTypeNameDiscriminatorConvention(string element) : base(element) { } + + /// + /// Our discriminator is the full type name with the assembly name. + /// Additional assembly information is excluded for forward compatibility. + /// + /// + /// + /// full type name with the simple assembly name + public override BsonValue GetDiscriminator(Type nominalType, Type actualType) + { + var assemblyName = actualType.GetTypeInfo().Assembly.FullName.Split(',')[0]; + return $"{actualType.FullName}, {assemblyName}"; + } + } +} diff --git a/src/Akka.Persistence.MongoDb/FullTypeNameObjectSerializer.cs b/src/Akka.Persistence.MongoDb/FullTypeNameObjectSerializer.cs new file mode 100644 index 0000000..dc98dba --- /dev/null +++ b/src/Akka.Persistence.MongoDb/FullTypeNameObjectSerializer.cs @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Reflection; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Bson.Serialization.Serializers; + +namespace Akka.Persistence.MongoDb +{ + /// + /// Represents a serializer for objects. + /// + class FullTypeNameObjectSerializer : ObjectSerializer + { + protected readonly IDiscriminatorConvention DiscriminatorConvention = FullTypeNameDiscriminatorConvention.Instance; + + /// + /// Initializes a new instance of the class. + /// + public FullTypeNameObjectSerializer() : base(FullTypeNameDiscriminatorConvention.Instance) { } + + /// + /// Deserializes a value. + /// + public override object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var bsonReader = context.Reader; + + if (BsonType.Document == bsonReader.GetCurrentBsonType()) + { + RegisterNewTypesToDiscriminator(DiscriminatorConvention.GetActualType(bsonReader, typeof(object))); + } + + return base.Deserialize(context, args); + } + + /// + /// Serializes a value. + /// + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) + { + if (value != null) + { + // auto-register new types with MongoDB on serialization, using their full assembly name + RegisterNewTypesToDiscriminator(value.GetType()); + } + + base.Serialize(context, args, value); + } + + /// + /// If the type is not registered, attach it to our discriminator + /// + /// the type to examine + protected void RegisterNewTypesToDiscriminator(Type actualType) + { + // we've detected a new concrete type that isn't registered in MongoDB's serializer + if (actualType != typeof(object) && !actualType.GetTypeInfo().IsInterface && !BsonSerializer.IsTypeDiscriminated(actualType)) + { + try + { + BsonSerializer.RegisterDiscriminatorConvention(actualType, DiscriminatorConvention); + BsonSerializer.RegisterDiscriminator(actualType, DiscriminatorConvention.GetDiscriminator(typeof(object), actualType)); + } + catch (BsonSerializationException) + { + // the MongoDB driver library has no nice mechanism for checking if a discriminator convention is registerd. + // The "Lookup" logic tends to define a default if it doesn't exist. + // So we're forced to eat the "duplicate registration" exception. + } + } + } + } +} diff --git a/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs b/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs index c33e13d..1106a28 100644 --- a/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs +++ b/src/Akka.Persistence.MongoDb/MongoDbPersistence.cs @@ -8,6 +8,7 @@ using System; using Akka.Actor; using Akka.Configuration; +using MongoDB.Bson.Serialization; namespace Akka.Persistence.MongoDb { @@ -16,6 +17,13 @@ namespace Akka.Persistence.MongoDb /// public class MongoDbPersistence : IExtension { + static MongoDbPersistence() + { + // Some MongoDB things are statically configured. + + // Register our own serializer for objects that uses the type's FullName + Assembly for the discriminator + BsonSerializer.RegisterSerializer(typeof(object), new FullTypeNameObjectSerializer()); + } /// /// Returns a default configuration for akka persistence MongoDb journal and snapshot store. /// From f7fbc6d780a772718521ba4a21d9668ab2ff8b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Li=C3=B1an?= Date: Fri, 23 Mar 2018 10:48:21 -0300 Subject: [PATCH 9/9] Update RELEASE_NOTES.md (#39) * Update RELEASE_NOTES.md * Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fd192ab..198733b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,8 +1,9 @@ -#### 1.3.5 March 16 2018 #### -Support for Akka.NET 1.3.5 and upgraded MongoDb drivers et al. -#### 1.3.1 October 11 2017 #### -Support for Akka.NET 1.3, .NET Standard 1.6, and the first stable RTM release of Akka.Persistence. +#### 1.3.5 March 23 2018 #### +Support for Akka.Persistence 1.3.5. +Support for .NET Standard 1.6 +Supports latest version of .NET MongoDB Driver. +You don't neeed to register/map your classes for serialization/deserialization anymore! #### 1.1.0 July 30 2016 #### Updated to Akka.Persistence 1.1.1 @@ -46,4 +47,4 @@ try { #### 1.0.5 August 08 2015 #### #### 1.0.4 August 07 2015 #### -Initial release of Akka.Persistence.MongoDb \ No newline at end of file +Initial release of Akka.Persistence.MongoDb