From bc33390aad7808d51bd6415d2251ff36426ec7da Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 11 Aug 2017 12:52:13 +0300 Subject: [PATCH 01/44] Ignore artifacts directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 216bb93..7cc6354 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ project.lock.json TestResult.xml *.nuget.props *.out -*.ncrunchsolution.user \ No newline at end of file +*.ncrunchsolution.user +artifacts/ \ No newline at end of file From 231800f827e049c24d98194e98ed7f3aff8f40f1 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 11 Aug 2017 12:53:06 +0300 Subject: [PATCH 02/44] Updated readme for new build url and added note about supported server versions --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f394d50..01b358d 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,6 @@ Direct port of the .NET client to .NET core targetting .netstandard1.3 and above -[![wercker status](https://app.wercker.com/status/b4ef76de17d3b5c9528cd0925ec4be44/s/master "wercker status")](https://app.wercker.com/project/byKey/b4ef76de17d3b5c9528cd0925ec4be44) +Works with EventStore server 4.0.0 and above + +[![wercker status](https://app.wercker.com/status/21204a69779b2b4543242fd543d0aaab/s/master "wercker status")](https://app.wercker.com/project/byKey/21204a69779b2b4543242fd543d0aaab) From 25cc787138e0ef12b6f5b0e6c790d84b9fbaa683 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 11 Aug 2017 15:47:18 +0300 Subject: [PATCH 03/44] Fixed issues with tooling upgrade --- EventStore.ClientAPI.NetCore.sln | 52 +++++++++---------- .../EventStore.ClientAPI.NetCore.Tests.csproj | 4 ++ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/EventStore.ClientAPI.NetCore.sln b/EventStore.ClientAPI.NetCore.sln index 99892b8..15a32ba 100644 --- a/EventStore.ClientAPI.NetCore.sln +++ b/EventStore.ClientAPI.NetCore.sln @@ -1,51 +1,47 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26114.2 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.ClientAPI.NetCore", "src\EventStore.ClientAPI.NetCore\EventStore.ClientAPI.NetCore.csproj", "{AFE5579C-111B-47F3-96E0-5E08DAA2215C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.ClientAPI.NetCore", "src\EventStore.ClientAPI.NetCore\EventStore.ClientAPI.NetCore.csproj", "{AFE5579C-111B-47F3-96E0-5E08DAA2215C}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Eventstore.ClientAPI.NetCore.Tests", "test\Eventstore.ClientAPI.NetCore.Tests\Eventstore.ClientAPI.NetCore.Tests.xproj", "{E5A83A9B-5E67-47DF-B96A-4401BB2AB3F1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6B01688A-F7FE-434C-AE82-E4D4B20C4315}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.ClientAPI.NetCore.Tests", "test\EventStore.ClientAPI.NetCore.Tests\EventStore.ClientAPI.NetCore.Tests.csproj", "{03219908-577E-4C11-88AE-0F3B831D09FE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.ClientAPI.NetCore.Tests", "test\EventStore.ClientAPI.NetCore.Tests\EventStore.ClientAPI.NetCore.Tests.csproj", "{DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|x64.Build.0 = Debug|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|x86.ActiveCfg = Debug|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Debug|x86.Build.0 = Debug|Any CPU {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|Any CPU.Build.0 = Release|Any CPU - {E5A83A9B-5E67-47DF-B96A-4401BB2AB3F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5A83A9B-5E67-47DF-B96A-4401BB2AB3F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5A83A9B-5E67-47DF-B96A-4401BB2AB3F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5A83A9B-5E67-47DF-B96A-4401BB2AB3F1}.Release|Any CPU.Build.0 = Release|Any CPU - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|x64.ActiveCfg = Debug|x64 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|x64.Build.0 = Debug|x64 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|x86.ActiveCfg = Debug|x86 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Debug|x86.Build.0 = Debug|x86 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|Any CPU.Build.0 = Release|Any CPU - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|x64.ActiveCfg = Release|x64 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|x64.Build.0 = Release|x64 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|x86.ActiveCfg = Release|x86 - {03219908-577E-4C11-88AE-0F3B831D09FE}.Release|x86.Build.0 = Release|x86 + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|x64.ActiveCfg = Release|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|x64.Build.0 = Release|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|x86.ActiveCfg = Release|Any CPU + {AFE5579C-111B-47F3-96E0-5E08DAA2215C}.Release|x86.Build.0 = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|x64.Build.0 = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Debug|x86.Build.0 = Debug|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|Any CPU.Build.0 = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|x64.ActiveCfg = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|x64.Build.0 = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|x86.ActiveCfg = Release|Any CPU + {DCB1B5AE-BDAF-4C5A-80F5-1AAC8074EC3F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {03219908-577E-4C11-88AE-0F3B831D09FE} = {6B01688A-F7FE-434C-AE82-E4D4B20C4315} - EndGlobalSection EndGlobal diff --git a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj index 0e8a16f..603c405 100755 --- a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj +++ b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj @@ -20,4 +20,8 @@ + + + + From af2ac0fca434699c316c1678fbcb4e99c835f920 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 14 Aug 2017 17:58:54 +0300 Subject: [PATCH 04/44] Bring core client in line with 4.0.2 rc 2 --- .../CatchUpSubscriptionSettings.cs | 17 +- ...onnectToPersistentSubscriptionOperation.cs | 2 +- .../ClientOperations/SubscriptionOperation.cs | 26 +- .../VolatileSubscriptionOperation.cs | 2 +- .../ClusterSettings.cs | 8 +- .../Common/Utils/Threading/TaskExtensions.cs | 19 + .../ConnectionSettings.cs | 4 +- .../ConnectionSettingsBuilder.cs | 7 +- .../DnsClusterSettingsBuilder.cs | 2 +- .../EventStoreCatchUpSubscription.cs | 341 ++++++++--------- .../EventStorePersistentSubscription.cs | 6 +- .../EventStorePersistentSubscriptionBase.cs | 16 +- .../EventStoreSubscription.cs | 8 +- .../GossipSeedClusterSettingsBuilder.cs | 2 +- .../IEventStoreConnection.cs | 96 ++--- .../IEventStoreConnectionExtensions.cs | 351 ++++++++++++++++++ .../EventStoreConnectionLogicHandler.cs | 10 +- .../Internal/EventStoreNodeConnection.cs | 124 +++---- .../Internal/Messages.cs | 8 +- .../Messages/ClientMessage.cs | 2 +- .../PersistentSubscriptionSettings.cs | 6 +- .../PersistentSubscriptionSettingsBuilder.cs | 6 +- .../Projections/ProjectionsClient.cs | 2 +- .../Projections/ProjectionsManager.cs | 3 +- .../Projections/QueryManager.cs | 83 +++++ 25 files changed, 793 insertions(+), 358 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/TaskExtensions.cs create mode 100644 src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs create mode 100644 src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs diff --git a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs index 854e10c..50ec220 100644 --- a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs @@ -27,10 +27,21 @@ public class CatchUpSubscriptionSettings /// public readonly bool ResolveLinkTos; + /// + /// The name of subscription. + /// + public readonly string SubscriptionName; + /// /// Returns default settings /// - public static readonly CatchUpSubscriptionSettings Default = new CatchUpSubscriptionSettings(Consts.CatchUpDefaultMaxPushQueueSize, Consts.CatchUpDefaultReadBatchSize, false, true); + public static readonly CatchUpSubscriptionSettings Default = new CatchUpSubscriptionSettings( + Consts.CatchUpDefaultMaxPushQueueSize, + Consts.CatchUpDefaultReadBatchSize, + verboseLogging: false, + resolveLinkTos: true, + subscriptionName: String.Empty + ); /// /// Constructs a object @@ -39,7 +50,8 @@ public class CatchUpSubscriptionSettings /// The number of events to read per batch when reading history /// Enables verbose logging on the subscription /// Whether or not to resolve link events - public CatchUpSubscriptionSettings(int maxLiveQueueSize, int readBatchSize, bool verboseLogging, bool resolveLinkTos) { + /// The name of subscription. + public CatchUpSubscriptionSettings(int maxLiveQueueSize, int readBatchSize, bool verboseLogging, bool resolveLinkTos, string subscriptionName = "") { Ensure.Positive(readBatchSize, "readBatchSize"); Ensure.Positive(maxLiveQueueSize, "maxLiveQueueSize"); if (readBatchSize > Consts.MaxReadSize) throw new ArgumentException(string.Format("Read batch size should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); @@ -47,6 +59,7 @@ public CatchUpSubscriptionSettings(int maxLiveQueueSize, int readBatchSize, bool ReadBatchSize = readBatchSize; VerboseLogging = verboseLogging; ResolveLinkTos = resolveLinkTos; + SubscriptionName = subscriptionName; } } } \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs index 2b77d88..1a6008d 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs @@ -15,7 +15,7 @@ internal class ConnectToPersistentSubscriptionOperation : SubscriptionOperation< private readonly int _bufferSize; private string _subscriptionId; - public ConnectToPersistentSubscriptionOperation(ILogger log, TaskCompletionSource source, string groupName, int bufferSize, string streamId, UserCredentials userCredentials, Action eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) + public ConnectToPersistentSubscriptionOperation(ILogger log, TaskCompletionSource source, string groupName, int bufferSize, string streamId, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) : base(log, source, streamId, false, userCredentials, eventAppeared, subscriptionDropped, verboseLogging, getConnection) { _groupName = groupName; diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs index 22cc75a..38bc5cd 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs @@ -17,12 +17,12 @@ internal abstract class SubscriptionOperation : ISubscriptionOperation where protected readonly string _streamId; protected readonly bool _resolveLinkTos; protected readonly UserCredentials _userCredentials; - protected readonly Action _eventAppeared; + protected readonly Func _eventAppeared; private readonly Action _subscriptionDropped; private readonly bool _verboseLogging; protected readonly Func _getConnection; private readonly int _maxQueueSize = 2000; - private readonly ConcurrentQueue _actionQueue = new ConcurrentQueue(); + private readonly ConcurrentQueue> _actionQueue = new ConcurrentQueue>(); private int _actionExecuting; private T _subscription; private int _unsubscribed; @@ -33,7 +33,7 @@ protected SubscriptionOperation(ILogger log, string streamId, bool resolveLinkTos, UserCredentials userCredentials, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) @@ -208,22 +208,26 @@ public void DropSubscription(SubscriptionDropReason reason, Exception exc, TcpPa if (reason != SubscriptionDropReason.UserInitiated) { - exc = exc ?? new Exception($"Subscription dropped for {reason}"); - _source.TrySetException(exc); + var er = exc ?? new Exception(String.Format("Subscription dropped for {0}", reason)); + _source.TrySetException(er); } if (reason == SubscriptionDropReason.UserInitiated && _subscription != null && connection != null) connection.EnqueueSend(CreateUnsubscriptionPackage()); if (_subscription != null) - ExecuteActionAsync(() => _subscriptionDropped(_subscription, reason, exc)); + ExecuteActionAsync(() => + { + _subscriptionDropped(_subscription, reason, exc); + return Task.CompletedTask; + }); } } protected void ConfirmSubscription(long lastCommitPosition, long? lastEventNumber) { if (lastCommitPosition < -1) - throw new ArgumentOutOfRangeException("lastCommitPosition", string.Format("Invalid lastCommitPosition {0} on subscription confirmation.", lastCommitPosition)); + throw new ArgumentOutOfRangeException(nameof(lastCommitPosition), string.Format("Invalid lastCommitPosition {0} on subscription confirmation.", lastCommitPosition)); if (_subscription != null) throw new Exception("Double confirmation of subscription."); @@ -251,7 +255,7 @@ protected void EventAppeared(ResolvedEvent e) ExecuteActionAsync(() => _eventAppeared(_subscription, e)); } - private void ExecuteActionAsync(Action action) + private void ExecuteActionAsync(Func action) { _actionQueue.Enqueue(action); if (_actionQueue.Count > _maxQueueSize) DropSubscription(SubscriptionDropReason.UserInitiated, new Exception("client buffer too big")); @@ -259,16 +263,16 @@ private void ExecuteActionAsync(Action action) ThreadPool.QueueUserWorkItem(ExecuteActions); } - private void ExecuteActions(object state) + private async void ExecuteActions(object state) { do { - Action action; + Func action; while (_actionQueue.TryDequeue(out action)) { try { - action(); + await action().ConfigureAwait(false); } catch (Exception exc) { diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs index 60480b5..179e620 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs @@ -9,7 +9,7 @@ namespace EventStore.ClientAPI.ClientOperations { internal class VolatileSubscriptionOperation : SubscriptionOperation { - public VolatileSubscriptionOperation(ILogger log, TaskCompletionSource source, string streamId, bool resolveLinkTos, UserCredentials userCredentials, Action eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) + public VolatileSubscriptionOperation(ILogger log, TaskCompletionSource source, string streamId, bool resolveLinkTos, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) : base(log, source, streamId, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, verboseLogging, getConnection) { } diff --git a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs index ac9fc0c..9566aca 100644 --- a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs @@ -34,15 +34,15 @@ public static ClusterSettingsBuilder Create() /// Endpoints for seeding gossip if not using DNS. /// public readonly GossipSeed[] GossipSeeds; - + /// /// Timeout for cluster gossip. /// public TimeSpan GossipTimeout; - /// - ///Prefer a randomly selected node - /// + /// + /// Prefer a randomly selected node. + /// public bool PreferRandomNode; /// diff --git a/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/TaskExtensions.cs b/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/TaskExtensions.cs new file mode 100644 index 0000000..38ee842 --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/TaskExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading.Tasks; +using EventStore.ClientAPI.Exceptions; + +namespace EventStore.ClientAPI.Common.Utils.Threading +{ + internal static class TaskExtensions + { + public static async Task WithTimeout(this Task task, TimeSpan timeout) + { + if (await Task.WhenAny(task, Task.Delay(timeout)) != task) + { + throw new OperationTimedOutException(string.Format("The operation did not complete within the specified time of {0}", timeout)); + } + + return await task; + } + } +} diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs index b9acd99..56c0c11 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs @@ -122,10 +122,10 @@ public static ConnectionSettingsBuilder Create() public readonly TimeSpan GossipTimeout; /// - /// Whether to randomly choose a node that is alive from known nodes + /// Whether to randomly choose a node that's alive from the known nodes. /// public readonly bool PreferRandomNode; - + /// /// The interval after which a client will time out during connection. /// diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs index 4470fd0..490b598 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs @@ -40,7 +40,8 @@ public class ConnectionSettingsBuilder private int _gossipExternalHttpPort = Consts.DefaultClusterManagerExternalHttpPort; private TimeSpan _gossipTimeout = TimeSpan.FromSeconds(1); private GossipSeed[] _gossipSeeds; - private bool _preferRandomNode; + private bool _preferRandomNode = false; + internal ConnectionSettingsBuilder() { @@ -344,9 +345,9 @@ public ConnectionSettingsBuilder SetGossipTimeout(TimeSpan timeout) } /// - /// Whether to randomly choose a node that's alive from the known nodes. + /// Whether to randomly choose a node that's alive from the known nodes. /// - /// A for further configuration. + /// A for further configuration. public ConnectionSettingsBuilder PreferRandomNode() { _preferRandomNode = true; diff --git a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs index 3c12268..3786afc 100644 --- a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs @@ -55,7 +55,7 @@ public DnsClusterSettingsBuilder SetGossipTimeout(TimeSpan timeout) } /// - /// Whether to randomly choose a node that's alive from the known nodes. + /// Whether to randomly choose a node that's alive from the known nodes. /// /// A for further configuration. public DnsClusterSettingsBuilder PreferRandomNode() diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs index 3fd833d..ed767c4 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs @@ -19,12 +19,16 @@ public abstract class EventStoreCatchUpSubscription /// Indicates whether the subscription is to all events or to /// a specific stream. /// - public bool IsSubscribedToAll { get { return _streamId == string.Empty; } } + public bool IsSubscribedToAll => StreamId == string.Empty; /// /// The name of the stream to which the subscription is subscribed /// (empty if subscribed to all). /// - public string StreamId { get { return _streamId; } } + public string StreamId { get; } + /// + /// The name of subscription. + /// + public string SubscriptionName { get; } /// /// The to use for the subscription. @@ -34,7 +38,6 @@ public abstract class EventStoreCatchUpSubscription private readonly IEventStoreConnection _connection; private readonly bool _resolveLinkTos; private readonly UserCredentials _userCredentials; - private readonly string _streamId; /// /// The batch size to use during the read phase of the subscription. @@ -48,7 +51,7 @@ public abstract class EventStoreCatchUpSubscription /// /// Action invoked when a new event appears on the subscription. /// - protected readonly Action EventAppeared; + protected readonly Func EventAppeared; private readonly Action _liveProcessingStarted; private readonly Action _subscriptionDropped; /// @@ -86,7 +89,7 @@ protected abstract Task ReadEventsTillAsync(IEventStoreConnection connection, /// Try to process a single . /// /// The to process. - protected abstract void TryProcess(ResolvedEvent e); + protected abstract Task TryProcessAsync(ResolvedEvent e); /// /// Constructs state for EventStoreCatchUpSubscription. @@ -103,7 +106,7 @@ protected EventStoreCatchUpSubscription(IEventStoreConnection connection, ILogger log, string streamId, UserCredentials userCredentials, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted, Action subscriptionDropped, CatchUpSubscriptionSettings settings) @@ -113,7 +116,7 @@ protected EventStoreCatchUpSubscription(IEventStoreConnection connection, Ensure.NotNull(eventAppeared, "eventAppeared"); _connection = connection; Log = log; - _streamId = string.IsNullOrEmpty(streamId) ? string.Empty : streamId; + StreamId = string.IsNullOrEmpty(streamId) ? string.Empty : streamId; _resolveLinkTos = settings.ResolveLinkTos; _userCredentials = userCredentials; ReadBatchSize = settings.ReadBatchSize; @@ -123,12 +126,13 @@ protected EventStoreCatchUpSubscription(IEventStoreConnection connection, _liveProcessingStarted = liveProcessingStarted; _subscriptionDropped = subscriptionDropped; Verbose = settings.VerboseLogging; + SubscriptionName = settings.SubscriptionName ?? String.Empty; } - internal Task Start() + internal Task StartAsync() { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: starting...", IsSubscribedToAll ? "" : StreamId); - return RunSubscription(); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: starting...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); + return RunSubscriptionAsync(); } /// @@ -139,7 +143,7 @@ internal Task Start() public void Stop(TimeSpan timeout) { Stop(); - if (Verbose) Log.Debug("Waiting on subscription to stop"); + if (Verbose) Log.Debug("Waiting on subscription {0} to stop", SubscriptionName); if (!_stopped.Wait(timeout)) throw new TimeoutException(string.Format("Could not stop {0} in time.", GetType().Name)); } @@ -149,9 +153,8 @@ public void Stop(TimeSpan timeout) /// public void Stop() { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: requesting stop...", IsSubscribedToAll ? "" : StreamId); - - if (Verbose) Log.Debug("Catch-up Subscription to {0}: unhooking from connection.Connected.", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: requesting stop...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: unhooking from connection.Connected.", SubscriptionName, IsSubscribedToAll ? "" : StreamId); _connection.Connected -= OnReconnect; ShouldStop = true; @@ -160,32 +163,38 @@ public void Stop() private void OnReconnect(object sender, ClientConnectionEventArgs clientConnectionEventArgs) { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: recovering after reconnection.", IsSubscribedToAll ? "" : StreamId); - if (Verbose) Log.Debug("Catch-up Subscription to {0}: unhooking from connection.Connected.", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: recovering after reconnection.", SubscriptionName, IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: unhooking from connection.Connected.", SubscriptionName, IsSubscribedToAll ? "" : StreamId); _connection.Connected -= OnReconnect; - RunSubscription(); + RunSubscriptionAsync(); } - private Task RunSubscription() + private Task RunSubscriptionAsync() { - return Task.Factory.StartNew(LoadHistoricalEvents, TaskCreationOptions.AttachedToParent) - .ContinueWith(_ => HandleErrorOrContinue(_)); + return LoadHistoricalEventsAsync(); } - private void LoadHistoricalEvents() + private async Task LoadHistoricalEventsAsync() { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: running...", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: running...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); _stopped.Reset(); _allowProcessing = false; if (!ShouldStop) { - if (Verbose) - Log.Debug("Catch-up Subscription to {0}: pulling events...", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: pulling events...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); - ReadEventsTillAsync(_connection, _resolveLinkTos, _userCredentials, null, null) - .ContinueWith(_ => HandleErrorOrContinue(_, SubscribeToStream), TaskContinuationOptions.AttachedToParent); + try + { + await ReadEventsTillAsync(_connection, _resolveLinkTos, _userCredentials, null, null).ConfigureAwait(false); + await SubscribeToStreamAsync().ConfigureAwait(false); + } + catch (Exception ex) + { + DropSubscription(SubscriptionDropReason.CatchUpError, ex); + throw; + } } else { @@ -193,21 +202,19 @@ private void LoadHistoricalEvents() } } - private void SubscribeToStream() + private async Task SubscribeToStreamAsync() { if (!ShouldStop) { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: subscribing...", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: subscribing...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); - var subscribeTask = _streamId == string.Empty - ? _connection.SubscribeToAllAsync(_resolveLinkTos, EnqueuePushedEvent, ServerSubscriptionDropped, _userCredentials) - : _connection.SubscribeToStreamAsync(_streamId, _resolveLinkTos, EnqueuePushedEvent, ServerSubscriptionDropped, _userCredentials); + var subscription = + StreamId == string.Empty + ? await _connection.SubscribeToAllAsync(_resolveLinkTos, EnqueuePushedEvent, ServerSubscriptionDropped, _userCredentials).ConfigureAwait(false) + : await _connection.SubscribeToStreamAsync(StreamId, _resolveLinkTos, EnqueuePushedEvent, ServerSubscriptionDropped, _userCredentials).ConfigureAwait(false); - subscribeTask.ContinueWith(_ => HandleErrorOrContinue(_, () => - { - _subscription = _.Result; - ReadMissedHistoricEvents(); - }), TaskContinuationOptions.AttachedToParent); + _subscription = subscription; + await ReadMissedHistoricEventsAsync().ConfigureAwait(false); } else { @@ -215,14 +222,14 @@ private void SubscribeToStream() } } - private void ReadMissedHistoricEvents() + private async Task ReadMissedHistoricEventsAsync() { if (!ShouldStop) { - if (Verbose) Log.Debug("Catch-up Subscription to {0}: pulling events (if left)...", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: pulling events (if left)...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); - ReadEventsTillAsync(_connection, _resolveLinkTos, _userCredentials, _subscription.LastCommitPosition, _subscription.LastEventNumber) - .ContinueWith(_ => HandleErrorOrContinue(_, StartLiveProcessing), TaskContinuationOptions.AttachedToParent); + await ReadEventsTillAsync(_connection, _resolveLinkTos, _userCredentials, _subscription.LastCommitPosition, _subscription.LastEventNumber).ConfigureAwait(false); + StartLiveProcessing(); } else { @@ -238,54 +245,40 @@ private void StartLiveProcessing() return; } - if (Verbose) Log.Debug("Catch-up Subscription to {0}: processing live events...", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: processing live events...", SubscriptionName, IsSubscribedToAll ? "" : StreamId); if (_liveProcessingStarted != null) _liveProcessingStarted(this); - if (Verbose) Log.Debug("Catch-up Subscription to {0}: hooking to connection.Connected", IsSubscribedToAll ? "" : StreamId); + if (Verbose) Log.Debug("Catch-up Subscription {0} to {1}: hooking to connection.Connected", SubscriptionName, IsSubscribedToAll ? "" : StreamId); _connection.Connected += OnReconnect; _allowProcessing = true; EnsureProcessingPushQueue(); } - private void HandleErrorOrContinue(Task task, Action continuation = null) + private Task EnqueuePushedEvent(EventStoreSubscription subscription, ResolvedEvent e) { - if (task.IsFaulted) - { - DropSubscription(SubscriptionDropReason.CatchUpError, task.Exception.GetBaseException()); - task.Wait(); - } - else if (task.IsCanceled) - { - DropSubscription(SubscriptionDropReason.CatchUpError, new TaskCanceledException(task)); - task.Wait(); - } - else if (continuation != null) + if (Verbose) { - continuation(); + Log.Debug("Catch-up Subscription {0} to {1}: event appeared ({2}, {3}, {4} @ {5}).", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + e.OriginalStreamId, e.OriginalEventNumber, e.OriginalEvent.EventType, e.OriginalPosition); } - } - - private void EnqueuePushedEvent(EventStoreSubscription subscription, ResolvedEvent e) - { - if (Verbose) - Log.Debug("Catch-up Subscription to {0}: event appeared ({1}, {2}, {3} @ {4}).", - IsSubscribedToAll ? "" : StreamId, - e.OriginalStreamId, e.OriginalEventNumber, e.OriginalEvent.EventType, e.OriginalPosition); if (_liveQueue.Count >= MaxPushQueueSize) { EnqueueSubscriptionDropNotification(SubscriptionDropReason.ProcessingQueueOverflow, null); subscription.Unsubscribe(); - return; + return Task.CompletedTask; } _liveQueue.Enqueue(e); if (_allowProcessing) EnsureProcessingPushQueue(); + return Task.CompletedTask; } private void ServerSubscriptionDropped(EventStoreSubscription subscription, SubscriptionDropReason reason, Exception exc) @@ -308,10 +301,10 @@ private void EnqueueSubscriptionDropNotification(SubscriptionDropReason reason, private void EnsureProcessingPushQueue() { if (Interlocked.CompareExchange(ref _isProcessing, 1, 0) == 0) - ThreadPool.QueueUserWorkItem(_ => ProcessLiveQueue()); + ThreadPool.QueueUserWorkItem(_ => ProcessLiveQueueAsync()); } - private void ProcessLiveQueue() + private async void ProcessLiveQueueAsync() { do { @@ -320,7 +313,7 @@ private void ProcessLiveQueue() { if (e.Equals(DropSubscriptionEvent)) // drop subscription artificial ResolvedEvent { - if (_dropData == null) _dropData = new DropData(SubscriptionDropReason.Unknown, new Exception("Drop reason not specified.")); + _dropData = _dropData ?? new DropData(SubscriptionDropReason.Unknown, new Exception("Drop reason not specified.")); DropSubscription(_dropData.Reason, _dropData.Error); Interlocked.CompareExchange(ref _isProcessing, 0, 1); return; @@ -328,11 +321,11 @@ private void ProcessLiveQueue() try { - TryProcess(e); + await TryProcessAsync(e).ConfigureAwait(false); } catch (Exception exc) { - Log.Debug("Catch-up Subscription to {0} Exception occurred in subscription {1}",IsSubscribedToAll ? "" : StreamId, exc); + Log.Debug("Catch-up Subscription {0} to {1} Exception occurred in subscription {1}", SubscriptionName, IsSubscribedToAll ? "" : StreamId, exc); DropSubscription(SubscriptionDropReason.EventHandlerException, exc); return; } @@ -341,18 +334,18 @@ private void ProcessLiveQueue() } while (_liveQueue.Count > 0 && Interlocked.CompareExchange(ref _isProcessing, 1, 0) == 0); } - private void DropSubscription(SubscriptionDropReason reason, Exception error) + internal void DropSubscription(SubscriptionDropReason reason, Exception error) { if (Interlocked.CompareExchange(ref _isDropped, 1, 0) == 0) { if (Verbose) - Log.Debug("Catch-up Subscription to {0}: dropping subscription, reason: {1} {2}.", - IsSubscribedToAll ? "" : StreamId, reason, error == null ? string.Empty : error.ToString()); + Log.Debug("Catch-up Subscription {0} to {1}: dropping subscription, reason: {2} {3}.", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + reason, error == null ? string.Empty : error.ToString()); - if (_subscription != null) - _subscription.Unsubscribe(); - if (_subscriptionDropped != null) - _subscriptionDropped(this, reason, error); + _subscription?.Unsubscribe(); + _subscriptionDropped?.Invoke(this, reason, error); _stopped.Set(); } } @@ -373,7 +366,7 @@ public DropData(SubscriptionDropReason reason, Exception error) /// /// A catch-up subscription to all events in the Event Store. /// - public class EventStoreAllCatchUpSubscription: EventStoreCatchUpSubscription + public class EventStoreAllCatchUpSubscription : EventStoreCatchUpSubscription { /// /// The last position processed on the subscription. @@ -394,13 +387,12 @@ public Position LastProcessedPosition private Position _nextReadPosition; private Position _lastProcessedPosition; - private TaskCompletionSource _completion; internal EventStoreAllCatchUpSubscription(IEventStoreConnection connection, ILogger log, Position? fromPositionExclusive, /* if null -- from the very beginning */ UserCredentials userCredentials, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted, Action subscriptionDropped, CatchUpSubscriptionSettings settings) @@ -421,67 +413,43 @@ internal EventStoreAllCatchUpSubscription(IEventStoreConnection connection, /// The event number to read until. /// protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos, - UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) - { - _completion = new TaskCompletionSource(); - ReadEventsInternal(connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - return _completion.Task; - } + UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) => + ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - private void ReadEventsInternal(IEventStoreConnection connection, bool resolveLinkTos, + private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) { - try { - connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials) - .ContinueWith(_ => - { - ReadEventsCallback(_, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - }); - } - catch (Exception ex) - { - _completion.TrySetException(ex); - } + var slice = await connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false); + await ReadEventsCallbackAsync(slice, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber).ConfigureAwait(false); } - private void ReadEventsCallback(Task task, IEventStoreConnection connection, bool resolveLinkTos, + private async Task ReadEventsCallbackAsync(AllEventsSlice slice, IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) { - try + if (!(await ProcessEventsAsync(lastCommitPosition, slice).ConfigureAwait(false)) && !ShouldStop) { - if (task.IsFaulted || task.IsCanceled) - { - task.Wait(); //force exception to be thrown - } - - if (!ProcessEvents(lastCommitPosition, task.Result) && !ShouldStop) - { - ReadEventsInternal(connection, resolveLinkTos, userCredentials, - lastCommitPosition, lastEventNumber); - } - else - { - if (Verbose) - { - Log.Debug( - "Catch-up Subscription to {0}: finished reading events, nextReadPosition = {1}.", - IsSubscribedToAll ? "" : StreamId, _nextReadPosition); - } - _completion.TrySetResult(true); - } + await ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, + lastCommitPosition, lastEventNumber).ConfigureAwait(false); } - catch (Exception e) + else { - _completion.TrySetException(e); + if (Verbose) + { + Log.Debug( + "Catch-up Subscription {0} to {1}: finished reading events, nextReadPosition = {2}.", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + _nextReadPosition); + } } } - private bool ProcessEvents(long? lastCommitPosition, AllEventsSlice slice) + private async Task ProcessEventsAsync(long? lastCommitPosition, AllEventsSlice slice) { foreach (var e in slice.Events) { - if (e.OriginalPosition == null) throw new Exception("Subscription event came up with no OriginalPosition."); - TryProcess(e); + if (e.OriginalPosition == null) throw new Exception(String.Format("Subscription {0} event came up with no OriginalPosition.", SubscriptionName)); + await TryProcessAsync(e).ConfigureAwait(false); } _nextReadPosition = slice.NextPosition; @@ -498,19 +466,31 @@ private bool ProcessEvents(long? lastCommitPosition, AllEventsSlice slice) /// Try to process a single . /// /// The to process. - protected override void TryProcess(ResolvedEvent e) + protected override async Task TryProcessAsync(ResolvedEvent e) { bool processed = false; if (e.OriginalPosition > _lastProcessedPosition) { - EventAppeared(this, e); + try + { + await EventAppeared(this, e).ConfigureAwait(false); + } + catch (Exception ex) + { + DropSubscription(SubscriptionDropReason.EventHandlerException, ex); + throw; + } _lastProcessedPosition = e.OriginalPosition.Value; processed = true; } if (Verbose) - Log.Debug("Catch-up Subscription to {0}: {1} event ({2}, {3}, {4} @ {5}).", - IsSubscribedToAll ? "" : StreamId, processed ? "processed" : "skipping", - e.OriginalEvent.EventStreamId, e.OriginalEvent.EventNumber, e.OriginalEvent.EventType, e.OriginalPosition); + { + Log.Debug("Catch-up Subscription {0} to {1}: {2} event ({3}, {4}, {5} @ {6}).", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + processed ? "processed" : "skipping", + e.OriginalEvent.EventStreamId, e.OriginalEvent.EventNumber, e.OriginalEvent.EventType, e.OriginalPosition); + } } } @@ -526,14 +506,13 @@ public class EventStoreStreamCatchUpSubscription : EventStoreCatchUpSubscription private long _nextReadEventNumber; private long _lastProcessedEventNumber; - private TaskCompletionSource _completion; internal EventStoreStreamCatchUpSubscription(IEventStoreConnection connection, ILogger log, string streamId, long? fromEventNumberExclusive, /* if null -- from the very beginning */ UserCredentials userCredentials, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted, Action subscriptionDropped, CatchUpSubscriptionSettings settings) @@ -556,61 +535,35 @@ internal EventStoreStreamCatchUpSubscription(IEventStoreConnection connection, /// The event number to read until. /// protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, - long? lastCommitPosition, long? lastEventNumber) - { - _completion = new TaskCompletionSource(); - ReadEventsInternal(connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - return _completion.Task; - } - - private void ReadEventsInternal(IEventStoreConnection connection, bool resolveLinkTos, - UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) + long? lastCommitPosition, long? lastEventNumber) => + ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastEventNumber); + + private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos, + UserCredentials userCredentials, long? lastEventNumber) { - try { - connection.ReadStreamEventsForwardAsync(StreamId, _nextReadEventNumber, ReadBatchSize, resolveLinkTos, userCredentials) - .ContinueWith(_ => - { - ReadEventsCallback(_, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - }); - } - catch(Exception ex) + bool shouldStopOrDone; + do { - _completion.TrySetException(ex); - } + var slice = await connection.ReadStreamEventsForwardAsync(StreamId, _nextReadEventNumber, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false); + shouldStopOrDone = await ReadEventsCallbackAsync(slice, lastEventNumber).ConfigureAwait(false); + } while (!shouldStopOrDone); } - private void ReadEventsCallback(Task task, IEventStoreConnection connection, bool resolveLinkTos, - UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) + private async Task ReadEventsCallbackAsync(StreamEventsSlice slice, long? lastEventNumber) { - try - { - if (task.IsFaulted || task.IsCanceled) - { - task.Wait(); //force exception to be thrown - } - - if (!ProcessEvents(lastEventNumber, task.Result) && !ShouldStop) - { - ReadEventsInternal(connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); - } - else - { - if (Verbose) - { - Log.Debug( - "Catch-up Subscription to {0}: finished reading events, nextReadEventNumber = {1}.", - IsSubscribedToAll ? "" : StreamId, _nextReadEventNumber); - } - _completion.TrySetResult(true); - } - } - catch (Exception e) + bool shouldStopOrDone = ShouldStop || await ProcessEventsAsync(lastEventNumber, slice).ConfigureAwait(false); + if (shouldStopOrDone && Verbose) { - _completion.TrySetException(e); + Log.Debug( + "Catch-up Subscription {0} to {1}: finished reading events, nextReadEventNumber = {2}.", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + _nextReadEventNumber); } + return shouldStopOrDone; } - private bool ProcessEvents(long? lastEventNumber, StreamEventsSlice slice) + private async Task ProcessEventsAsync(long? lastEventNumber, StreamEventsSlice slice) { bool done; switch (slice.Status) @@ -619,7 +572,7 @@ private bool ProcessEvents(long? lastEventNumber, StreamEventsSlice slice) { foreach (var e in slice.Events) { - TryProcess(e); + await TryProcessAsync(e).ConfigureAwait(false); } _nextReadEventNumber = slice.NextEventNumber; done = lastEventNumber == null ? slice.IsEndOfStream : slice.NextEventNumber > lastEventNumber; @@ -628,17 +581,20 @@ private bool ProcessEvents(long? lastEventNumber, StreamEventsSlice slice) case SliceReadStatus.StreamNotFound: { if (lastEventNumber.HasValue && lastEventNumber != -1) + { throw new Exception( - string.Format("Impossible: stream {0} disappeared in the middle of catching up subscription.", - StreamId)); + string.Format("Impossible: stream {0} disappeared in the middle of catching up subscription {1}.", + StreamId, SubscriptionName)); + } + done = true; break; } case SliceReadStatus.StreamDeleted: throw new StreamDeletedException(StreamId); default: - throw new ArgumentOutOfRangeException(string.Format("Unexpected StreamEventsSlice.Status: {0}.", - slice.Status)); + throw new ArgumentOutOfRangeException(string.Format("Subscription {0} unexpected StreamEventsSlice.Status: {0}.", + SubscriptionName, slice.Status)); } if (!done && slice.IsEndOfStream) @@ -650,19 +606,30 @@ private bool ProcessEvents(long? lastEventNumber, StreamEventsSlice slice) /// Try to process a single . /// /// The to process. - protected override void TryProcess(ResolvedEvent e) + protected override async Task TryProcessAsync(ResolvedEvent e) { bool processed = false; if (e.OriginalEventNumber > _lastProcessedEventNumber) { - EventAppeared(this, e); + try + { + await EventAppeared(this, e).ConfigureAwait(false); + } + catch (Exception ex) + { + DropSubscription(SubscriptionDropReason.EventHandlerException, ex); + throw; + } _lastProcessedEventNumber = e.OriginalEventNumber; processed = true; } if (Verbose) - Log.Debug("Catch-up Subscription to {0}: {1} event ({2}, {3}, {4} @ {5}).", - IsSubscribedToAll ? "" : StreamId, processed ? "processed" : "skipping", - e.OriginalEvent.EventStreamId, e.OriginalEvent.EventNumber, e.OriginalEvent.EventType, e.OriginalEventNumber); + { + Log.Debug("Catch-up Subscription {0} to {1}: {2} event ({3}, {4}, {5} @ {6}).", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, processed ? "processed" : "skipping", + e.OriginalEvent.EventStreamId, e.OriginalEvent.EventNumber, e.OriginalEvent.EventType, e.OriginalEventNumber); + } } } } diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs index 91bc3af..40faca0 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs @@ -1,6 +1,5 @@ using System; using System.Threading.Tasks; -using EventStore.ClientAPI.Common.Utils.Threading; using EventStore.ClientAPI.Internal; using EventStore.ClientAPI.SystemData; @@ -15,7 +14,7 @@ public class EventStorePersistentSubscription : EventStorePersistentSubscription internal EventStorePersistentSubscription( string subscriptionId, string streamId, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped, UserCredentials userCredentials, ILogger log, bool verboseLogging, ConnectionSettings settings, EventStoreConnectionLogicHandler handler, int bufferSize = 10, bool autoAck = true) @@ -27,7 +26,8 @@ internal EventStorePersistentSubscription( } internal override Task StartSubscription( - string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, Action onEventAppeared, + string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, + Func onEventAppeared, Action onSubscriptionDropped, ConnectionSettings settings) { var source = new TaskCompletionSource(); diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs index b1ff7fc..9297793 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using EventStore.ClientAPI.Internal; using EventStore.ClientAPI.SystemData; namespace EventStore.ClientAPI @@ -22,7 +21,7 @@ public abstract class EventStorePersistentSubscriptionBase private readonly string _subscriptionId; private readonly string _streamId; - private readonly Action _eventAppeared; + private readonly Func _eventAppeared; private readonly Action _subscriptionDropped; private readonly UserCredentials _userCredentials; private readonly ILogger _log; @@ -40,8 +39,8 @@ public abstract class EventStorePersistentSubscriptionBase private readonly int _bufferSize; internal EventStorePersistentSubscriptionBase(string subscriptionId, - string streamId, - Action eventAppeared, + string streamId, + Func eventAppeared, Action subscriptionDropped, UserCredentials userCredentials, ILogger log, @@ -78,7 +77,7 @@ internal Task Start() internal abstract Task StartSubscription( string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, - Action onEventAppeared, + Func onEventAppeared, Action onSubscriptionDropped, ConnectionSettings settings); @@ -178,9 +177,10 @@ private void OnSubscriptionDropped(EventStoreSubscription subscription, Subscrip EnqueueSubscriptionDropNotification(reason, exception); } - private void OnEventAppeared(EventStoreSubscription subscription, ResolvedEvent resolvedEvent) + private Task OnEventAppeared(EventStoreSubscription subscription, ResolvedEvent resolvedEvent) { Enqueue(resolvedEvent); + return Task.CompletedTask; } private void Enqueue(ResolvedEvent resolvedEvent) @@ -191,7 +191,7 @@ private void Enqueue(ResolvedEvent resolvedEvent) } - private void ProcessQueue() + private async void ProcessQueue() { do { @@ -217,7 +217,7 @@ private void ProcessQueue() } try { - _eventAppeared(this, e); + await _eventAppeared(this, e).ConfigureAwait(false); if (_autoAck) _subscription.NotifyEventsProcessed(new[] { e.OriginalEvent.EventId }); if (_verbose) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreSubscription.cs index f901336..682d287 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreSubscription.cs @@ -11,11 +11,11 @@ public abstract class EventStoreSubscription : IDisposable /// /// True if this subscription is to all streams. /// - public bool IsSubscribedToAll { get { return _streamId == string.Empty; } } + public bool IsSubscribedToAll { get { return StreamId == string.Empty; } } /// /// The name of the stream to which the subscription is subscribed. /// - public string StreamId { get { return _streamId; } } + public string StreamId { get; } /// /// The last commit position seen on the subscription (if this is /// a subscription to all events). @@ -27,11 +27,9 @@ public abstract class EventStoreSubscription : IDisposable /// public readonly long? LastEventNumber; - private readonly string _streamId; - internal EventStoreSubscription(string streamId, long lastCommitPosition, long? lastEventNumber) { - _streamId = streamId; + StreamId = streamId; LastCommitPosition = lastCommitPosition; LastEventNumber = lastEventNumber; } diff --git a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs index e386cda..9d1b95d 100644 --- a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs @@ -78,7 +78,7 @@ public GossipSeedClusterSettingsBuilder SetGossipTimeout(TimeSpan timeout) } /// - /// Whether or nto to randomly choose a node that's alive from the known nodes. + /// Whether to randomly choose a node that's alive from the known nodes. /// /// A for further configuration. public GossipSeedClusterSettingsBuilder PreferRandomNode() diff --git a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs index 4835cc6..e191a90 100644 --- a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs @@ -45,7 +45,7 @@ public interface IEventStoreConnection : IDisposable /// The name of the stream to delete. /// The expected version that the streams should have when being deleted. /// The optional user credentials to perform operation with. - /// A that can be awaited upon by the caller. + /// A containing the results of the delete stream operation. Task DeleteStreamAsync(string stream, long expectedVersion, UserCredentials userCredentials = null); /// @@ -56,7 +56,7 @@ public interface IEventStoreConnection : IDisposable /// Indicator for tombstoning vs soft-deleting the stream. Tombstoned streams can never be recreated. Soft-deleted streams /// can be written to again, but the EventNumber sequence will not start from 0. /// The optional user credentials to perform operation with. - /// A that can be awaited upon by the caller. + /// A containing the results of the delete stream operation. Task DeleteStreamAsync(string stream, long expectedVersion, bool hardDelete, UserCredentials userCredentials = null); /// @@ -75,6 +75,7 @@ public interface IEventStoreConnection : IDisposable /// The name of the stream to append events to /// The of the stream to append to /// The events to append to the stream + /// A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, params EventData[] events); /// @@ -94,6 +95,7 @@ public interface IEventStoreConnection : IDisposable /// The of the stream to append to /// The optional user credentials to perform operation with. /// The events to append to the stream + /// A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, UserCredentials userCredentials, params EventData[] events); /// @@ -113,6 +115,7 @@ public interface IEventStoreConnection : IDisposable /// The of the stream to append to /// The events to append to the stream /// The optional user credentials to perform operation with. + ///A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null); /// @@ -132,7 +135,7 @@ public interface IEventStoreConnection : IDisposable /// The of the stream to append to /// The events to append to the stream /// The optional user credentials to perform operation with. - /// If the operation succeeded and, if not, the reason for failure (which can be either stream version mismatch or trying to write to a deleted stream) + /// A describing if the operation succeeded and, if not, the reason for failure (which can be either stream version mismatch or trying to write to a deleted stream). Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null); /// @@ -146,7 +149,7 @@ public interface IEventStoreConnection : IDisposable /// The stream to start a transaction on /// The expected version of the stream at the time of starting the transaction /// The optional user credentials to perform operation with. - /// A task the caller can use to control the operation. + /// A representing a multi-request transaction. Task StartTransactionAsync(string stream, long expectedVersion, UserCredentials userCredentials = null); /// @@ -159,7 +162,7 @@ public interface IEventStoreConnection : IDisposable /// /// The transaction ID that needs to be continued. /// The optional user credentials to perform operation with. - /// object. + /// A representing a multi-request transaction. EventStoreTransaction ContinueTransaction(long transactionId, UserCredentials userCredentials = null); /// @@ -169,7 +172,7 @@ public interface IEventStoreConnection : IDisposable /// The event number to read, StreamPosition.End to read the last event in the stream /// Whether to resolve LinkTo events automatically /// The optional user credentials to perform operation with. - /// A containing the results of the read operation + /// A containing the results of the read operation. Task ReadEventAsync(string stream, long eventNumber, bool resolveLinkTos, UserCredentials userCredentials = null); /// @@ -180,7 +183,7 @@ public interface IEventStoreConnection : IDisposable /// The count of items to read /// Whether to resolve LinkTo events automatically /// The optional user credentials to perform operation with. - /// A containing the results of the read operation + /// A containing the results of the read operation. Task ReadStreamEventsForwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null); /// @@ -191,7 +194,7 @@ public interface IEventStoreConnection : IDisposable /// The count to read from the position /// Whether to resolve LinkTo events automatically /// The optional user credentials to perform operation with. - /// An containing the results of the read operation + /// A containing the results of the read operation. Task ReadStreamEventsBackwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null); /// @@ -201,7 +204,7 @@ public interface IEventStoreConnection : IDisposable /// The maximum count to read /// Whether to resolve LinkTo events automatically /// The optional user credentials to perform operation with. - /// A containing the records read + /// A containing the records read. Task ReadAllEventsForwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null); /// @@ -211,7 +214,7 @@ public interface IEventStoreConnection : IDisposable /// The maximum count to read /// Whether to resolve Link events automatically /// The optional user credentials to perform operation with. - /// A containing the records read + /// A containing the records read. Task ReadAllEventsBackwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null); /// @@ -221,14 +224,14 @@ public interface IEventStoreConnection : IDisposable /// /// The stream to subscribe to /// Whether to resolve Link events automatically - /// An action invoked when a new event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked if the subscription is dropped /// User credentials to use for the operation - /// An representing the subscription + /// A representing the subscription. Task SubscribeToStreamAsync( string stream, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null); @@ -257,22 +260,24 @@ Task SubscribeToStreamAsync( /// NOTE: Using here will result in missing /// the first event in the stream. /// Whether to resolve Link events automatically - /// An action invoked when an event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked when the subscription switches to newly-pushed events /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The batch size to use during the read phase - /// An representing the subscription + /// The name of subscription + /// An representing the subscription. [Obsolete("This method will be obsoleted in the next major version please switch to the overload with a settings object")] EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( string stream, long? lastCheckpoint, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null, - int readBatchSize = 500); + int readBatchSize = 500, + string subscriptionName = ""); /// /// Subscribes to a single event stream. Existing events from @@ -298,17 +303,17 @@ EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( /// /// NOTE: Using here will result in missing /// the first event in the stream. - /// An action invoked when an event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked when the subscription switches to newly-pushed events /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The for the subscription - /// An representing the subscription + /// An representing the subscription. EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( string stream, long? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null); @@ -321,13 +326,13 @@ EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( /// will be pushed to the client. /// /// Whether to resolve Link events automatically - /// An action invoked when a new event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked if the subscription is dropped /// User credentials to use for the operation - /// An representing the subscription + /// A representing the subscription. Task SubscribeToAllAsync( bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null); @@ -336,7 +341,7 @@ Task SubscribeToAllAsync( /// /// The subscription group to connect to /// The stream to subscribe to - /// An action invoked when an event appears + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The buffer size to use for the persistent subscription @@ -348,11 +353,11 @@ Task SubscribeToAllAsync( /// If one connection dies work will be balanced across the rest of the consumers in the group. If /// you attempt to connect to a group that does not exist you will be given an exception. /// - /// An representing the subscription + /// An representing the subscription. EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( string stream, string groupName, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -363,7 +368,7 @@ EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( /// /// The subscription group to connect to /// The stream to subscribe to - /// An action invoked when an event appears + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The buffer size to use for the persistent subscription @@ -375,11 +380,11 @@ EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( /// If one connection dies work will be balanced across the rest of the consumers in the group. If /// you attempt to connect to a group that does not exist you will be given an exception. /// - /// An representing the subscription + /// An representing the subscription. Task ConnectToPersistentSubscriptionAsync( string stream, string groupName, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -390,7 +395,7 @@ Task ConnectToPersistentSubscriptionAsync( /// Subscribes a persistent subscription (competing consumer) to all events in the event store /// /// The subscription group to connect to - /// An action invoked when an event appears + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The buffer size to use for the persistent subscription @@ -435,21 +440,23 @@ EventStorePersistentSubscription ConnectToPersistentSubscriptionForAll( /// NOTE: Using here will result in missing /// the first event in the stream. /// Whether to resolve Link events automatically - /// An action invoked when an event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked when the subscription switches to newly-pushed events /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The batch size to use during the read phase - /// An representing the subscription + /// The name of subscription + /// An representing the subscription. [Obsolete("This overload will be removed in the next major release please use the overload with a settings object")] EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null, - int readBatchSize = 500); + int readBatchSize = 500, + string subscriptionName = ""); /// /// Subscribes to a all events. Existing events from lastCheckpoint @@ -473,16 +480,16 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// /// NOTE: Using here will result in missing /// the first event in the stream. - /// An action invoked when an event is received over the subscription + /// A Task invoked and awaited when a new event is received over the subscription /// An action invoked when the subscription switches to newly-pushed events /// An action invoked if the subscription is dropped /// User credentials to use for the operation /// The for the subscription - /// An representing the subscription + /// An representing the subscription. EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null); @@ -507,7 +514,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The name of the group to create /// The for the subscription /// The credentials to be used for this operation. - /// A . + /// A that can be waited upon. Task UpdatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials); @@ -518,7 +525,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The name of the group to create /// The for the subscription /// The credentials to be used for this operation. - /// A . + /// A that can be waited upon. Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials); @@ -528,7 +535,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The name of the stream to delete the persistent subscription on /// The name of the group to delete /// User credentials to use for the operation - /// A . + /// A that can be waited upon. Task DeletePersistentSubscriptionAsync(string stream, string groupName, UserCredentials userCredentials = null); /* @@ -548,7 +555,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The expected version for the write to the metadata stream. /// A representing the new metadata. /// User credentials to use for the operation - /// A . + /// A containing the results of the write operation. Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, StreamMetadata metadata, UserCredentials userCredentials = null); /// @@ -558,7 +565,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The expected version for the write to the metadata stream. /// A byte array representing the new metadata. /// User credentials to use for the operation. - /// A . + /// A containing the results of the write operation. Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, byte[] metadata, UserCredentials userCredentials = null); /// @@ -566,7 +573,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// /// The name of the stream for which to read metadata. /// User credentials to use for the operation. - /// A representing the result of the operation. + /// A representing system and user-specified metadata as properties. Task GetStreamMetadataAsync(string stream, UserCredentials userCredentials = null); /// @@ -574,7 +581,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// /// The name of the stream for which to read metadata. /// User credentials to use for the operation. - /// A representing the result of the operation. + /// A representing system metadata as properties and user-specified metadata as bytes. Task GetStreamMetadataAsRawBytesAsync(string stream, UserCredentials userCredentials = null); /// @@ -583,6 +590,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// /// The to apply. /// User credentials to use for the operation. + /// A that can be waited upon. Task SetSystemSettingsAsync(SystemSettings settings, UserCredentials userCredentials = null); /// diff --git a/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs b/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs new file mode 100644 index 0000000..f9dce42 --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs @@ -0,0 +1,351 @@ +using System; +using System.Threading.Tasks; +using EventStore.ClientAPI.SystemData; + +namespace EventStore.ClientAPI +{ + /// + /// Extensions for + /// + public static class IEventStoreConnectionExtensions + { + + private static Func ToTask(Action eventAppeared) => + (subscription, e) => + { + eventAppeared(subscription, e); + return Task.CompletedTask; + }; + + /// + /// Asynchronously subscribes to a single event stream. New events + /// written to the stream while the subscription is active will be + /// pushed to the client. + /// + /// The connection to subscribe to + /// The stream to subscribe to + /// Whether to resolve Link events automatically + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// An representing the subscription + public static Task SubscribeToStreamAsync( + this IEventStoreConnection target, + string stream, + bool resolveLinkTos, + Action eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null) => + target.SubscribeToStreamAsync( + stream, + resolveLinkTos, + ToTask(eventAppeared), + subscriptionDropped, + userCredentials + ); + + /// + /// Subscribes to a single event stream. Existing events from + /// lastCheckpoint onwards are read from the stream + /// and presented to the user of + /// as if they had been pushed. + /// + /// Once the end of the stream is read the subscription is + /// transparently (to the user) switched to push new events as + /// they are written. + /// + /// The action liveProcessingStarted is called when the + /// switches from the reading + /// phase to the live subscription phase. + /// + /// The stream to subscribe to + /// The event number from which to start. + /// + /// To receive all events in the stream, use . + /// If events have already been received and resubscription from the same point + /// is desired, use the event number of the last event processed which + /// appeared on the subscription. + /// + /// NOTE: Using here will result in missing + /// the first event in the stream. + /// The connection to subscribe to + /// Whether to resolve Link events automatically + /// An action invoked when a new event is received over the subscription + /// An action invoked when the subscription switches to newly-pushed events + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The batch size to use during the read phase + /// The name of subscription + /// An representing the subscription + [Obsolete("This method will be obsoleted in the next major version please switch to the overload with a settings object")] + public static EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( + this IEventStoreConnection target, + string stream, + long? lastCheckpoint, + bool resolveLinkTos, + Action eventAppeared, + Action liveProcessingStarted = null, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int readBatchSize = 500, + string subscriptionName = "") => + target.SubscribeToStreamFrom( + stream, + lastCheckpoint, + resolveLinkTos, + ToTask(eventAppeared), + liveProcessingStarted, + subscriptionDropped, + userCredentials, + readBatchSize, + subscriptionName + ); + + /// + /// Subscribes to a single event stream. Existing events from + /// lastCheckpoint onwards are read from the stream + /// and presented to the user of + /// as if they had been pushed. + /// + /// Once the end of the stream is read the subscription is + /// transparently (to the user) switched to push new events as + /// they are written. + /// + /// The action liveProcessingStarted is called when the + /// switches from the reading + /// phase to the live subscription phase. + /// + /// The stream to subscribe to + /// The event number from which to start. + /// + /// To receive all events in the stream, use . + /// If events have already been received and resubscription from the same point + /// is desired, use the event number of the last event processed which + /// appeared on the subscription. + /// + /// NOTE: Using here will result in missing + /// the first event in the stream. + /// The connection to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked when the subscription switches to newly-pushed events + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The for the subscription + /// An representing the subscription + public static EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( + this IEventStoreConnection target, + string stream, + long? lastCheckpoint, + CatchUpSubscriptionSettings settings, + Action eventAppeared, + Action liveProcessingStarted = null, + Action subscriptionDropped = null, + UserCredentials userCredentials = null) => + target.SubscribeToStreamFrom( + stream, + lastCheckpoint, + settings, + ToTask(eventAppeared), + liveProcessingStarted, + subscriptionDropped, + userCredentials + ); + + /// + /// Asynchronously subscribes to all events in the Event Store. New + /// events written to the stream while the subscription is active + /// will be pushed to the client. + /// + /// The connection to subscribe to + /// Whether to resolve Link events automatically + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// An representing the subscription + public static Task SubscribeToAllAsync( + this IEventStoreConnection target, + bool resolveLinkTos, + Action eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null) => + target.SubscribeToAllAsync( + resolveLinkTos, + ToTask(eventAppeared), + subscriptionDropped, + userCredentials + ); + + /// + /// Subscribes to a persistent subscription(competing consumer) on event store + /// + /// The connection to subscribe to + /// The subscription group to connect to + /// The stream to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The buffer size to use for the persistent subscription + /// Whether the subscription should automatically acknowledge messages processed. + /// If not set the receiver is required to explicitly acknowledge messages through the subscription. + /// This will connect you to a persistent subscription group for a stream. The subscription group + /// must first be created with CreatePersistentSubscriptionAsync many connections + /// can connect to the same group and they will be treated as competing consumers within the group. + /// If one connection dies work will be balanced across the rest of the consumers in the group. If + /// you attempt to connect to a group that does not exist you will be given an exception. + /// + /// An representing the subscription + public static EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( + this IEventStoreConnection target, + string stream, + string groupName, + Action eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int bufferSize = 10, + bool autoAck = true) => + target.ConnectToPersistentSubscription( + stream, + groupName, + ToTask(eventAppeared), + subscriptionDropped, + userCredentials, + bufferSize, + autoAck + ); + + /// + /// Asynchronously subscribes to a persistent subscription(competing consumer) on event store + /// + /// The connection to subscribe to + /// The subscription group to connect to + /// The stream to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The buffer size to use for the persistent subscription + /// Whether the subscription should automatically acknowledge messages processed. + /// If not set the receiver is required to explicitly acknowledge messages through the subscription. + /// This will connect you to a persistent subscription group for a stream. The subscription group + /// must first be created with CreatePersistentSubscriptionAsync many connections + /// can connect to the same group and they will be treated as competing consumers within the group. + /// If one connection dies work will be balanced across the rest of the consumers in the group. If + /// you attempt to connect to a group that does not exist you will be given an exception. + /// + /// An representing the subscription + public static Task ConnectToPersistentSubscriptionAsync( + this IEventStoreConnection target, + string stream, + string groupName, + Action eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int bufferSize = 10, + bool autoAck = true) => + target.ConnectToPersistentSubscriptionAsync( + stream, + groupName, + ToTask(eventAppeared), + subscriptionDropped, + userCredentials, + bufferSize, + autoAck + ); + + /// + /// Subscribes to all events. Existing events from lastCheckpoint + /// onwards are read from the Event Store and presented to the user of + /// as if they had been pushed. + /// + /// Once the end of the stream is read the subscription is + /// transparently (to the user) switched to push new events as + /// they are written. + /// + /// The action liveProcessingStarted is called when the + /// switches from the reading + /// phase to the live subscription phase. + /// + /// The position from which to start. + /// + /// To receive all events in the database, use . + /// If events have already been received and resubscription from the same point + /// is desired, use the position representing the last event processed which + /// appeared on the subscription. + /// + /// NOTE: Using here will result in missing + /// the first event in the stream. + /// The connection to subscribe to + /// Whether to resolve Link events automatically + /// An action invoked when a new event is received over the subscription + /// An action invoked when the subscription switches to newly-pushed events + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The batch size to use during the read phase + /// The name of subscription + /// An representing the subscription + [Obsolete("This overload will be removed in the next major release please use the overload with a settings object")] + public static EventStoreAllCatchUpSubscription SubscribeToAllFrom( + this IEventStoreConnection target, + Position? lastCheckpoint, + bool resolveLinkTos, + Action eventAppeared, + Action liveProcessingStarted = null, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int readBatchSize = 500, + string subscriptionName = "") => + target.SubscribeToAllFrom( + lastCheckpoint, + resolveLinkTos, + ToTask(eventAppeared), + liveProcessingStarted, + subscriptionDropped, + userCredentials + ); + + /// + /// Subscribes to a all events. Existing events from lastCheckpoint + /// onwards are read from the Event Store and presented to the user of + /// as if they had been pushed. + /// + /// Once the end of the stream is read the subscription is + /// transparently (to the user) switched to push new events as + /// they are written. + /// + /// The action liveProcessingStarted is called when the + /// switches from the reading + /// phase to the live subscription phase. + /// + /// The position from which to start. + /// + /// To receive all events in the database, use . + /// If events have already been received and resubscription from the same point + /// is desired, use the position representing the last event processed which + /// appeared on the subscription. + /// + /// NOTE: Using here will result in missing + /// the first event in the stream. + /// The connection to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked when the subscription switches to newly-pushed events + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The for the subscription + /// An representing the subscription + public static EventStoreAllCatchUpSubscription SubscribeToAllFrom( + this IEventStoreConnection target, + Position? lastCheckpoint, + CatchUpSubscriptionSettings settings, + Action eventAppeared, + Action liveProcessingStarted = null, + Action subscriptionDropped = null, + UserCredentials userCredentials = null) => + target.SubscribeToAllFrom( + lastCheckpoint, + settings, + ToTask(eventAppeared), + liveProcessingStarted, + subscriptionDropped, + userCredentials + ); + } +} diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreConnectionLogicHandler.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreConnectionLogicHandler.cs index 48d7f7e..d8bf81d 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreConnectionLogicHandler.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreConnectionLogicHandler.cs @@ -6,9 +6,9 @@ using EventStore.ClientAPI.ClientOperations; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Exceptions; -using EventStore.ClientAPI.Messages; using EventStore.ClientAPI.SystemData; using EventStore.ClientAPI.Transport.Tcp; +using EventStore.ClientAPI.Messages; namespace EventStore.ClientAPI.Internal { @@ -122,14 +122,12 @@ private void DiscoverEndPoint(TaskCompletionSource completionTask) if (t.IsFaulted) { EnqueueMessage(new CloseConnectionMessage("Failed to resolve TCP end point to which to connect.", t.Exception)); - if (completionTask != null) - completionTask.SetException(new CannotEstablishConnectionException("Cannot resolve target end point.", t.Exception)); + completionTask?.SetException(new CannotEstablishConnectionException("Cannot resolve target end point.", t.Exception)); } else { EnqueueMessage(new EstablishTcpConnectionMessage(t.Result)); - if (completionTask != null) - completionTask.SetResult(null); + completionTask?.SetResult(null); } }); } @@ -324,7 +322,7 @@ private void TimerTick() } if (_connectingPhase == ConnectingPhase.Identification && _stopwatch.Elapsed - _identifyInfo.TimeStamp >= _settings.OperationTimeout) { - string msg = "Timed out waiting for client to be identified"; + const string msg = "Timed out waiting for client to be identified"; LogDebug(msg); CloseTcpConnection(msg); } diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs index 3772e63..1f5d0dc 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs @@ -25,29 +25,19 @@ namespace EventStore.ClientAPI.Internal /// internal class EventStoreNodeConnection : IEventStoreConnection, IEventStoreTransactionConnection { - public string ConnectionName { get { return _connectionName; } } - - private readonly string _connectionName; - private readonly ConnectionSettings _settings; - private readonly ClusterSettings _clusterSettings; + public string ConnectionName { get; } private readonly IEndPointDiscoverer _endPointDiscoverer; private readonly EventStoreConnectionLogicHandler _handler; /// /// Returns the use to create this connection /// - public ConnectionSettings Settings - { - get { return _settings; } - } + public ConnectionSettings Settings { get; } /// /// Returns the use to create this connection /// - public ClusterSettings ClusterSettings - { - get { return _clusterSettings; } - } + public ClusterSettings ClusterSettings { get; } /// /// Constructs a new instance of a @@ -61,9 +51,9 @@ internal EventStoreNodeConnection(ConnectionSettings settings, ClusterSettings c Ensure.NotNull(settings, "settings"); Ensure.NotNull(endPointDiscoverer, "endPointDiscoverer"); - _connectionName = connectionName ?? string.Format("ES-{0}", Guid.NewGuid()); - _settings = settings; - _clusterSettings = clusterSettings; + ConnectionName = connectionName ?? string.Format("ES-{0}", Guid.NewGuid()); + Settings = settings; + ClusterSettings = clusterSettings; _endPointDiscoverer = endPointDiscoverer; _handler = new EventStoreConnectionLogicHandler(this, settings); } @@ -95,7 +85,7 @@ public Task DeleteStreamAsync(string stream, long expectedVersion, Ensure.NotNullOrEmpty(stream, "stream"); var source = new TaskCompletionSource(); - EnqueueOperation(new DeleteStreamOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new DeleteStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, hardDelete, userCredentials)); return source.Task; } @@ -123,7 +113,7 @@ public Task AppendToStreamAsync(string stream, long expectedVersion Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(); - EnqueueOperation(new AppendToStreamOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new AppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, events, userCredentials)); return source.Task; // ReSharper restore PossibleMultipleEnumeration @@ -137,7 +127,7 @@ public Task ConditionalAppendToStreamAsync(string stream Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(); - EnqueueOperation(new ConditionalAppendToStreamOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new ConditionalAppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, events, userCredentials)); return source.Task; // ReSharper restore PossibleMultipleEnumeration @@ -148,7 +138,7 @@ public Task StartTransactionAsync(string stream, long exp Ensure.NotNullOrEmpty(stream, "stream"); var source = new TaskCompletionSource(); - EnqueueOperation(new StartTransactionOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new StartTransactionOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, this, userCredentials)); return source.Task; } @@ -166,7 +156,7 @@ Task IEventStoreTransactionConnection.TransactionalWriteAsync(EventStoreTransact Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(); - EnqueueOperation(new TransactionalWriteOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new TransactionalWriteOperation(Settings.Log, source, Settings.RequireMaster, transaction.TransactionId, events, userCredentials)); return source.Task; // ReSharper restore PossibleMultipleEnumeration @@ -177,7 +167,7 @@ Task IEventStoreTransactionConnection.CommitTransactionAsync(EventS Ensure.NotNull(transaction, "transaction"); var source = new TaskCompletionSource(); - EnqueueOperation(new CommitTransactionOperation(_settings.Log, source, _settings.RequireMaster, + EnqueueOperation(new CommitTransactionOperation(Settings.Log, source, Settings.RequireMaster, transaction.TransactionId, userCredentials)); return source.Task; } @@ -186,10 +176,10 @@ Task IEventStoreTransactionConnection.CommitTransactionAsync(EventS public Task ReadEventAsync(string stream, long eventNumber, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); - if (eventNumber < -1) throw new ArgumentOutOfRangeException("eventNumber"); + if (eventNumber < -1) throw new ArgumentOutOfRangeException(nameof(eventNumber)); var source = new TaskCompletionSource(); - var operation = new ReadEventOperation(_settings.Log, source, stream, eventNumber, resolveLinkTos, - _settings.RequireMaster, userCredentials); + var operation = new ReadEventOperation(Settings.Log, source, stream, eventNumber, resolveLinkTos, + Settings.RequireMaster, userCredentials); EnqueueOperation(operation); return source.Task; } @@ -201,8 +191,8 @@ public Task ReadStreamEventsForwardAsync(string stream, long Ensure.Positive(count, "count"); if(count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); var source = new TaskCompletionSource(); - var operation = new ReadStreamEventsForwardOperation(_settings.Log, source, stream, start, count, - resolveLinkTos, _settings.RequireMaster, userCredentials); + var operation = new ReadStreamEventsForwardOperation(Settings.Log, source, stream, start, count, + resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); return source.Task; } @@ -213,8 +203,8 @@ public Task ReadStreamEventsBackwardAsync(string stream, long Ensure.Positive(count, "count"); if (count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); var source = new TaskCompletionSource(); - var operation = new ReadStreamEventsBackwardOperation(_settings.Log, source, stream, start, count, - resolveLinkTos, _settings.RequireMaster, userCredentials); + var operation = new ReadStreamEventsBackwardOperation(Settings.Log, source, stream, start, count, + resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); return source.Task; } @@ -224,8 +214,8 @@ public Task ReadAllEventsForwardAsync(Position position, int max Ensure.Positive(maxCount, "maxCount"); if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); var source = new TaskCompletionSource(); - var operation = new ReadAllEventsForwardOperation(_settings.Log, source, position, maxCount, - resolveLinkTos, _settings.RequireMaster, userCredentials); + var operation = new ReadAllEventsForwardOperation(Settings.Log, source, position, maxCount, + resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); return source.Task; } @@ -235,25 +225,25 @@ public Task ReadAllEventsBackwardAsync(Position position, int ma Ensure.Positive(maxCount, "maxCount"); if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); var source = new TaskCompletionSource(); - var operation = new ReadAllEventsBackwardOperation(_settings.Log, source, position, maxCount, - resolveLinkTos, _settings.RequireMaster, userCredentials); + var operation = new ReadAllEventsBackwardOperation(Settings.Log, source, position, maxCount, + resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); return source.Task; } private void EnqueueOperation(IClientOperation operation) { - while (_handler.TotalOperationCount >= _settings.MaxQueueSize) + while (_handler.TotalOperationCount >= Settings.MaxQueueSize) { Thread.Sleep(1); } - _handler.EnqueueMessage(new StartOperationMessage(operation, _settings.MaxRetries, _settings.OperationTimeout)); + _handler.EnqueueMessage(new StartOperationMessage(operation, Settings.MaxRetries, Settings.OperationTimeout)); } public Task SubscribeToStreamAsync( string stream, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null) { @@ -263,21 +253,24 @@ public Task SubscribeToStreamAsync( var source = new TaskCompletionSource(); _handler.EnqueueMessage(new StartSubscriptionMessage(source, stream, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, - _settings.MaxRetries, _settings.OperationTimeout)); + Settings.MaxRetries, Settings.OperationTimeout)); return source.Task; } public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom(string stream, long? lastCheckpoint, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null, - int readBatchSize = 500) + int readBatchSize = 500, + string subscriptionName = "") { var settings = new CatchUpSubscriptionSettings(Consts.CatchUpDefaultMaxPushQueueSize, readBatchSize, - _settings.VerboseLogging, resolveLinkTos); + Settings.VerboseLogging, + resolveLinkTos, + subscriptionName); return SubscribeToStreamFrom(stream, lastCheckpoint, settings, eventAppeared, liveProcessingStarted, subscriptionDropped, userCredentials); } @@ -285,7 +278,7 @@ public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( string stream, long? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null) @@ -294,16 +287,16 @@ public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( Ensure.NotNull(settings, "settings"); Ensure.NotNull(eventAppeared, "eventAppeared"); var catchUpSubscription = - new EventStoreStreamCatchUpSubscription(this, _settings.Log, stream, lastCheckpoint, + new EventStoreStreamCatchUpSubscription(this, Settings.Log, stream, lastCheckpoint, userCredentials, eventAppeared, liveProcessingStarted, subscriptionDropped, settings); - catchUpSubscription.Start(); + catchUpSubscription.StartAsync(); return catchUpSubscription; } public Task SubscribeToAllAsync( bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null) { @@ -312,28 +305,29 @@ public Task SubscribeToAllAsync( var source = new TaskCompletionSource(); _handler.EnqueueMessage(new StartSubscriptionMessage(source, string.Empty, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, - _settings.MaxRetries, _settings.OperationTimeout)); + Settings.MaxRetries, Settings.OperationTimeout)); return source.Task; } public EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, bool resolveLinkTos, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null, - int readBatchSize = 500) + int readBatchSize = 500, + string subscriptionName = "") { var settings = new CatchUpSubscriptionSettings(Consts.CatchUpDefaultMaxPushQueueSize, readBatchSize, - _settings.VerboseLogging, resolveLinkTos); + Settings.VerboseLogging, resolveLinkTos, subscriptionName); return SubscribeToAllFrom(lastCheckpoint, settings,eventAppeared, liveProcessingStarted, subscriptionDropped, userCredentials); } public EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null) @@ -341,17 +335,17 @@ public EventStoreAllCatchUpSubscription SubscribeToAllFrom( Ensure.NotNull(eventAppeared, "eventAppeared"); Ensure.NotNull(settings, "settings"); var catchUpSubscription = - new EventStoreAllCatchUpSubscription(this, _settings.Log, lastCheckpoint, + new EventStoreAllCatchUpSubscription(this, Settings.Log, lastCheckpoint, userCredentials, eventAppeared, liveProcessingStarted, subscriptionDropped, settings); - catchUpSubscription.Start(); + catchUpSubscription.StartAsync(); return catchUpSubscription; } public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( string stream, string groupName, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -362,8 +356,8 @@ public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( Ensure.NotNull(eventAppeared, "eventAppeared"); var subscription = new EventStorePersistentSubscription( - groupName, stream, eventAppeared, subscriptionDropped, userCredentials, _settings.Log, - _settings.VerboseLogging, _settings, _handler, bufferSize, autoAck); + groupName, stream, eventAppeared, subscriptionDropped, userCredentials, Settings.Log, + Settings.VerboseLogging, Settings, _handler, bufferSize, autoAck); subscription.Start().Wait(); return subscription; @@ -372,7 +366,7 @@ public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( public Task ConnectToPersistentSubscriptionAsync( string stream, string groupName, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -383,8 +377,8 @@ public Task ConnectToPersistentSubscriptio Ensure.NotNull(eventAppeared, "eventAppeared"); var subscription = new EventStorePersistentSubscription( - groupName, stream, eventAppeared, subscriptionDropped, userCredentials, _settings.Log, - _settings.VerboseLogging, _settings, _handler, bufferSize, autoAck); + groupName, stream, eventAppeared, subscriptionDropped, userCredentials, Settings.Log, + Settings.VerboseLogging, Settings, _handler, bufferSize, autoAck); return subscription.Start(); } @@ -409,22 +403,22 @@ public EventStorePersistentSubscription ConnectToPersistentSubscriptionForAll( */ - public Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials userCredentials = null) { + public Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); var source = new TaskCompletionSource(); - EnqueueOperation(new CreatePersistentSubscriptionOperation(_settings.Log, source, stream, groupName, settings, userCredentials)); + EnqueueOperation(new CreatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); return source.Task; } - public Task UpdatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials userCredentials = null) + public Task UpdatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); var source = new TaskCompletionSource(); - EnqueueOperation(new UpdatePersistentSubscriptionOperation(_settings.Log, source, stream, groupName, settings, userCredentials)); + EnqueueOperation(new UpdatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); return source.Task; } /* @@ -443,7 +437,7 @@ public Task DeletePersistentSubscriptionAsync(string stream, string groupName, U Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); var source = new TaskCompletionSource(); - EnqueueOperation(new DeletePersistentSubscriptionOperation(_settings.Log, source, stream, groupName, userCredentials)); + EnqueueOperation(new DeletePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, userCredentials)); return source.Task; } /* @@ -467,14 +461,14 @@ public Task SetStreamMetadataAsync(string stream, long expectedMeta { Ensure.NotNullOrEmpty(stream, "stream"); if (SystemStreams.IsMetastream(stream)) - throw new ArgumentException(string.Format("Setting metadata for metastream '{0}' is not supported.", stream), "stream"); + throw new ArgumentException(string.Format("Setting metadata for metastream '{0}' is not supported.", stream), nameof(stream)); var source = new TaskCompletionSource(); var metaevent = new EventData(Guid.NewGuid(), SystemEventTypes.StreamMetadata, true, metadata ?? Empty.ByteArray, null); - EnqueueOperation(new AppendToStreamOperation(_settings.Log, + EnqueueOperation(new AppendToStreamOperation(Settings.Log, source, - _settings.RequireMaster, + Settings.RequireMaster, SystemStreams.MetastreamOf(stream), expectedMetastreamVersion, new[] { metaevent }, diff --git a/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs b/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs index 4c1f6b4..51f52e4 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs @@ -99,7 +99,7 @@ internal class StartSubscriptionMessage : Message public readonly string StreamId; public readonly bool ResolveLinkTos; public readonly UserCredentials UserCredentials; - public readonly Action EventAppeared; + public readonly Func EventAppeared; public readonly Action SubscriptionDropped; public readonly int MaxRetries; @@ -109,7 +109,7 @@ public StartSubscriptionMessage(TaskCompletionSource sou string streamId, bool resolveLinkTos, UserCredentials userCredentials, - Action eventAppeared, + Func eventAppeared, Action subscriptionDropped, int maxRetries, TimeSpan timeout) @@ -136,13 +136,13 @@ internal class StartPersistentSubscriptionMessage : Message public readonly string StreamId; public readonly int BufferSize; public readonly UserCredentials UserCredentials; - public readonly Action EventAppeared; + public readonly Func EventAppeared; public readonly Action SubscriptionDropped; public readonly int MaxRetries; public readonly TimeSpan Timeout; - public StartPersistentSubscriptionMessage(TaskCompletionSource source, string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, Action eventAppeared, Action subscriptionDropped, int maxRetries, TimeSpan timeout) + public StartPersistentSubscriptionMessage(TaskCompletionSource source, string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, int maxRetries, TimeSpan timeout) { Ensure.NotNull(source, "source"); Ensure.NotNull(eventAppeared, "eventAppeared"); diff --git a/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs b/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs index 475c39b..fdf253f 100644 --- a/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs +++ b/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs @@ -86,7 +86,7 @@ public partial class EventRecord private EventRecord() { } - public EventRecord(string eventStreamId, int eventNumber, byte[] eventId, string eventType, int dataContentType, int metadataContentType, byte[] data, byte[] metadata, long? created, long? createdEpoch) + public EventRecord(string eventStreamId, long eventNumber, byte[] eventId, string eventType, int dataContentType, int metadataContentType, byte[] data, byte[] metadata, long? created, long? createdEpoch) { EventStreamId = eventStreamId; EventNumber = eventNumber; diff --git a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs index 7ddabbd..3079584 100644 --- a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs @@ -39,7 +39,7 @@ public static PersistentSubscriptionSettingsBuilder Create() /// /// Where the subscription should start from (position) /// - public readonly int StartFrom; + public readonly long StartFrom; /// /// Whether or not in depth latency statistics should be tracked on this subscription. @@ -72,7 +72,7 @@ public static PersistentSubscriptionSettingsBuilder Create() public int HistoryBufferSize; /// - /// The amount of time to try to checkpoint after + /// The amount of time to try to checkpoint after /// public readonly TimeSpan CheckPointAfter; @@ -99,7 +99,7 @@ public static PersistentSubscriptionSettingsBuilder Create() /// /// Constructs a new /// - internal PersistentSubscriptionSettings(bool resolveLinkTos, int startFrom, bool extraStatistics, TimeSpan messageTimeout, + internal PersistentSubscriptionSettings(bool resolveLinkTos, long startFrom, bool extraStatistics, TimeSpan messageTimeout, int maxRetryCount, int liveBufferSize, int readBatchSize, int historyBufferSize, TimeSpan checkPointAfter, int minCheckPointCount, int maxCheckPointCount, int maxSubscriberCount, string namedConsumerStrategy) diff --git a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettingsBuilder.cs index 728f4a0..8081b90 100644 --- a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettingsBuilder.cs @@ -10,7 +10,7 @@ namespace EventStore.ClientAPI public class PersistentSubscriptionSettingsBuilder { private bool _resolveLinkTos; - private int _startFrom; + private long _startFrom; private bool _timingStatistics; private TimeSpan _timeout; private int _readBatchSize; @@ -23,7 +23,7 @@ public class PersistentSubscriptionSettingsBuilder private int _maxSubscriberCount; private string _namedConsumerStrategies; - internal PersistentSubscriptionSettingsBuilder(bool resolveLinkTos, int startFrom, bool timingStatistics, TimeSpan timeout, + internal PersistentSubscriptionSettingsBuilder(bool resolveLinkTos, long startFrom, bool timingStatistics, TimeSpan timeout, int bufferSize, int liveBufferSize, int maxRetryCount, int readBatchSize, TimeSpan checkPointAfter, int minCheckPointCount, int maxCheckPointCount, int maxSubscriberCount, string namedConsumerStrategies) @@ -112,7 +112,7 @@ public PersistentSubscriptionSettingsBuilder StartFromBeginning() /// Sets that the subscription should start from a specified location of the stream. /// /// A new - public PersistentSubscriptionSettingsBuilder StartFrom(int position) + public PersistentSubscriptionSettingsBuilder StartFrom(long position) { _startFrom = position; return this; diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs index 90955a2..20039c6 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs @@ -53,7 +53,7 @@ public Task CreateTransient(IPEndPoint endPoint, string name, string query, User public Task CreateContinuous(IPEndPoint endPoint, string name, string query, bool trackEmitted, UserCredentials userCredentials = null) { return SendPost(endPoint.ToHttpUrl("/projections/continuous?name={0}&type=JS&emit=1&trackemittedstreams={1}", name, trackEmitted), - query, userCredentials, HttpStatusCode.Created); + query, userCredentials, HttpStatusCode.Created); } [Obsolete("Use 'Task> ListAll' instead")] diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs index 573d325..97da93e 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs @@ -290,8 +290,7 @@ public Task UpdateQueryAsync(string name, string query, UserCredentials userCred /// A task representing the operation. public Task DeleteAsync(string name, UserCredentials userCredentials = null) { - Ensure.NotNullOrEmpty(name, "name"); - return _client.Delete(_httpEndPoint, name, false, userCredentials); + return DeleteAsync(name, false, userCredentials); } /// diff --git a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs new file mode 100644 index 0000000..0e5797f --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs @@ -0,0 +1,83 @@ +using System; +using System.Net; +using System.Threading.Tasks; +using EventStore.ClientAPI.Common.Utils; +using EventStore.ClientAPI.Common.Utils.Threading; +using EventStore.ClientAPI.SystemData; +using Newtonsoft.Json.Linq; + +namespace EventStore.ClientAPI.Projections +{ + /// + /// API for executinmg queries in the Event Store through C# code. Communicates + /// with the Event Store over the RESTful API. + /// + public class QueryManager + { + private readonly TimeSpan _queryTimeout; + private readonly ProjectionsManager _projectionsManager; + + /// + /// Creates a new instance of . + /// + /// An instance of to use for logging. + /// HTTP endpoint of an Event Store server. + /// Timeout of projection API operations + /// Timeout of query execution + public QueryManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) + { + _queryTimeout = queryTimeout; + _projectionsManager = new ProjectionsManager(log, httpEndPoint, projectionOperationTimeout); + } + + /// + /// Asynchronously executes a query. + /// + /// + /// Creates a new transient projection and polls its status until it is Completed. + /// + /// A name for the query. + /// The JavaScript source code for the query. + /// Initial time to wait between polling for projection status. + /// Maximum time to wait between polling for projection status. + /// Credentials for a user with permission to create a query. + /// String of JSON containing query result. + public async Task ExecuteAsync(string name, string query, TimeSpan initialPollingDelay, TimeSpan maximumPollingDelay, UserCredentials userCredentials = null) + { + return await Task.Run(async () => + { + await _projectionsManager.CreateTransientAsync(name, query, userCredentials).ConfigureAwait(false); + await WaitForCompletedAsync(name, initialPollingDelay, maximumPollingDelay, userCredentials).ConfigureAwait(false); + return await _projectionsManager.GetStateAsync(name, userCredentials).ConfigureAwait(false); + }).WithTimeout(_queryTimeout).ConfigureAwait(false); + } + + private async Task WaitForCompletedAsync(string name, TimeSpan initialPollingDelay, TimeSpan maximumPollingDelay, UserCredentials userCredentials) + { + var attempts = 0; + var status = await GetStatusAsync(name, userCredentials).ConfigureAwait(false); + + while (!status.Contains("Completed")) + { + attempts++; + + await DelayPollingAsync(attempts, initialPollingDelay, maximumPollingDelay).ConfigureAwait(false); + status = await GetStatusAsync(name, userCredentials).ConfigureAwait(false); + } + } + + private static Task DelayPollingAsync(int attempts, TimeSpan initialPollingDelay, TimeSpan maximumPollingDelay) + { + var delayInMilliseconds = initialPollingDelay.TotalMilliseconds * (Math.Pow(2, attempts) - 1); + delayInMilliseconds = Math.Min(delayInMilliseconds, maximumPollingDelay.TotalMilliseconds); + + return Task.Delay(TimeSpan.FromMilliseconds(delayInMilliseconds)); + } + + private async Task GetStatusAsync(string name, UserCredentials userCredentials) + { + var projectionStatus = await _projectionsManager.GetStatusAsync(name, userCredentials).ConfigureAwait(false); + return projectionStatus.ParseJson()["status"].ToString(); + } + } +} From 8dfa9b03aaf02372f1353f423112349f142d83d3 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 14 Aug 2017 23:56:45 +0300 Subject: [PATCH 05/44] Updated tests for 4.0.2-rc and added new tests where possible --- .../Properties/AssemblyInfo.cs | 2 +- .../DefaultData.cs | 2 +- .../EventNumber.cs | 2 +- .../EventStore.ClientAPI.NetCore.Tests.csproj | 10 +- .../FakeEventStoreConnection.cs | 53 ++- .../Helpers/EventDataComparer.cs | 2 +- .../Helpers/EventsStream.cs | 2 +- .../Helpers/OngoingTransaction.cs | 2 +- .../Helpers/StreamWriter.cs | 2 +- .../Helpers/SystemStreams.cs | 2 +- .../Helpers/TailWriter.cs | 2 +- .../Helpers/TcpType.cs | 2 +- .../Helpers/TestConnection.cs | 3 +- .../Helpers/TestEvent.cs | 2 +- .../Helpers/TestNode.cs | 2 +- .../Helpers/TransactionalWriter.cs | 2 +- .../ProjectionSpecification.cs | 72 +++ .../Security/AuthenticationTestBase.cs | 5 +- .../all_stream_with_no_acl_security.cs | 2 +- ...authorized_default_credentials_security.cs | 2 +- .../Security/delete_stream_security.cs | 2 +- .../Security/multiple_role_security.cs | 2 +- .../overriden_system_stream_security.cs | 2 +- ...verriden_system_stream_security_for_all.cs | 5 +- .../overriden_user_stream_security.cs | 2 +- .../Security/read_all_security.cs | 2 +- .../Security/read_stream_meta_security.cs | 2 +- .../Security/read_stream_security.cs | 2 +- .../Security/stream_security_inheritance.cs | 2 +- .../Security/subscribe_to_all_security.cs | 2 +- .../Security/subscribe_to_stream_security.cs | 2 +- .../Security/system_stream_security.cs | 2 +- .../transactional_write_stream_security.cs | 2 +- .../Security/write_stream_meta_security.cs | 2 +- .../Security/write_stream_security.cs | 2 +- .../SpecificationWithConnection.cs | 4 +- .../SpecificationWithLinkToToDeletedEvents.cs | 2 +- ...cationWithLinkToToMaxCountDeletedEvents.cs | 2 +- .../SystemData/clientapi_tcp_package.cs | 2 +- .../SystemRoles.cs | 2 +- .../SystemUsers.cs | 2 +- .../UserManagement/TestWithNode.cs | 4 +- .../UserManagement/TestWithUser.cs | 2 +- .../UserManagement/change_password.cs | 2 +- .../UserManagement/creating_a_user.cs | 2 +- .../UserManagement/deleting_a_user.cs | 2 +- .../UserManagement/enable_disable_user.cs | 2 +- .../UserManagement/get_current_user.cs | 2 +- .../UserManagement/list_users.cs | 2 +- .../UserManagement/reset_password.cs | 2 +- .../UserManagement/updating_a_user.cs | 3 +- ..._in_autoack_mode_drops_the_subscription.cs | 5 +- .../append_to_stream.cs | 4 +- .../appending_to_implicitly_created_stream.cs | 4 +- ...icitly_created_stream_using_transaction.cs | 4 +- ...ription_group_name_on_different_streams.cs | 2 +- .../catch_up_subscription_handles_errors.cs | 11 +- ..._subscription_handles_small_batch_sizes.cs | 4 +- .../connect.cs | 4 +- ...istent_subscription_with_max_one_client.cs | 2 +- ..._subscription_with_max_one_client_async.cs | 2 +- ...ersistent_subscription_with_permissions.cs | 2 +- ...ent_subscription_with_permissions_async.cs | 2 +- ...h_start_from_beginning_and_events_in_it.cs | 6 +- ...t_from_beginning_and_events_in_it_async.cs | 6 +- ...with_start_from_beginning_and_no_stream.cs | 16 +- ...tart_from_beginning_and_no_stream_async.cs | 16 +- ...from_beginning_not_set_and_events_in_it.cs | 6 +- ...eginning_not_set_and_events_in_it_async.cs | 6 +- ...set_and_events_in_it_then_event_written.cs | 6 +- ...ption_with_start_from_two_and_no_stream.cs | 16 +- ...with_start_from_two_and_no_stream_async.cs | 16 +- ..._with_start_from_x_set_and_events_in_it.cs | 16 +- ...set_and_events_in_it_then_event_written.cs | 6 +- ...n_x_and_events_in_it_then_event_written.cs | 6 +- ...istent_subscription_without_permissions.cs | 2 +- ..._subscription_without_permissions_async.cs | 2 +- ...ersistent_subscription_with_permissions.cs | 9 +- ...ent_subscription_with_permissions_async.cs | 9 +- .../connection_string.cs | 2 +- ...duplicate_persistent_subscription_group.cs | 2 +- ...nt_subscription_after_deleting_the_same.cs | 2 +- ..._subscription_group_without_permissions.cs | 2 +- ...e_persistent_subscription_on_all_stream.cs | 24 + ...sistent_subscription_on_existing_stream.cs | 84 +--- ...ent_subscription_on_non_existing_stream.cs | 2 +- ...rsistent_subscription_with_dont_timeout.cs | 34 ++ ...scription_with_too_big_checkpoint_after.cs | 22 + ...bscription_with_too_big_message_timeout.cs | 2 +- ...t_subscription_with_too_big_retry_after.cs | 2 +- ...ent_subscription_group_with_permissions.cs | 2 +- ...persistent_subscription_with_subscriber.cs | 2 +- ...nt_subscription_group_that_doesnt_exist.cs | 2 +- ..._subscription_group_without_permissions.cs | 2 +- .../deleting_stream.cs | 4 +- .../event_store_connection_should.cs | 4 +- ..._catching_up_to_link_to_events_auto_ack.cs | 2 +- ...atching_up_to_link_to_events_manual_ack.cs | 2 +- ...e_catching_up_to_normal_events_auto_ack.cs | 2 +- ...catching_up_to_normal_events_manual_ack.cs | 2 +- ...d_subscribing_to_normal_events_auto_ack.cs | 2 +- ...subscribing_to_normal_events_manual_ack.cs | 2 +- .../not_connected_tests.cs | 4 +- .../projectionsManager.cs | 449 ------------------ .../read_all_events_backward_should.cs | 4 +- .../read_all_events_forward_should.cs | 4 +- ...forward_with_hard_deleted_stream_should.cs | 4 +- ...ts_forward_with_linkto_passed_max_count.cs | 2 +- ...ts_forward_with_linkto_to_deleted_event.cs | 2 +- ...forward_with_soft_deleted_stream_should.cs | 4 +- ...ents_backward_with_linkto_deleted_event.cs | 2 +- .../read_event_of_linkto_to_deleted_event.cs | 2 +- .../read_event_should.cs | 2 +- .../read_event_stream_backward_should.cs | 4 +- .../read_event_stream_forward_should.cs | 4 +- ...ad_stream_events_with_unresolved_linkto.cs | 4 +- .../soft_delete.cs | 4 +- .../ssl_append_to_stream.cs | 4 +- .../subscribe_should.cs | 4 +- .../subscribe_to_all_catching_up_should.cs | 4 +- .../subscribe_to_all_should.cs | 4 +- .../subscribe_to_stream_catching_up_should.cs | 4 +- .../transaction.cs | 4 +- ...update_existing_persistent_subscription.cs | 2 +- ...ersistent_subscription_with_subscribers.cs | 2 +- ...istent_subscription_without_permissions.cs | 2 +- ...te_non_existing_persistent_subscription.cs | 2 +- .../when_a_projection_is_running.cs | 57 +++ .../when_committing_empty_transaction.cs | 4 +- .../when_connecting_with_connection_string.cs | 4 +- .../when_creating_continuous_projection.cs | 56 +++ ...s_projection_with_track_emitted_streams.cs | 54 +++ .../when_creating_one_time_projection.cs | 34 ++ .../when_creating_transient_projection.cs | 36 ++ .../when_disabling_projections.cs | 41 ++ .../when_enabling_projections.cs | 42 ++ .../when_having_max_count_set_for_stream.cs | 4 +- ...en_having_truncatebefore_set_for_stream.cs | 4 +- .../when_listing_all_projections.cs | 29 ++ .../when_listing_continuous_projections.cs | 33 ++ .../when_listing_one_time_projections.cs | 30 ++ .../when_updating_a_projection_query.cs | 39 ++ .../when_working_with_metadata.cs | 6 +- ...king_with_stream_metadata_as_byte_array.cs | 4 +- ...with_stream_metadata_as_structured_info.cs | 4 +- ...ubscribing_to_normal_events_manual_nack.cs | 65 +++ 146 files changed, 951 insertions(+), 761 deletions(-) create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/ProjectionSpecification.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_all_stream.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_dont_timeout.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_checkpoint_after.cs delete mode 100644 test/EventStore.ClientAPI.NetCore.Tests/projectionsManager.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_a_projection_is_running.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection_with_track_emitted_streams.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_creating_one_time_projection.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_creating_transient_projection.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_disabling_projections.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_enabling_projections.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_listing_all_projections.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_listing_continuous_projections.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_listing_one_time_projections.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_updating_a_projection_query.cs create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/when_writing_and_subscribing_to_normal_events_manual_nack.cs diff --git a/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs b/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs index c935cc0..a4048b2 100644 --- a/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs +++ b/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs @@ -16,4 +16,4 @@ [assembly: ComVisible(false)] [assembly: Guid("0bffd734-18c5-4575-9321-324ed1a3bbfb")] -[assembly: InternalsVisibleTo("EventStore.ClientAPI.NetCore.Tests")] \ No newline at end of file +[assembly: InternalsVisibleTo("EventStore.Core.Tests.ClientAPI")] \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/DefaultData.cs b/test/EventStore.ClientAPI.NetCore.Tests/DefaultData.cs index d869a7d..26a180a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/DefaultData.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/DefaultData.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using EventStore.ClientAPI.SystemData; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public class DefaultData { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/EventNumber.cs b/test/EventStore.ClientAPI.NetCore.Tests/EventNumber.cs index 6f1639f..f630f21 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/EventNumber.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/EventNumber.cs @@ -1,4 +1,4 @@ -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public static class EventNumber { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj index 603c405..3f24bf7 100755 --- a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj +++ b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj @@ -1,11 +1,19 @@  + + Library + + netcoreapp1.1 - EventStore.ClientAPI.NetCore.Tests + EventStore.Core.Tests.ClientAPI EventStore.ClientAPI.NetCore.Tests true $(PackageTargetFallback);portable-net45+win8 + + library + + EventStore.Core.Tests.ClientAPI diff --git a/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs b/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs index c369cd6..d3cc962 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs @@ -4,20 +4,20 @@ using EventStore.ClientAPI; using EventStore.ClientAPI.SystemData; -namespace Eventstore.ClientAPI.Tests -{ - internal class FakeEventStoreConnection : IEventStoreConnection +namespace EventStore.Core.Tests.ClientAPI +{ +internal class FakeEventStoreConnection : IEventStoreConnection { - private Func> _readAllEventsForwardAsync; - private Func> _readStreamEventsForwardAsync; - private Func, Action, Task> _subscribeToStreamAsync; + private Func> _readAllEventsForwardAsync; + private Func> _readStreamEventsForwardAsync; + private Func, Action, Task> _subscribeToStreamAsync; public void Dispose() { throw new NotImplementedException(); } - public string ConnectionName { get; private set; } + public string ConnectionName { get; } public ConnectionSettings Settings { get { return null; } } public Task ConnectAsync() @@ -55,6 +55,12 @@ public Task AppendToStreamAsync(string stream, long expectedVersion throw new NotImplementedException(); } + public Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, + UserCredentials userCredentials = null) + { + throw new NotImplementedException(); + } + public Task StartTransactionAsync(string stream, long expectedVersion, UserCredentials userCredentials = null) { throw new NotImplementedException(); @@ -70,7 +76,7 @@ public Task ReadEventAsync(string stream, long eventNumber, boo throw new NotImplementedException(); } - public void HandleReadStreamEventsForwardAsync(Func> callback) + public void HandleReadStreamEventsForwardAsync(Func> callback) { _readStreamEventsForwardAsync = callback; } @@ -87,7 +93,7 @@ public Task ReadStreamEventsBackwardAsync(string stream, long throw new NotImplementedException(); } - public void HandleReadAllEventsForwardAsync(Func> callback) + public void HandleReadAllEventsForwardAsync(Func> callback) { _readAllEventsForwardAsync = callback; } @@ -104,20 +110,20 @@ public Task ReadAllEventsBackwardAsync(Position position, int ma throw new NotImplementedException(); } - public void HandleSubscribeToStreamAsync(Func, Action, Task> callback) + public void HandleSubscribeToStreamAsync(Func, Action, Task> callback) { _subscribeToStreamAsync = callback; } - public Task SubscribeToStreamAsync(string stream, bool resolveLinkTos, Action eventAppeared, Action subscriptionDropped = null, + public Task SubscribeToStreamAsync(string stream, bool resolveLinkTos, Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null) { return _subscribeToStreamAsync(stream, eventAppeared, subscriptionDropped); } public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom(string stream, long? lastCheckpoint, bool resolveLinkTos, - Action eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, - UserCredentials userCredentials = null, int readBatchSize = 500) + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, + UserCredentials userCredentials = null, int readBatchSize = 500, string subscriptionName = "") { throw new NotImplementedException(); } @@ -126,7 +132,7 @@ public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( string stream, long? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null) @@ -134,22 +140,24 @@ public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( throw new NotImplementedException(); } - public Task SubscribeToAllAsync(bool resolveLinkTos, Action eventAppeared, Action subscriptionDropped = null, + public Task SubscribeToAllAsync(bool resolveLinkTos, Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null) { throw new NotImplementedException(); } public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription(string stream, string groupName, - Action eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) { throw new NotImplementedException(); } - public EventStoreAllCatchUpSubscription SubscribeToAllFrom(Position? lastCheckpoint, bool resolveLinkTos, Action eventAppeared, + public EventStoreAllCatchUpSubscription SubscribeToAllFrom(Position? lastCheckpoint, bool resolveLinkTos, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null, - int readBatchSize = 500) + int readBatchSize = 500, + string subscriptionName = "") { throw new NotImplementedException(); } @@ -157,7 +165,7 @@ public EventStoreAllCatchUpSubscription SubscribeToAllFrom(Position? lastCheckpo public EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, CatchUpSubscriptionSettings settings, - Action eventAppeared, + Func eventAppeared, Action liveProcessingStarted = null, Action subscriptionDropped = null, UserCredentials userCredentials = null) @@ -252,12 +260,7 @@ public void OnConnected(ClientConnectionEventArgs e) if (handler != null) handler(this, e); } - public Task ConnectToPersistentSubscriptionAsync(string stream, string groupName, Action eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) - { - throw new NotImplementedException(); - } - - public Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null) + public Task ConnectToPersistentSubscriptionAsync(string stream, string groupName, Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) { throw new NotImplementedException(); } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventDataComparer.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventDataComparer.cs index d04094a..9201eff 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventDataComparer.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventDataComparer.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal static class EventDataComparer { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventsStream.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventsStream.cs index 6f227a7..b3f1339 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventsStream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/EventsStream.cs @@ -1,6 +1,6 @@ using EventStore.ClientAPI; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal class EventsStream { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/OngoingTransaction.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/OngoingTransaction.cs index 8f01ac8..097bc18 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/OngoingTransaction.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/OngoingTransaction.cs @@ -1,6 +1,6 @@ using EventStore.ClientAPI; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal class OngoingTransaction { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/StreamWriter.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/StreamWriter.cs index f9cad76..87a1a48 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/StreamWriter.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/StreamWriter.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal class StreamWriter { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/SystemStreams.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/SystemStreams.cs index 5986e3b..5d25671 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/SystemStreams.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/SystemStreams.cs @@ -1,4 +1,4 @@ -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { public static class SystemStreams { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TailWriter.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TailWriter.cs index 0ba1235..40243ba 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TailWriter.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TailWriter.cs @@ -1,6 +1,6 @@ using EventStore.ClientAPI; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal class TailWriter { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TcpType.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TcpType.cs index 765ea74..2533170 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TcpType.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TcpType.cs @@ -1,4 +1,4 @@ -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { public enum TcpType { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestConnection.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestConnection.cs index f618ae5..0318e57 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestConnection.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestConnection.cs @@ -4,12 +4,11 @@ using System.Text; using System.Threading; using EventStore.ClientAPI; -using EventStore.ClientAPI.Common.Log; using EventStore.ClientAPI.Internal; using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { public static class TestConnection { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestEvent.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestEvent.cs index c38fdc4..65e5493 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestEvent.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestEvent.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { public class TestEvent { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestNode.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestNode.cs index 57c2679..33b54b4 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestNode.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TestNode.cs @@ -5,7 +5,7 @@ using EventStore.ClientAPI.SystemData; using Microsoft.Extensions.Configuration; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { public static class TestNode { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TransactionalWriter.cs b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TransactionalWriter.cs index f7655ed..6bfd39a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TransactionalWriter.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Helpers/TransactionalWriter.cs @@ -1,6 +1,6 @@ using EventStore.ClientAPI; -namespace Eventstore.ClientAPI.Tests.Helpers +namespace EventStore.Core.Tests.ClientAPI.Helpers { internal class TransactionalWriter { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/ProjectionSpecification.cs b/test/EventStore.ClientAPI.NetCore.Tests/ProjectionSpecification.cs new file mode 100644 index 0000000..735c54c --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/ProjectionSpecification.cs @@ -0,0 +1,72 @@ +using System; +using System.Text; +using EventStore.ClientAPI; +using EventStore.ClientAPI.Common.Log; +using EventStore.ClientAPI.Projections; +using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; + +namespace EventStore.Core.Tests.ClientAPI +{ + public abstract class ProjectionSpecification + { + protected readonly ProjectionsManager _projManager; + protected readonly IEventStoreConnection _connection; + protected readonly UserCredentials _credentials; + protected ProjectionSpecification() + { + _credentials = TestNode.AdminCredentials; + _connection = TestConnection.Create(TcpType.Normal, _credentials); + _connection.ConnectAsync().Wait(); + _projManager = new ProjectionsManager(new ConsoleLogger(), TestNode.HttpEndPoint, TimeSpan.FromSeconds(20)); + Given(); + When(); + } + + public virtual void Given() { } + public virtual void When() { } + + protected EventData CreateEvent(string eventType, string data) + { + return new EventData(Guid.NewGuid(), eventType, true, Encoding.UTF8.GetBytes(data), null); + } + + protected void PostEvent(string stream, string eventType, string data) + { + _connection.AppendToStreamAsync(stream, ExpectedVersion.Any, new[] { CreateEvent(eventType, data) }).Wait(); + } + + protected void CreateOneTimeProjection() + { + var query = CreateStandardQuery(Guid.NewGuid().ToString()); + _projManager.CreateOneTimeAsync(query, _credentials).Wait(); + } + + protected void CreateContinuousProjection(string projectionName) + { + var query = CreateStandardQuery(Guid.NewGuid().ToString()); + _projManager.CreateContinuousAsync(projectionName, query, _credentials).Wait(); + } + + protected string CreateStandardQuery(string stream) + { + return @"fromStream(""" + stream + @""") + .when({ + ""$any"":function(s,e) { + s.count = 1; + return s; + } + });"; + } + + protected string CreateEmittingQuery(string stream, string emittingStream) + { + return @"fromStream(""" + stream + @""") + .when({ + ""$any"":function(s,e) { + emit(""" + emittingStream + @""", ""emittedEvent"", e); + } + });"; + } + } +} diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/AuthenticationTestBase.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/AuthenticationTestBase.cs index d126d61..bed4e79 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/AuthenticationTestBase.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/AuthenticationTestBase.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Log; using EventStore.ClientAPI.SystemData; using EventStore.ClientAPI.UserManagement; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { public abstract class AuthenticationTestBase { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/all_stream_with_no_acl_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/all_stream_with_no_acl_security.cs index fc3108c..3d9e5c9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/all_stream_with_no_acl_security.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class all_stream_with_no_acl_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/authorized_default_credentials_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/authorized_default_credentials_security.cs index e53faa0..1608cbe 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/authorized_default_credentials_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/authorized_default_credentials_security.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class authorized_default_credentials_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/delete_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/delete_stream_security.cs index f958803..6656993 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/delete_stream_security.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class delete_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/multiple_role_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/multiple_role_security.cs index 236a5d6..a7ea99a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/multiple_role_security.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class multiple_role_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security.cs index efd8119..1b313de 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class overriden_system_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security_for_all.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security_for_all.cs index a04e872..bf74b64 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_system_stream_security_for_all.cs @@ -1,9 +1,8 @@ -using Eventstore.ClientAPI.Tests.Helpers; -using EventStore.ClientAPI; +using EventStore.ClientAPI; using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class overriden_system_stream_security_for_all : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_user_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_user_stream_security.cs index 1086443..120355d 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/overriden_user_stream_security.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class overriden_user_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_all_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_all_security.cs index 8f1968a..a00689f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_all_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_all_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class read_all_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_meta_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_meta_security.cs index f30449f..4ccc995 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_meta_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class read_stream_meta_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_security.cs index f4c0d5d..8662924 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/read_stream_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class read_stream_security: AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/stream_security_inheritance.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/stream_security_inheritance.cs index f05922d..aacaa40 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/stream_security_inheritance.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class stream_security_inheritance: AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_all_security.cs index 2e8c0ea..0b8cb26 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_all_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class subscribe_to_all_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_stream_security.cs index c99eed9..9e208e2 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/subscribe_to_stream_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class subscribe_to_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/system_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/system_stream_security.cs index 137ec12..b625fb9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/system_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/system_stream_security.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class system_stream_security: AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/transactional_write_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/transactional_write_stream_security.cs index 74c4599..6db3b5d 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/transactional_write_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/transactional_write_stream_security.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class transactional_write_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_meta_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_meta_security.cs index ce31bd9..6160343 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_meta_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class write_stream_meta_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_security.cs b/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_security.cs index 0196479..69fc260 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_security.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/Security/write_stream_security.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.Security +namespace EventStore.Core.Tests.ClientAPI.Security { [TestFixture, Category("LongRunning"), Category("Network")] public class write_stream_security : AuthenticationTestBase diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithConnection.cs b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithConnection.cs index 3a6046a..8a6de06 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithConnection.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithConnection.cs @@ -1,9 +1,9 @@ using System.Net; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public abstract class SpecificationWithConnection { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToDeletedEvents.cs b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToDeletedEvents.cs index 57a0750..062e749 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToDeletedEvents.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToDeletedEvents.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using EventStore.ClientAPI.Common; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public abstract class SpecificationWithLinkToToDeletedEvents : SpecificationWithConnection { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToMaxCountDeletedEvents.cs b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToMaxCountDeletedEvents.cs index 9c584f4..5373409 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToMaxCountDeletedEvents.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SpecificationWithLinkToToMaxCountDeletedEvents.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using EventStore.ClientAPI.Common; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public abstract class SpecificationWithLinkToToMaxCountDeletedEvents : SpecificationWithConnection { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SystemData/clientapi_tcp_package.cs b/test/EventStore.ClientAPI.NetCore.Tests/SystemData/clientapi_tcp_package.cs index 9b54e2a..95a1fe5 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SystemData/clientapi_tcp_package.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SystemData/clientapi_tcp_package.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.SystemData +namespace EventStore.Core.Tests.ClientAPI.SystemData { [TestFixture] public class clientapi_tcp_package diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SystemRoles.cs b/test/EventStore.ClientAPI.NetCore.Tests/SystemRoles.cs index 385b9fe..3b005b5 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SystemRoles.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SystemRoles.cs @@ -1,4 +1,4 @@ -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public static class SystemRoles { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/SystemUsers.cs b/test/EventStore.ClientAPI.NetCore.Tests/SystemUsers.cs index 58d94fa..672b58d 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/SystemUsers.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/SystemUsers.cs @@ -1,4 +1,4 @@ -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public static class SystemUsers { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithNode.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithNode.cs index e70ab4b..f28bd70 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithNode.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithNode.cs @@ -1,11 +1,11 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Log; using EventStore.ClientAPI.UserManagement; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { [Category("LongRunning")] public class TestWithNode diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithUser.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithUser.cs index 9e0d132..c5a96cb 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithUser.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/TestWithUser.cs @@ -1,7 +1,7 @@ using System; using EventStore.ClientAPI.SystemData; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class TestWithUser : TestWithNode { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/change_password.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/change_password.cs index 4a92d7b..eb3b65a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/change_password.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/change_password.cs @@ -4,7 +4,7 @@ using EventStore.ClientAPI.Transport.Http; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class change_password : TestWithUser { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/creating_a_user.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/creating_a_user.cs index a49d86e..61120bf 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/creating_a_user.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/creating_a_user.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.UserManagement; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class creating_a_user : TestWithNode { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/deleting_a_user.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/deleting_a_user.cs index c5a19d9..6c08995 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/deleting_a_user.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/deleting_a_user.cs @@ -4,7 +4,7 @@ using EventStore.ClientAPI.Transport.Http; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { [TestFixture] public class deleting_a_user : TestWithNode diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/enable_disable_user.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/enable_disable_user.cs index 522ddc0..d7da49f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/enable_disable_user.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/enable_disable_user.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class enable_disable_user : TestWithUser { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/get_current_user.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/get_current_user.cs index 4386b0a..338cd28 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/get_current_user.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/get_current_user.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class get_current_user : TestWithNode { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/list_users.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/list_users.cs index 76b9805..6fa585f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/list_users.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/list_users.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI.SystemData; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class list_users: TestWithNode { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/reset_password.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/reset_password.cs index a11b610..579c91c 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/reset_password.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/reset_password.cs @@ -4,7 +4,7 @@ using EventStore.ClientAPI.Transport.Http; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { public class reset_password : TestWithUser { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/updating_a_user.cs b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/updating_a_user.cs index be027cb..49a679a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/updating_a_user.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/UserManagement/updating_a_user.cs @@ -1,9 +1,8 @@ using System; using EventStore.ClientAPI.SystemData; -using EventStore.ClientAPI.UserManagement; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests.UserManagement +namespace EventStore.Core.Tests.ClientAPI.UserManagement { [TestFixture] public class updating_a_user : TestWithNode diff --git a/test/EventStore.ClientAPI.NetCore.Tests/a_nak_in_subscription_handler_in_autoack_mode_drops_the_subscription.cs b/test/EventStore.ClientAPI.NetCore.Tests/a_nak_in_subscription_handler_in_autoack_mode_drops_the_subscription.cs index 9a74a39..e671e68 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/a_nak_in_subscription_handler_in_autoack_mode_drops_the_subscription.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/a_nak_in_subscription_handler_in_autoack_mode_drops_the_subscription.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class a_nak_in_subscription_handler_in_autoack_mode_drops_the_subscription : SpecificationWithConnection @@ -48,7 +49,7 @@ protected override void When() } - private static void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private static Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { throw new Exception("test"); } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/append_to_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/append_to_stream.cs index bb2005c..7b29c01 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/append_to_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/append_to_stream.cs @@ -1,11 +1,11 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture] public class append_to_stream diff --git a/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream.cs index efe8419..fc6f384 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream.cs @@ -1,11 +1,11 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class appending_to_implicitly_created_stream diff --git a/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream_using_transaction.cs b/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream_using_transaction.cs index 9996b43..d75e274 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream_using_transaction.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/appending_to_implicitly_created_stream_using_transaction.cs @@ -1,11 +1,11 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class appending_to_implicitly_created_stream_using_transaction diff --git a/test/EventStore.ClientAPI.NetCore.Tests/can_create_duplicate_persistent_subscription_group_name_on_different_streams.cs b/test/EventStore.ClientAPI.NetCore.Tests/can_create_duplicate_persistent_subscription_group_name_on_different_streams.cs index b05895f..6b21b7f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/can_create_duplicate_persistent_subscription_group_name_on_different_streams.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/can_create_duplicate_persistent_subscription_group_name_on_different_streams.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class can_create_duplicate_persistent_subscription_group_name_on_different_streams : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs b/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs index c1b0127..0865967 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs @@ -12,7 +12,7 @@ using ClientMessage = EventStore.ClientAPI.Messages.ClientMessage; using ResolvedEvent = EventStore.ClientAPI.ResolvedEvent; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture] public class catch_up_subscription_handles_errors @@ -47,6 +47,7 @@ public void SetUp() { _raisedEvents.Add(ev); _raisedEventEvent.Set(); + return Task.CompletedTask; }, subscription => { @@ -81,7 +82,7 @@ public void read_events_til_stops_subscription_when_throws_immediately() private void AssertStartFailsAndDropsSubscriptionWithException(Exception expectedException) { - Assert.That(() => _subscription.Start().Wait(TimeoutMs), Throws.TypeOf()); + Assert.That(() => _subscription.StartAsync().Wait(TimeoutMs), Throws.TypeOf()); Assert.That(_isDropped); Assert.That(_dropReason, Is.EqualTo(SubscriptionDropReason.CatchUpError)); Assert.That(_dropException, Is.SameAs(expectedException)); @@ -312,7 +313,7 @@ public void start_completes_onces_subscription_is_live() return taskCompletionSource.Task; }); - var task = _subscription.Start(); + var task = _subscription.StartAsync(); Assert.That(task.Status, Is.Not.EqualTo(TaskStatus.RanToCompletion)); @@ -353,7 +354,7 @@ public void when_live_processing_and_disconnected_reconnect_keeps_events_ordered return taskCompletionSource.Task; }); - Assert.That(_subscription.Start().Wait(TimeoutMs)); + Assert.That(_subscription.StartAsync().Wait(TimeoutMs)); Assert.That(_raisedEvents.Count, Is.EqualTo(0)); Assert.That(innerSubscriptionDrop, Is.Not.Null); @@ -414,7 +415,7 @@ public void when_live_processing_and_disconnected_reconnect_keeps_events_ordered Assert.That(reconnectTask.Wait(TimeoutMs)); } - private static VolatileEventStoreSubscription CreateVolatileSubscription(Action raise, Action drop, int? lastEventNumber) + private static VolatileEventStoreSubscription CreateVolatileSubscription(Func raise, Action drop, int? lastEventNumber) { return new VolatileEventStoreSubscription(new VolatileSubscriptionOperation(new NoopLogger(), new TaskCompletionSource(), StreamId, false, null, raise, drop, false, () => null), StreamId, -1, lastEventNumber); } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/catchup_subscription_handles_small_batch_sizes.cs b/test/EventStore.ClientAPI.NetCore.Tests/catchup_subscription_handles_small_batch_sizes.cs index c08dfd5..92e5dbc 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/catchup_subscription_handles_small_batch_sizes.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/catchup_subscription_handles_small_batch_sizes.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Text; using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Ignore("Very long running")] [Category("LongRunning")] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect.cs index eb29870..614bb08 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect.cs @@ -1,11 +1,11 @@ using System; using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Internal; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture(TcpType.Normal), TestFixture(TcpType.Ssl), Category("LongRunning")] public class connect diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client.cs index b8cc977..b9350ab 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.ClientOperations; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_max_one_client : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client_async.cs index 1a633ca..5b4f37a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_max_one_client_async.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.ClientOperations; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_max_one_client_async : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions.cs index 4a64df3..e9295c6 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions_async.cs index 97f1f0f..6e95831 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_permissions_async.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_permissions_async : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it.cs index 43ea009..93746b7 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it : SpecificationWithConnection @@ -50,7 +51,7 @@ protected override void When() DefaultData.AdminCredentials); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { if (!_set) { @@ -58,6 +59,7 @@ private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent _firstEvent = resolvedEvent; _resetEvent.Set(); } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs index 7836e4a..2a83625 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async : SpecificationWithConnection @@ -50,7 +51,7 @@ protected override void When() DefaultData.AdminCredentials).Wait(); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { if (!_set) { @@ -58,6 +59,7 @@ private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent _firstEvent = resolvedEvent; _resetEvent.Set(); } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs index b86cbfd..2449bb4 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream : SpecificationWithConnection @@ -40,12 +41,15 @@ protected override void When() new EventData(_id, "test", true, Encoding.UTF8.GetBytes("{'foo' : 'bar'}"), new byte[0])).Wait(); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) return; - _set = true; - _firstEvent = resolvedEvent; - _resetEvent.Set(); + if (!_set) + { + _set = true; + _firstEvent = resolvedEvent; + _resetEvent.Set(); + } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs index 492f9b8..2bd2c45 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async : SpecificationWithConnection @@ -40,12 +41,15 @@ protected override void When() new EventData(_id, "test", true, Encoding.UTF8.GetBytes("{'foo' : 'bar'}"), new byte[0])).Wait(); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) return; - _set = true; - _firstEvent = resolvedEvent; - _resetEvent.Set(); + if (_set) + { + _set = true; + _firstEvent = resolvedEvent; + _resetEvent.Set(); + } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it.cs index bb35236..b3452a6 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it : SpecificationWithConnection @@ -44,9 +45,10 @@ protected override void When() DefaultData.AdminCredentials); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { _resetEvent.Set(); + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_async.cs index 4f46243..f703abf 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_async.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_async : SpecificationWithConnection @@ -45,9 +46,10 @@ protected override void When() DefaultData.AdminCredentials).Wait(); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { _resetEvent.Set(); + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_then_event_written.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_then_event_written.cs index 376d2d9..3a5517a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_then_event_written.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_then_event_written.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_beginning_not_set_and_events_in_it_then_event_written : SpecificationWithConnection @@ -50,10 +51,11 @@ protected override void When() } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { _firstEvent = resolvedEvent; _resetEvent.Set(); + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream.cs index 6244ad6..f5930c2 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream : SpecificationWithConnection @@ -45,12 +46,15 @@ protected override void When() } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) return; - _set = true; - _firstEvent = resolvedEvent; - _resetEvent.Set(); + if (!_set) + { + _set = true; + _firstEvent = resolvedEvent; + _resetEvent.Set(); + } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream_async.cs index d703f58..ee64144 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream_async.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_two_and_no_stream_async : SpecificationWithConnection @@ -44,12 +45,15 @@ protected override void When() new EventData(_id, "test", true, Encoding.UTF8.GetBytes("{'foo' : 'bar'}"), new byte[0])).Wait(); } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) return; - _set = true; - _firstEvent = resolvedEvent; - _resetEvent.Set(); + if (!_set) + { + _set = true; + _firstEvent = resolvedEvent; + _resetEvent.Set(); + } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it.cs index b6ab615..82d0540 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it : SpecificationWithConnection @@ -54,12 +55,15 @@ protected override void When() } private bool _set = false; - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) return; - _set = true; - _firstEvent = resolvedEvent; - _resetEvent.Set(); + if (!_set) + { + _set = true; + _firstEvent = resolvedEvent; + _resetEvent.Set(); + } + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it_then_event_written.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it_then_event_written.cs index 5cf5878..b8f18ea 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it_then_event_written.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it_then_event_written.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_x_set_and_events_in_it_then_event_written : SpecificationWithConnection @@ -52,10 +53,11 @@ protected override void When() } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { _firstEvent = resolvedEvent; _resetEvent.Set(); + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs index c2a6bab..daa40f6 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; +using System.Threading.Tasks; using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written : SpecificationWithConnection @@ -52,10 +53,11 @@ protected override void When() } - private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { _firstEvent = resolvedEvent; _resetEvent.Set(); + return Task.CompletedTask; } [Test] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions.cs index b8b8cb5..6c1fea8 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_without_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions_async.cs index c428a48..7efae36 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_without_permissions_async.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_existing_persistent_subscription_without_permissions_async : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs index 6b1c236..9ee7a1b 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs @@ -1,7 +1,8 @@ using System; +using System.Threading.Tasks; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_non_existing_persistent_subscription_with_permissions : SpecificationWithConnection @@ -15,7 +16,11 @@ protected override void When() _conn.ConnectToPersistentSubscription( "nonexisting2", "foo", - (sub, e) => Console.Write("appeared"), + (sub, e) => + { + Console.Write("appeared"); + return Task.CompletedTask; + }, (sub, reason, ex) => { }); diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs index 87fa138..c7d8c20 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs @@ -1,7 +1,8 @@ using System; +using System.Threading.Tasks; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class connect_to_non_existing_persistent_subscription_with_permissions_async : SpecificationWithConnection @@ -15,7 +16,11 @@ protected override void When() _conn.ConnectToPersistentSubscriptionAsync( "nonexisting2", "foo", - (sub, e) => Console.Write("appeared"), + (sub, e) => + { + Console.Write("appeared"); + return Task.CompletedTask; + }, (sub, reason, ex) => { }).Wait(); diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connection_string.cs b/test/EventStore.ClientAPI.NetCore.Tests/connection_string.cs index 8fa5398..55ddb49 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connection_string.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connection_string.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture] public class connection_string diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_duplicate_persistent_subscription_group.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_duplicate_persistent_subscription_group.cs index 8b77f82..a733dd5 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_duplicate_persistent_subscription_group.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_duplicate_persistent_subscription_group.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_duplicate_persistent_subscription_group : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_after_deleting_the_same.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_after_deleting_the_same.cs index f8806ef..65a9cdc 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_after_deleting_the_same.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_after_deleting_the_same.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_after_deleting_the_same : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_group_without_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_group_without_permissions.cs index 7739719..4f6954e 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_group_without_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_group_without_permissions.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_group_without_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_all_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_all_stream.cs new file mode 100644 index 0000000..6fe9cb1 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_all_stream.cs @@ -0,0 +1,24 @@ +using System; +using EventStore.ClientAPI; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture, Category("LongRunning")] + public class create_persistent_subscription_on_all_stream : SpecificationWithConnection + { + private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettings.Create() + .DoNotResolveLinkTos() + .StartFromCurrent(); + protected override void When() + { + + } + + [Test] + public void the_completion_fails_with_invalid_stream() + { + Assert.Throws(() => _conn.CreatePersistentSubscriptionAsync("$all", "shitbird", _settings, DefaultData.AdminCredentials).Wait()); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_existing_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_existing_stream.cs index c9817bc..7db28e9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_existing_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_existing_stream.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_on_existing_stream : SpecificationWithConnection @@ -29,86 +29,4 @@ public void the_completion_succeeds() .Wait()); } } - - - //ALL -/* - - [TestFixture, Category("LongRunning")] - public class create_persistent_subscription_on_all : SpecificationWithConnection - { - private PersistentSubscriptionCreateResult _result; - private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettingsBuilder.Create() - .DoNotResolveLinkTos() - .StartFromCurrent(); - - protected override void When() - { - _result = _conn.CreatePersistentSubscriptionForAllAsync("group", _settings, DefaultData.AdminCredentials).Result; - } - - [Test] - public void the_completion_succeeds() - { - Assert.AreEqual(PersistentSubscriptionCreateStatus.Success, _result.Status); - } - } - - - [TestFixture, Category("LongRunning")] - public class create_duplicate_persistent_subscription_group_on_all : SpecificationWithConnection - { - private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettingsBuilder.Create() - .DoNotResolveLinkTos() - .StartFromCurrent(); - protected override void When() - { - _conn.CreatePersistentSubscriptionForAllAsync("group32", _settings, DefaultData.AdminCredentials).Wait(); - } - - [Test] - public void the_completion_fails_with_invalid_operation_exception() - { - try - { - _conn.CreatePersistentSubscriptionForAllAsync("group32", _settings, DefaultData.AdminCredentials).Wait(); - throw new Exception("expected exception"); - } - catch (Exception ex) - { - Assert.IsInstanceOf(typeof(AggregateException), ex); - var inner = ex.InnerException; - Assert.IsInstanceOf(typeof(InvalidOperationException), inner); - } - } - } - - [TestFixture, Category("LongRunning")] - public class create_persistent_subscription_group_on_all_without_permissions : SpecificationWithConnection - { - private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettingsBuilder.Create() - .DoNotResolveLinkTos() - .StartFromCurrent(); - protected override void When() - { - } - - [Test] - public void the_completion_succeeds() - { - try - { - _conn.CreatePersistentSubscriptionForAllAsync("group57", _settings, null).Wait(); - throw new Exception("expected exception"); - } - catch (Exception ex) - { - Assert.IsInstanceOf(typeof(AggregateException), ex); - var inner = ex.InnerException; - Assert.IsInstanceOf(typeof(AccessDeniedException), inner); - } - } - } -*/ - } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_non_existing_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_non_existing_stream.cs index c4dfa29..4c8d23f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_non_existing_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_on_non_existing_stream.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_on_non_existing_stream : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_dont_timeout.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_dont_timeout.cs new file mode 100644 index 0000000..dd00dc3 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_dont_timeout.cs @@ -0,0 +1,34 @@ +using System; +using EventStore.ClientAPI; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture, Category("LongRunning")] + public class create_persistent_subscription_with_dont_timeout : SpecificationWithConnection + { + private readonly string _stream = Guid.NewGuid().ToString(); + private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettings.Create() + .DoNotResolveLinkTos() + .StartFromCurrent() + .DontTimeoutMessages(); + protected override void When() + { + } + + [Test] + public void the_message_timeout_should_be_zero() + { + Assert.That(_settings.MessageTimeout == TimeSpan.Zero); + } + + [Test] + public void the_subscription_is_created_without_error() + { + Assert.DoesNotThrow( + () => + _conn.CreatePersistentSubscriptionAsync(_stream, "dont-timeout", _settings, DefaultData.AdminCredentials).Wait() + ); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_checkpoint_after.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_checkpoint_after.cs new file mode 100644 index 0000000..17dc525 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_checkpoint_after.cs @@ -0,0 +1,22 @@ +using System; +using EventStore.ClientAPI; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture, Category("LongRunning")] + public class create_persistent_subscription_with_too_big_checkpoint_after : SpecificationWithConnection + { + + protected override void When() + { + + } + + [Test] + public void the_build_fails_with_argument_exception() + { + Assert.Throws(() => PersistentSubscriptionSettings.Create().CheckPointAfter(TimeSpan.FromDays(25 * 365)).Build()); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_message_timeout.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_message_timeout.cs index 1484f14..0d0b661 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_message_timeout.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_message_timeout.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_with_too_big_message_timeout : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_retry_after.cs b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_retry_after.cs index e20642d..66cd110 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_retry_after.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/create_persistent_subscription_with_too_big_retry_after.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class create_persistent_subscription_with_too_big_retry_after : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_group_with_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_group_with_permissions.cs index 9e4d78b..fc5d887 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_group_with_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_group_with_permissions.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class deleting_existing_persistent_subscription_group_with_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_with_subscriber.cs b/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_with_subscriber.cs index b2e6414..84d5fdc 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_with_subscriber.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/deleting_existing_persistent_subscription_with_subscriber.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class deleting_existing_persistent_subscription_with_subscriber : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_that_doesnt_exist.cs b/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_that_doesnt_exist.cs index cc43897..9a85358 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_that_doesnt_exist.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_that_doesnt_exist.cs @@ -1,7 +1,7 @@ using System; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class deleting_persistent_subscription_group_that_doesnt_exist : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_without_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_without_permissions.cs index 6944418..b6482fd 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_without_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/deleting_persistent_subscription_group_without_permissions.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class deleting_persistent_subscription_group_without_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/deleting_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/deleting_stream.cs index 8591b6d..fd8338f 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/deleting_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/deleting_stream.cs @@ -1,10 +1,10 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class deleting_stream diff --git a/test/EventStore.ClientAPI.NetCore.Tests/event_store_connection_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/event_store_connection_should.cs index f78146d..a5e9c90 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/event_store_connection_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/event_store_connection_should.cs @@ -1,9 +1,9 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture(TcpType.Normal), TestFixture(TcpType.Ssl), Category("LongRunning")] public class event_store_connection_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_auto_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_auto_ack.cs index 9f176fa..ba0becd 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_auto_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_auto_ack.cs @@ -5,7 +5,7 @@ using EventStore.ClientAPI.Common; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_catching_up_to_link_to_events_auto_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_manual_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_manual_ack.cs index a05ff36..90be95c 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_manual_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_link_to_events_manual_ack.cs @@ -5,7 +5,7 @@ using EventStore.ClientAPI.Common; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_catching_up_to_link_to_events_manual_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_auto_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_auto_ack.cs index 552aad8..a7413c9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_auto_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_auto_ack.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_catching_up_to_normal_events_auto_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_manual_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_manual_ack.cs index 3c01b28..294d496 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_manual_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_catching_up_to_normal_events_manual_ack.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_catching_up_to_normal_events_manual_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_auto_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_auto_ack.cs index c8b23ab..004cf0a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_auto_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_auto_ack.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_writing_and_subscribing_to_normal_events_auto_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs index 808c8ac..d2ee561 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class happy_case_writing_and_subscribing_to_normal_events_manual_ack : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/not_connected_tests.cs b/test/EventStore.ClientAPI.NetCore.Tests/not_connected_tests.cs index a7c4835..c9c2d82 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/not_connected_tests.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/not_connected_tests.cs @@ -1,12 +1,12 @@ using System; using System.Net; using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Internal; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class not_connected_tests diff --git a/test/EventStore.ClientAPI.NetCore.Tests/projectionsManager.cs b/test/EventStore.ClientAPI.NetCore.Tests/projectionsManager.cs deleted file mode 100644 index c089805..0000000 --- a/test/EventStore.ClientAPI.NetCore.Tests/projectionsManager.cs +++ /dev/null @@ -1,449 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Eventstore.ClientAPI.Tests.Helpers; -using EventStore.ClientAPI; -using EventStore.ClientAPI.Common.Log; -using EventStore.ClientAPI.Common.Utils; -using EventStore.ClientAPI.Projections; -using EventStore.ClientAPI.SystemData; -using Newtonsoft.Json.Linq; -using NUnit.Framework; - -namespace Eventstore.ClientAPI.Tests.projectionsManager -{ - public abstract class ProjectionSpecification - { - protected readonly ProjectionsManager _projManager; - protected readonly IEventStoreConnection _connection; - protected readonly UserCredentials _credentials; - protected ProjectionSpecification() - { - _credentials = TestNode.AdminCredentials; - _connection = TestConnection.Create(TcpType.Normal, _credentials); - _connection.ConnectAsync().Wait(); - _projManager = new ProjectionsManager(new ConsoleLogger(), TestNode.HttpEndPoint, TimeSpan.FromSeconds(20)); - Given(); - When(); - } - - public virtual void Given() { } - public virtual void When() { } - - protected EventData CreateEvent(string eventType, string data) - { - return new EventData(Guid.NewGuid(), eventType, true, Encoding.UTF8.GetBytes(data), null); - } - - protected void PostEvent(string stream, string eventType, string data) - { - _connection.AppendToStreamAsync(stream, ExpectedVersion.Any, new[] { CreateEvent(eventType, data) }).Wait(); - } - - protected void CreateOneTimeProjection() - { - var query = CreateStandardQuery(Guid.NewGuid().ToString()); - _projManager.CreateOneTimeAsync(query, _credentials).Wait(); - } - - protected void CreateContinuousProjection(string projectionName) - { - var query = CreateStandardQuery(Guid.NewGuid().ToString()); - _projManager.CreateContinuousAsync(projectionName, query, _credentials).Wait(); - } - - protected string CreateStandardQuery(string stream) - { - return @"fromStream(""" + stream + @""") - .when({ - ""$any"":function(s,e) { - s.count = 1; - return s; - } - });"; - } - - protected string CreateEmittingQuery(string stream, string emittingStream) - { - return @"fromStream(""" + stream + @""") - .when({ - ""$any"":function(s,e) { - emit(""" + emittingStream + @""", ""emittedEvent"", e); - } - });"; - } - } - [TestFixture] - [Category("ProjectionsManager")] - public class when_creating_one_time_projection : ProjectionSpecification - { - private string _streamName; - private string _query; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - _query = CreateStandardQuery(_streamName); - } - - public override void When() - { - _projManager.CreateOneTimeAsync(_query, _credentials).Wait(); - } - - [Test] - public void should_create_projection() - { - var projections = _projManager.ListOneTimeAsync(_credentials).Result; - Assert.AreEqual(1, projections.Count); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_creating_transient_projection : ProjectionSpecification - { - private string _streamName; - private string _projectionName; - private string _query; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - _projectionName = "when_creating_transient_projection"; - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - _query = CreateStandardQuery(_streamName); - } - - public override void When() - { - _projManager.CreateTransientAsync(_projectionName, _query, _credentials).Wait(); - } - - [Test] - public void should_create_projection() - { - var status = _projManager.GetStatusAsync(_projectionName, _credentials).Result; - Assert.IsNotEmpty(status); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_creating_continuous_projection : ProjectionSpecification - { - private string _streamName; - private string _emittedStreamName; - private string _projectionName; - private string _query; - private string _projectionId; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid(); - _projectionName = "when_creating_continuous_projection"; - _emittedStreamName = "emittedStream-" + Guid.NewGuid(); - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - _query = CreateEmittingQuery(_streamName, _emittedStreamName); - } - - public override void When() - { - _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); - } - - [Test] - public void should_create_projection() - { - var allProjections = _projManager.ListContinuousAsync(_credentials).Result; - var proj = allProjections.FirstOrDefault(x => x.EffectiveName == _projectionName); - _projectionId = proj.Name; - Assert.IsNotNull(proj); - } - - [Test] - public void should_have_turn_on_emit_to_stream() - { - var events = _connection.ReadEventAsync(string.Format("$projections-{0}", _projectionId), 0, true, _credentials).Result; - var data = Encoding.UTF8.GetString(events.Event.Value.Event.Data); - var eventData = data.ParseJson(); - Assert.IsTrue((bool)eventData["emitEnabled"]); - } - - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_creating_continuous_projection_with_track_emitted_streams : ProjectionSpecification - { - private string _streamName; - private string _emittedStreamName; - private string _projectionName; - private string _query; - private string _projectionId; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid(); - _projectionName = "when_creating_continuous_projection_with_track_emitted_streams"; - _emittedStreamName = "emittedStream-" + Guid.NewGuid(); - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - - _query = CreateEmittingQuery(_streamName, _emittedStreamName); - } - - public override void When() - { - _projManager.CreateContinuousAsync(_projectionName, _query, true, _credentials).Wait(); - } - - [Test] - public void should_create_projection() - { - var allProjections = _projManager.ListContinuousAsync(_credentials).Result; - var proj = allProjections.FirstOrDefault(x => x.EffectiveName == _projectionName); - _projectionId = proj.Name; - Assert.IsNotNull(proj); - } - - [Test] - public void should_enable_track_emitted_streams() - { - var events = _connection.ReadEventAsync(string.Format("$projections-{0}", _projectionId), 0, true, _credentials).Result; - var data = Encoding.UTF8.GetString(events.Event.Value.Event.Data); - var eventData = data.ParseJson(); - Assert.IsTrue((bool)eventData["trackEmittedStreams"]); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_disabling_projections : ProjectionSpecification - { - private string _streamName; - private string _projectionName; - private string _query; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - _projectionName = "when_disabling_projection"; - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - _query = CreateStandardQuery(_streamName); - - _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); - } - - public override void When() - { - _projManager.DisableAsync(_projectionName, _credentials).Wait(); - } - - [Test] - public void should_stop_the_projection() - { - var projectionStatus = _projManager.GetStatusAsync(_projectionName, _credentials).Result; - var status = projectionStatus.ParseJson()["status"].ToString(); - Assert.IsTrue(status.Contains("Stopped"), "Status did not contain 'Stopped' : {0}", status); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_enabling_projections : ProjectionSpecification - { - private string _streamName; - private string _projectionName; - private string _query; - - public override void Given() - { - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - _projectionName = "when_enabling_projections"; - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - _query = CreateStandardQuery(_streamName); - - _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); - _projManager.DisableAsync(_projectionName, _credentials).Wait(); - } - - public override void When() - { - _projManager.EnableAsync(_projectionName, _credentials).Wait(); - } - - [Test] - public void should_reenable_projection() - { - var projectionStatus = _projManager.GetStatusAsync(_projectionName, _credentials).Result; - var status = projectionStatus.ParseJson()["status"].ToString(); - Assert.IsTrue(status.Contains("Running"), "Status did not contain 'Running' : {0}", status); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_listing_all_projections : ProjectionSpecification - { - private List _result; - public override void Given() - { - } - - public override void When() - { - _result = _projManager.ListAllAsync(_credentials).Result.ToList(); - } - - [Test] - public void should_return_all_projections() - { - Assert.IsNotEmpty(_result); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_listing_one_time_projections : ProjectionSpecification - { - private List _result; - public override void Given() - { - CreateOneTimeProjection(); - } - - public override void When() - { - _result = _projManager.ListOneTimeAsync(_credentials).Result.ToList(); - } - - [Test] - public void should_return_projections() - { - Assert.IsNotEmpty(_result); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_listing_continuous_projections : ProjectionSpecification - { - private List _result; - private string _projectionName; - - public override void Given() - { - _projectionName = Guid.NewGuid().ToString(); - CreateContinuousProjection(_projectionName); - } - - public override void When() - { - _result = _projManager.ListContinuousAsync(_credentials).Result.ToList(); - } - - [Test] - public void should_return_continuous_projections() - { - Assert.IsTrue(_result.Any(x => x.EffectiveName == _projectionName)); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_a_projection_is_running : ProjectionSpecification - { - private string _projectionName; - private string _streamName; - private string _query; - - public override void Given() - { - _projectionName = "when_getting_projection_information"; - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - } - - public override void When() - { - _query = CreateStandardQuery(_streamName); - _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); - } - - [Test] - public void should_be_able_to_get_the_projection_state() - { - var state = _projManager.GetStateAsync(_projectionName, _credentials).Result; - Assert.IsNotEmpty(state); - } - - [Test] - public void should_be_able_to_get_the_projection_status() - { - var status = _projManager.GetStatusAsync(_projectionName, _credentials).Result; - Assert.IsNotEmpty(status); - } - - [Test] - public void should_be_able_to_get_the_projection_result() - { - var result = _projManager.GetResultAsync(_projectionName, _credentials).Result; - Assert.AreEqual("{\"count\":1}", result); - } - - [Test] - public void should_be_able_to_get_the_projection_query() - { - var query = _projManager.GetQueryAsync(_projectionName, _credentials).Result; - Assert.AreEqual(_query, query); - } - } - - [TestFixture] - [Category("ProjectionsManager")] - public class when_updating_a_projection_query : ProjectionSpecification - { - private string _projectionName; - private string _streamName; - private string _newQuery; - - public override void Given() - { - _projectionName = "when_updating_a_projection_query"; - _streamName = "test-stream-" + Guid.NewGuid().ToString(); - - PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); - PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); - - var origQuery = CreateStandardQuery(_streamName); - _newQuery = CreateStandardQuery("DifferentStream"); - _projManager.CreateContinuousAsync(_projectionName, origQuery, _credentials).Wait(); - } - - public override void When() - { - _projManager.UpdateQueryAsync(_projectionName, _newQuery, _credentials).Wait(); - } - - [Test] - public void should_update_the_projection_query() - { - var query = _projManager.GetQueryAsync(_projectionName, _credentials).Result; - Assert.AreEqual(_newQuery, query); - } - } -} diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs index fd899d7..aa2d157 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_all_events_backward_should : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs index 830dddc..3b2242a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_all_events_forward_should : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_hard_deleted_stream_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_hard_deleted_stream_should.cs index fc6f3ab..1c700b0 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_hard_deleted_stream_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_hard_deleted_stream_should.cs @@ -1,13 +1,13 @@ using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; using StreamMetadata = EventStore.ClientAPI.StreamMetadata; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning"), Ignore("Uses $all")] public class read_all_events_forward_with_hard_deleted_stream_should : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_passed_max_count.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_passed_max_count.cs index bdc2438..7d7f64a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_passed_max_count.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_passed_max_count.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture] public class read_all_events_forward_with_linkto_passed_max_count : SpecificationWithLinkToToMaxCountDeletedEvents diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_to_deleted_event.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_to_deleted_event.cs index 9b4a79d..0649e9d 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_to_deleted_event.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_linkto_to_deleted_event.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_all_events_forward_with_linkto_to_deleted_event : SpecificationWithLinkToToDeletedEvents diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_soft_deleted_stream_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_soft_deleted_stream_should.cs index c50d45c..6e5ac75 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_soft_deleted_stream_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_with_soft_deleted_stream_should.cs @@ -1,13 +1,13 @@ using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; using StreamMetadata = EventStore.ClientAPI.StreamMetadata; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_all_events_forward_with_soft_deleted_stream_should : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_allevents_backward_with_linkto_deleted_event.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_allevents_backward_with_linkto_deleted_event.cs index cd3316f..f15b89b 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_allevents_backward_with_linkto_deleted_event.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_allevents_backward_with_linkto_deleted_event.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_allevents_backward_with_linkto_deleted_event : SpecificationWithLinkToToDeletedEvents diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_of_linkto_to_deleted_event.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_of_linkto_to_deleted_event.cs index 6f68a52..f8373fa 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_of_linkto_to_deleted_event.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_of_linkto_to_deleted_event.cs @@ -1,7 +1,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_event_of_linkto_to_deleted_event : SpecificationWithLinkToToDeletedEvents diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs index f9a19ad..c5f9e3e 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_event_should : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs index 1560cd8..f474770 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs @@ -1,10 +1,10 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_event_stream_backward_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs index 0eeee50..d77bb41 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs @@ -1,11 +1,11 @@ using System; using System.Globalization; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_event_stream_forward_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_stream_events_with_unresolved_linkto.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_stream_events_with_unresolved_linkto.cs index 7c5746e..e11cf19 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_stream_events_with_unresolved_linkto.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_stream_events_with_unresolved_linkto.cs @@ -1,14 +1,14 @@ using System; using System.Linq; using System.Text; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; using StreamMetadata = EventStore.ClientAPI.StreamMetadata; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class read_stream_events_with_unresolved_linkto : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/soft_delete.cs b/test/EventStore.ClientAPI.NetCore.Tests/soft_delete.cs index 7078290..2c7aaf6 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/soft_delete.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/soft_delete.cs @@ -1,11 +1,11 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class soft_delete diff --git a/test/EventStore.ClientAPI.NetCore.Tests/ssl_append_to_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/ssl_append_to_stream.cs index ab0addf..645fda1 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/ssl_append_to_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/ssl_append_to_stream.cs @@ -1,11 +1,11 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Ignore("TODO: Setup SSL")] public class ssl_append_to_stream diff --git a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_should.cs index 9847d72..7db0e74 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_should.cs @@ -1,9 +1,9 @@ using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class subscribe_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_catching_up_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_catching_up_should.cs index 605980a..264db6a 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_catching_up_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_catching_up_should.cs @@ -3,13 +3,13 @@ using System.Diagnostics; using System.Linq; using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Log; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using Newtonsoft.Json.Linq; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class subscribe_to_all_catching_up_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_should.cs index b2fe2d5..9d48adc 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_all_should.cs @@ -1,10 +1,10 @@ using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.SystemData; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class subscribe_to_all_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_stream_catching_up_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_stream_catching_up_should.cs index 9470751..5408daf 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_stream_catching_up_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/subscribe_to_stream_catching_up_should.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Log; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class subscribe_to_stream_catching_up_should diff --git a/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs b/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs index 640f350..0b31aff 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class transaction diff --git a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription.cs b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription.cs index 4b465d7..36b9494 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription.cs @@ -3,7 +3,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class update_existing_persistent_subscription : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_with_subscribers.cs b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_with_subscribers.cs index 62138cf..5533dda 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_with_subscribers.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_with_subscribers.cs @@ -4,7 +4,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class update_existing_persistent_subscription_with_subscribers : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_without_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_without_permissions.cs index 36c9648..2f0fa69 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_without_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/update_existing_persistent_subscription_without_permissions.cs @@ -4,7 +4,7 @@ using EventStore.ClientAPI.Exceptions; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class update_existing_persistent_subscription_without_permissions : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/update_non_existing_persistent_subscription.cs b/test/EventStore.ClientAPI.NetCore.Tests/update_non_existing_persistent_subscription.cs index 1ed6ecb..e47b2d5 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/update_non_existing_persistent_subscription.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/update_non_existing_persistent_subscription.cs @@ -2,7 +2,7 @@ using EventStore.ClientAPI; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class update_non_existing_persistent_subscription : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_a_projection_is_running.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_a_projection_is_running.cs new file mode 100644 index 0000000..1aabd2b --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_a_projection_is_running.cs @@ -0,0 +1,57 @@ +using System; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_a_projection_is_running : ProjectionSpecification + { + private string _projectionName; + private string _streamName; + private string _query; + + public override void Given() + { + _projectionName = "when_getting_projection_information"; + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + } + + public override void When() + { + _query = CreateStandardQuery(_streamName); + _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); + } + + [Test] + public void should_be_able_to_get_the_projection_state() + { + var state = _projManager.GetStateAsync(_projectionName, _credentials).Result; + Assert.IsNotEmpty((string) state); + } + + [Test] + public void should_be_able_to_get_the_projection_status() + { + var status = _projManager.GetStatusAsync(_projectionName, _credentials).Result; + Assert.IsNotEmpty((string) status); + } + + [Test] + public void should_be_able_to_get_the_projection_result() + { + var result = _projManager.GetResultAsync(_projectionName, _credentials).Result; + Assert.AreEqual("{\"count\":1}", result); + } + + [Test] + public void should_be_able_to_get_the_projection_query() + { + var query = _projManager.GetQueryAsync(_projectionName, _credentials).Result; + Assert.AreEqual(_query, query); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_committing_empty_transaction.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_committing_empty_transaction.cs index 9d44897..8b07a63 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_committing_empty_transaction.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_committing_empty_transaction.cs @@ -1,10 +1,10 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_committing_empty_transaction diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_connecting_with_connection_string.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_connecting_with_connection_string.cs index 62a32d7..1e72493 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_connecting_with_connection_string.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_connecting_with_connection_string.cs @@ -1,10 +1,10 @@ using System; using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { public class when_connecting_with_connection_string { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection.cs new file mode 100644 index 0000000..b113b67 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection.cs @@ -0,0 +1,56 @@ +using System; +using System.Linq; +using System.Text; +using EventStore.ClientAPI.Projections; +using Newtonsoft.Json.Linq; +using NUnit.Framework; +using EventStore.ClientAPI.Common.Utils; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_creating_continuous_projection : ProjectionSpecification + { + private string _streamName; + private string _emittedStreamName; + private string _projectionName; + private string _query; + private string _projectionId; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid(); + _projectionName = "when_creating_continuous_projection"; + _emittedStreamName = "emittedStream-" + Guid.NewGuid(); + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + _query = CreateEmittingQuery(_streamName, _emittedStreamName); + } + + public override void When() + { + _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); + } + + [Test] + public void should_create_projection() + { + var allProjections = _projManager.ListContinuousAsync(_credentials).Result; + var proj = Enumerable.FirstOrDefault(allProjections, x => x.EffectiveName == _projectionName); + _projectionId = proj.Name; + Assert.IsNotNull(proj); + } + + [Test] + public void should_have_turn_on_emit_to_stream() + { + var events = _connection.ReadEventAsync(string.Format((string) "$projections-{0}", (object) _projectionId), 0, true, _credentials).Result; + var data = Encoding.UTF8.GetString(events.Event.Value.Event.Data); + var eventData = data.ParseJson(); + Assert.IsTrue((bool)eventData["emitEnabled"]); + } + + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection_with_track_emitted_streams.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection_with_track_emitted_streams.cs new file mode 100644 index 0000000..562a6d1 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_continuous_projection_with_track_emitted_streams.cs @@ -0,0 +1,54 @@ +using System; +using System.Linq; +using System.Text; +using EventStore.ClientAPI.Common.Utils; +using EventStore.ClientAPI.Projections; +using Newtonsoft.Json.Linq; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_creating_continuous_projection_with_track_emitted_streams : ProjectionSpecification + { + private string _streamName; + private string _emittedStreamName; + private string _projectionName; + private string _query; + private string _projectionId; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid(); + _projectionName = "when_creating_continuous_projection_with_track_emitted_streams"; + _emittedStreamName = "emittedStream-" + Guid.NewGuid(); + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + + _query = CreateEmittingQuery(_streamName, _emittedStreamName); + } + + public override void When() + { + _projManager.CreateContinuousAsync(_projectionName, _query, true, _credentials).Wait(); + } + + [Test] + public void should_create_projection() + { + var allProjections = _projManager.ListContinuousAsync(_credentials).Result; + var proj = Enumerable.FirstOrDefault(allProjections, x => x.EffectiveName == _projectionName); + _projectionId = proj.Name; + Assert.IsNotNull(proj); + } + + [Test] + public void should_enable_track_emitted_streams() + { + var events = _connection.ReadEventAsync(string.Format((string) "$projections-{0}", (object) _projectionId), 0, true, _credentials).Result; + var data = Encoding.UTF8.GetString(events.Event.Value.Event.Data); + var eventData = data.ParseJson(); + Assert.IsTrue((bool)eventData["trackEmittedStreams"]); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_creating_one_time_projection.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_one_time_projection.cs new file mode 100644 index 0000000..508133d --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_one_time_projection.cs @@ -0,0 +1,34 @@ +using System; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_creating_one_time_projection : ProjectionSpecification + { + private string _streamName; + private string _query; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + _query = CreateStandardQuery(_streamName); + } + + public override void When() + { + _projManager.CreateOneTimeAsync(_query, _credentials).Wait(); + } + + [Test] + public void should_create_projection() + { + var projections = _projManager.ListOneTimeAsync(_credentials).Result; + Assert.AreEqual(1, projections.Count); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_creating_transient_projection.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_transient_projection.cs new file mode 100644 index 0000000..81eb5c7 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_creating_transient_projection.cs @@ -0,0 +1,36 @@ +using System; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_creating_transient_projection : ProjectionSpecification + { + private string _streamName; + private string _projectionName; + private string _query; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + _projectionName = "when_creating_transient_projection"; + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + _query = CreateStandardQuery(_streamName); + } + + public override void When() + { + _projManager.CreateTransientAsync(_projectionName, _query, _credentials).Wait(); + } + + [Test] + public void should_create_projection() + { + var status = _projManager.GetStatusAsync(_projectionName, _credentials).Result; + Assert.IsNotEmpty((string) status); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_disabling_projections.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_disabling_projections.cs new file mode 100644 index 0000000..8097b3b --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_disabling_projections.cs @@ -0,0 +1,41 @@ +using System; +using EventStore.ClientAPI.Common.Utils; +using Newtonsoft.Json.Linq; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_disabling_projections : ProjectionSpecification + { + private string _streamName; + private string _projectionName; + private string _query; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + _projectionName = "when_disabling_projection"; + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + _query = CreateStandardQuery(_streamName); + + _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); + } + + public override void When() + { + _projManager.DisableAsync(_projectionName, _credentials).Wait(); + } + + [Test] + public void should_stop_the_projection() + { + var projectionStatus = _projManager.GetStatusAsync(_projectionName, _credentials).Result; + var status = projectionStatus.ParseJson()["status"].ToString(); + Assert.IsTrue(status.Contains("Stopped"), "Status did not contain 'Stopped' : {0}", status); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_enabling_projections.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_enabling_projections.cs new file mode 100644 index 0000000..ddcaa05 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_enabling_projections.cs @@ -0,0 +1,42 @@ +using System; +using Newtonsoft.Json.Linq; +using NUnit.Framework; +using EventStore.ClientAPI.Common.Utils; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_enabling_projections : ProjectionSpecification + { + private string _streamName; + private string _projectionName; + private string _query; + + public override void Given() + { + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + _projectionName = "when_enabling_projections"; + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + _query = CreateStandardQuery(_streamName); + + _projManager.CreateContinuousAsync(_projectionName, _query, _credentials).Wait(); + _projManager.DisableAsync(_projectionName, _credentials).Wait(); + } + + public override void When() + { + _projManager.EnableAsync(_projectionName, _credentials).Wait(); + } + + [Test] + public void should_reenable_projection() + { + var projectionStatus = _projManager.GetStatusAsync(_projectionName, _credentials).Result; + var status = projectionStatus.ParseJson()["status"].ToString(); + Assert.IsTrue(status.Contains("Running"), "Status did not contain 'Running' : {0}", status); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_having_max_count_set_for_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_having_max_count_set_for_stream.cs index 1c29200..9f5932e 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_having_max_count_set_for_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_having_max_count_set_for_stream.cs @@ -1,9 +1,9 @@ using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_having_max_count_set_for_stream diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_having_truncatebefore_set_for_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_having_truncatebefore_set_for_stream.cs index 4d0787d..51c9fd4 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_having_truncatebefore_set_for_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_having_truncatebefore_set_for_stream.cs @@ -1,9 +1,9 @@ using System.Linq; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_having_truncatebefore_set_for_stream : SpecificationWithConnection diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_listing_all_projections.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_all_projections.cs new file mode 100644 index 0000000..35cdac0 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_all_projections.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using EventStore.ClientAPI.Projections; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_listing_all_projections : ProjectionSpecification + { + private List _result; + public override void Given() + { + } + + public override void When() + { + _result = Enumerable.ToList(_projManager.ListAllAsync(_credentials).Result); + } + + [Test] + public void should_return_all_projections() + { + Assert.IsNotEmpty((IEnumerable) _result); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_listing_continuous_projections.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_continuous_projections.cs new file mode 100644 index 0000000..dc457fb --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_continuous_projections.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using EventStore.ClientAPI.Projections; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_listing_continuous_projections : ProjectionSpecification + { + private List _result; + private string _projectionName; + + public override void Given() + { + _projectionName = Guid.NewGuid().ToString(); + CreateContinuousProjection(_projectionName); + } + + public override void When() + { + _result = Enumerable.ToList(_projManager.ListContinuousAsync(_credentials).Result); + } + + [Test] + public void should_return_continuous_projections() + { + Assert.IsTrue(Enumerable.Any(_result, x => x.EffectiveName == _projectionName)); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_listing_one_time_projections.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_one_time_projections.cs new file mode 100644 index 0000000..6456a30 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_listing_one_time_projections.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using EventStore.ClientAPI.Projections; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_listing_one_time_projections : ProjectionSpecification + { + private List _result; + public override void Given() + { + CreateOneTimeProjection(); + } + + public override void When() + { + _result = Enumerable.ToList(_projManager.ListOneTimeAsync(_credentials).Result); + } + + [Test] + public void should_return_projections() + { + Assert.IsNotEmpty((IEnumerable) _result); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_updating_a_projection_query.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_updating_a_projection_query.cs new file mode 100644 index 0000000..37f4ef5 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_updating_a_projection_query.cs @@ -0,0 +1,39 @@ +using System; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture] + [Category("ProjectionsManager")] + public class when_updating_a_projection_query : ProjectionSpecification + { + private string _projectionName; + private string _streamName; + private string _newQuery; + + public override void Given() + { + _projectionName = "when_updating_a_projection_query"; + _streamName = "test-stream-" + Guid.NewGuid().ToString(); + + PostEvent(_streamName, "testEvent", "{\"A\":\"1\"}"); + PostEvent(_streamName, "testEvent", "{\"A\":\"2\"}"); + + var origQuery = CreateStandardQuery(_streamName); + _newQuery = CreateStandardQuery("DifferentStream"); + _projManager.CreateContinuousAsync(_projectionName, origQuery, _credentials).Wait(); + } + + public override void When() + { + _projManager.UpdateQueryAsync(_projectionName, _newQuery, _credentials).Wait(); + } + + [Test] + public void should_update_the_projection_query() + { + var query = _projManager.GetQueryAsync(_projectionName, _credentials).Result; + Assert.AreEqual(_newQuery, query); + } + } +} \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_metadata.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_metadata.cs index 21f818b..60c5b49 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_metadata.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_metadata.cs @@ -1,10 +1,10 @@ -using Eventstore.ClientAPI.Tests.Helpers; -using EventStore.ClientAPI; +using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_working_with_metadata diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_byte_array.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_byte_array.cs index 1e623bd..a3ab839 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_byte_array.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_byte_array.cs @@ -1,11 +1,11 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_working_with_stream_metadata_as_byte_array diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_structured_info.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_structured_info.cs index b3e0c72..d966bf2 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_structured_info.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_working_with_stream_metadata_as_structured_info.cs @@ -1,13 +1,13 @@ using System; -using Eventstore.ClientAPI.Tests.Helpers; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Exceptions; +using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; using ExpectedVersion = EventStore.ClientAPI.ExpectedVersion; using StreamMetadata = EventStore.ClientAPI.StreamMetadata; -namespace Eventstore.ClientAPI.Tests +namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] public class when_working_with_stream_metadata_as_structured_info diff --git a/test/EventStore.ClientAPI.NetCore.Tests/when_writing_and_subscribing_to_normal_events_manual_nack.cs b/test/EventStore.ClientAPI.NetCore.Tests/when_writing_and_subscribing_to_normal_events_manual_nack.cs new file mode 100644 index 0000000..fac7a52 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/when_writing_and_subscribing_to_normal_events_manual_nack.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using EventStore.ClientAPI; +using NUnit.Framework; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture, Category("ClientAPI"), Category("LongRunning")] + public class when_writing_and_subscribing_to_normal_events_manual_nack : SpecificationWithConnection + { + private readonly string StreamName = Guid.NewGuid().ToString(); + private readonly string GroupName = Guid.NewGuid().ToString(); + private const int BufferCount = 10; + private const int EventWriteCount = BufferCount * 2; + + private readonly ManualResetEvent _eventsReceived = new ManualResetEvent(false); + private int _eventReceivedCount; + + protected override void When() + { + + } + + + [Test] + public void Test() + { + var settings = PersistentSubscriptionSettings + .Create() + .StartFromCurrent() + .ResolveLinkTos() + .Build(); + + _conn.CreatePersistentSubscriptionAsync(StreamName, GroupName, settings, DefaultData.AdminCredentials) + .Wait(); + _conn.ConnectToPersistentSubscription(StreamName, GroupName, + (subscription, resolvedEvent) => + { + subscription.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Park, "fail"); + + if (Interlocked.Increment(ref _eventReceivedCount) == EventWriteCount) + { + _eventsReceived.Set(); + } + return Task.CompletedTask; + }, + (sub, reason, exception) => + Console.WriteLine("Subscription dropped (reason:{0}, exception:{1}).", reason, exception), + bufferSize: 10, autoAck: false, userCredentials: DefaultData.AdminCredentials); + + for (var i = 0; i < EventWriteCount; i++) + { + var eventData = new EventData(Guid.NewGuid(), "SomeEvent", false, new byte[0], new byte[0]); + + _conn.AppendToStreamAsync(StreamName, ExpectedVersion.Any, DefaultData.AdminCredentials, eventData); + } + + if (!_eventsReceived.WaitOne(TimeSpan.FromSeconds(5))) + { + throw new Exception("Timed out waiting for events."); + } + } + } +} \ No newline at end of file From c1c0dd004e99d70bd5c6507a528cd2ca6c785543 Mon Sep 17 00:00:00 2001 From: James Geall Date: Tue, 15 Aug 2017 00:14:40 +0300 Subject: [PATCH 06/44] Fixed duplicate group names --- ...cription_with_start_from_beginning_and_events_in_it_async.cs | 2 +- ...tent_subscription_with_start_from_beginning_and_no_stream.cs | 2 +- ...ubscription_with_start_from_beginning_and_no_stream_async.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs index 2a83625..00c9cf3 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_events_in_it_async.cs @@ -22,7 +22,7 @@ public class connect_to_existing_persistent_subscription_with_start_from_beginni private List _ids = new List(); private bool _set = false; - private const string _group = "startinbeginning1"; + private const string _group = "startinbeginning2"; protected override void Given() { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs index 2449bb4..5ed89a9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream.cs @@ -20,7 +20,7 @@ public class connect_to_existing_persistent_subscription_with_start_from_beginni private readonly Guid _id = Guid.NewGuid(); private bool _set = false; - private const string _group = "startinbeginning1"; + private const string _group = "startinbeginning3"; protected override void Given() { diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs index 2bd2c45..a985f87 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs @@ -21,7 +21,7 @@ public class connect_to_existing_persistent_subscription_with_start_from_beginni private readonly Guid _id = Guid.NewGuid(); private bool _set = false; - private const string _group = "startinbeginning1"; + private const string _group = "startinbeginning4"; protected override void Given() { From eccbc2d33dd7613c41716d4e5564afb19c464677 Mon Sep 17 00:00:00 2001 From: James Geall Date: Tue, 15 Aug 2017 01:45:38 +0300 Subject: [PATCH 07/44] Fixed broken tests --- .../catch_up_subscription_handles_errors.cs | 12 ++++++------ ..._with_start_from_beginning_and_no_stream_async.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs b/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs index 0865967..6f6093d 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/catch_up_subscription_handles_errors.cs @@ -288,22 +288,22 @@ public void start_completes_onces_subscription_is_live() { var finalEvent = new ManualResetEventSlim(); int callCount = 0; - _connection.HandleReadStreamEventsForwardAsync((stream, start, max) => + _connection.HandleReadStreamEventsForwardAsync(async (stream, start, max) => { callCount++; - - var taskCompletionSource = new TaskCompletionSource(); + await Task.Yield(); + StreamEventsSlice result = null; if (callCount == 1) { - taskCompletionSource.SetResult(CreateStreamEventsSlice(isEnd: true)); + result = CreateStreamEventsSlice(isEnd: true); } else if (callCount == 2) { - taskCompletionSource.SetResult(CreateStreamEventsSlice(fromEvent:1, isEnd: true)); + result = CreateStreamEventsSlice(fromEvent:1, isEnd: true); Assert.That(finalEvent.Wait(TimeoutMs)); } - return taskCompletionSource.Task; + return result; }); _connection.HandleSubscribeToStreamAsync((stream, raise, drop) => diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs index a985f87..872d144 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_existing_persistent_subscription_with_start_from_beginning_and_no_stream_async.cs @@ -43,7 +43,7 @@ protected override void When() private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent) { - if (_set) + if (!_set) { _set = true; _firstEvent = resolvedEvent; From 2cabfd9ddd2dc004bf643e3301746a654859e1f6 Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 24 Aug 2017 12:21:49 +0100 Subject: [PATCH 08/44] Updating to netstandard2.0 --- global.json | 3 - .../EventStore.ClientAPI.NetCore.csproj | 70 ++++++++++--------- .../EventStore.ClientAPI.NetCore.Tests.csproj | 54 +++++++------- wercker.yml | 14 ++-- 4 files changed, 71 insertions(+), 70 deletions(-) delete mode 100644 global.json diff --git a/global.json b/global.json deleted file mode 100644 index b2410a9..0000000 --- a/global.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sdk": { "version": "1.0.4" } -} diff --git a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj index e69fcf9..356d3d0 100755 --- a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj +++ b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj @@ -1,39 +1,41 @@  - - The client API for the Event Store. Get the open source or commercial versions of the Event Store server from http://geteventstore.com - 4.0.0-alpha - Event Store LLP - netstandard1.3 - portable - EventStore.ClientAPI.NetCore - EventStore.ClientAPI.NetCore - eventstore;client;netstandard1.3;netcore - http://geteventstore.com/assets/ouro-200.png - https://github.com/EventStore/netcore-client/blob/master/LICENSE.md - git - https://github.com/EventStore/ClientAPI.NetCore - $(PackageTargetFallback);dnxcore50 - false - false - false - false - false - false - false - false - + + netstandard2.0 + - - - - - - - - - - - + + The client API for the Event Store. Get the open source or commercial versions of the Event Store server from http://geteventstore.com + 4.0.0-alpha + Event Store LLP + portable + EventStore.ClientAPI.NetCore + EventStore.ClientAPI.NetCore + eventstore;client;netstandard2.0;netcore + http://geteventstore.com/assets/ouro-200.png + https://github.com/EventStore/netcore-client/blob/master/LICENSE.md + git + https://github.com/EventStore/ClientAPI.NetCore + false + false + false + false + false + false + false + false + + + + + + + + + + + + + diff --git a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj index 3f24bf7..a80677b 100755 --- a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj +++ b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj @@ -1,35 +1,35 @@  - - Library - + + Library + - - netcoreapp1.1 - EventStore.Core.Tests.ClientAPI - EventStore.ClientAPI.NetCore.Tests - true - $(PackageTargetFallback);portable-net45+win8 - - library - - EventStore.Core.Tests.ClientAPI - + + netcoreapp2.0 + EventStore.Core.Tests.ClientAPI + EventStore.ClientAPI.NetCore.Tests + true + + library + + EventStore.Core.Tests.ClientAPI + False + - - - + + + - - - - - - - + + + + + - - - + + + + + diff --git a/wercker.yml b/wercker.yml index 27aef7c..ce203f9 100644 --- a/wercker.yml +++ b/wercker.yml @@ -6,10 +6,12 @@ build: code: | apt-get update apt-get install apt-transport-https -y - sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list' - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893 + apt-get install curl + curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg + mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg + sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list' apt-get update - apt-get install dotnet-dev-1.0.1 -y + apt-get install dotnet-sdk-2.0.0 -y - script: name: install and run eventstore @@ -32,14 +34,14 @@ build: name: Run tests code: | dotnet restore - dotnet test test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj + dotnet test test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj --no-build --logger trx;LogFileName=~/TestResults.xml after-steps: - script: name: copy log files code: | - echo "contents of ~" - ls ~ + echo "copying test results" + cp ./test/EventStore.ClientAPI.NetCore.Tests/TestResults/*.trx $WERCKER_REPORT_ARTIFACTS_DIR echo "copying server logs" cp -R ~/logs $WERCKER_REPORT_ARTIFACTS_DIR # TODO: copy test output \ No newline at end of file From b0631723dd6d9321d33168d3d176a526e2025159 Mon Sep 17 00:00:00 2001 From: James Geall Date: Sun, 27 Aug 2017 09:54:02 +0100 Subject: [PATCH 09/44] Adding appveyor scripts for nuget package deployment --- appveyor.yml | 36 +++++++++++++++++++++++++++++ scripts/installandruneventstore.ps1 | 2 ++ scripts/updateversion.ps1 | 8 +++++++ 3 files changed, 46 insertions(+) create mode 100644 appveyor.yml create mode 100644 scripts/installandruneventstore.ps1 create mode 100644 scripts/updateversion.ps1 diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..33e7ff4 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,36 @@ +version: 4.0.2.{build} + +image: Visual Studio 2017 + +install: + - ps: .\scripts\updateversion.ps1 + - ps: .\scripts\installandruneventstore.ps1 + +dotnet_csproj: + patch: true + file: '**\*.csproj' + version: '{version}' + package_version: '{version}' + +configuration: Release + +before_build: + - msbuild /t:restore EventStore.ClientAPI.NetCore.sln + +build: + project: EventStore.ClientAPI.NetCore.sln /t:pack + +test_script: + - dotnet test EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj --no-build + + +artifacts: + - path: '*.nupkg' + +# deploy: +# provider: NuGet +# on: +# appveyor_repo_tag: true +# api_key: +# secure: +# artifact: /.*\.nupkg/ diff --git a/scripts/installandruneventstore.ps1 b/scripts/installandruneventstore.ps1 new file mode 100644 index 0000000..39b44aa --- /dev/null +++ b/scripts/installandruneventstore.ps1 @@ -0,0 +1,2 @@ +(New-Object Net.WebClient).DownloadFile('http://download.geteventstore.com/binaries/EventStore-OSS-Win-v4.0.2.zip','%TEMP%\eventstore.zip');(new-object -com shell.application).namespace('%TEMP%\EventStore').CopyHere((new-object -com shell.application).namespace('%TEMP%\Tools\eventstore.zip').Items(),16) +start-process -NoNewWindow %TEMP%\EventStore\EventStore.ClusterNode.exe --memdb --run-projections ALL \ No newline at end of file diff --git a/scripts/updateversion.ps1 b/scripts/updateversion.ps1 new file mode 100644 index 0000000..08341b7 --- /dev/null +++ b/scripts/updateversion.ps1 @@ -0,0 +1,8 @@ +$v = new-object System.Version($env:APPVEYOR_BUILD_VERSION) +$version = "{0}.{1}.{2}-alpha-{3}" -f ($v.Major, $v.Minor, $v.Build, $v.Revision) + +if($env:APPVEYOR_REPO_TAG -eq 'True'){ + $version = $env:APPVEYOR_REPO_BRANCH +} + +Update-AppveyorBuild -version $version \ No newline at end of file From c4b632b73499326e931108b268256f59cf38be0e Mon Sep 17 00:00:00 2001 From: James Geall Date: Sun, 27 Aug 2017 15:38:24 +0100 Subject: [PATCH 10/44] Install eventstore for AppVeyor build and fix appveyor build and test scripts --- appveyor.yml | 28 +++++++++--------- scripts/appveyortest.ps1 | 4 +++ scripts/installandruneventstore.ps1 | 5 ++-- scripts/updateversion.ps1 | 8 ++--- .../EventStore.ClientAPI.NetCore.csproj | 29 +++++++------------ .../Properties/AssemblyInfo.cs | 12 -------- 6 files changed, 32 insertions(+), 54 deletions(-) create mode 100644 scripts/appveyortest.ps1 diff --git a/appveyor.yml b/appveyor.yml index 33e7ff4..14b2919 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,19 +18,17 @@ before_build: - msbuild /t:restore EventStore.ClientAPI.NetCore.sln build: - project: EventStore.ClientAPI.NetCore.sln /t:pack - + project: EventStore.ClientAPI.NetCore.sln + publish_nuget: true + verbosity: minimal + test_script: - - dotnet test EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj --no-build - - -artifacts: - - path: '*.nupkg' - -# deploy: -# provider: NuGet -# on: -# appveyor_repo_tag: true -# api_key: -# secure: -# artifact: /.*\.nupkg/ + - ps: .\scripts\appveyortest.ps1 + +deploy: + provider: NuGet + on: + appveyor_repo_tag: true + api_key: + secure: zd6D5E28IF7m/HSA9k1GUDSzOiWhnrvQUBATrbEqA2MJVh1rDDl+4LDuv+dvioWp + artifact: /.*\.nupkg/ diff --git a/scripts/appveyortest.ps1 b/scripts/appveyortest.ps1 new file mode 100644 index 0000000..a9bb1b7 --- /dev/null +++ b/scripts/appveyortest.ps1 @@ -0,0 +1,4 @@ +$testResults = Join-Path $env:APPVEYOR_BUILD_FOLDER testResults.xml +dotnet test test\EventStore.ClientAPI.NetCore.Tests\EventStore.ClientAPI.NetCore.Tests.csproj --no-build --logger="trx;LogFileName=$testResults" +$wc = New-Object System.Net.WebClient +$wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$env:APPVEYOR_JOB_ID", $testResults) \ No newline at end of file diff --git a/scripts/installandruneventstore.ps1 b/scripts/installandruneventstore.ps1 index 39b44aa..5d40be6 100644 --- a/scripts/installandruneventstore.ps1 +++ b/scripts/installandruneventstore.ps1 @@ -1,2 +1,3 @@ -(New-Object Net.WebClient).DownloadFile('http://download.geteventstore.com/binaries/EventStore-OSS-Win-v4.0.2.zip','%TEMP%\eventstore.zip');(new-object -com shell.application).namespace('%TEMP%\EventStore').CopyHere((new-object -com shell.application).namespace('%TEMP%\Tools\eventstore.zip').Items(),16) -start-process -NoNewWindow %TEMP%\EventStore\EventStore.ClusterNode.exe --memdb --run-projections ALL \ No newline at end of file +(New-Object Net.WebClient).DownloadFile('http://download.geteventstore.com/binaries/EventStore-OSS-Win-v4.0.2.zip','c:\tools\eventstore.zip') +7z e C:\tools\eventstore.zip -oC:\tools\EventStore +start-process -NoNewWindow "C:\tools\EventStore\EventStore.ClusterNode.exe" "--memdb --run-projections ALL" \ No newline at end of file diff --git a/scripts/updateversion.ps1 b/scripts/updateversion.ps1 index 08341b7..48727cc 100644 --- a/scripts/updateversion.ps1 +++ b/scripts/updateversion.ps1 @@ -1,8 +1,4 @@ -$v = new-object System.Version($env:APPVEYOR_BUILD_VERSION) -$version = "{0}.{1}.{2}-alpha-{3}" -f ($v.Major, $v.Minor, $v.Build, $v.Revision) if($env:APPVEYOR_REPO_TAG -eq 'True'){ - $version = $env:APPVEYOR_REPO_BRANCH -} - -Update-AppveyorBuild -version $version \ No newline at end of file + Update-AppveyorBuild -version $env:APPVEYOR_REPO_BRANCH +} \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj index 356d3d0..51ca040 100755 --- a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj +++ b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj @@ -1,41 +1,32 @@ - + netstandard2.0 - + + EventStore.ClientAPI + EventStore NetStandard ClientApi + Event Store LLP + Copyright © Event Store LLP. All rights reserved. + EventStore.ClientAPI + 4.0.2-alpha + The client API for the Event Store. Get the open source or commercial versions of the Event Store server from http://geteventstore.com - 4.0.0-alpha Event Store LLP portable EventStore.ClientAPI.NetCore EventStore.ClientAPI.NetCore - eventstore;client;netstandard2.0;netcore + eventstore;client;netstandard2.0 http://geteventstore.com/assets/ouro-200.png https://github.com/EventStore/netcore-client/blob/master/LICENSE.md git https://github.com/EventStore/ClientAPI.NetCore - false - false - false - false - false - false - false - false - - - - - - - diff --git a/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs b/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs index a4048b2..1d8312a 100644 --- a/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs +++ b/src/EventStore.ClientAPI.NetCore/Properties/AssemblyInfo.cs @@ -2,18 +2,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: AssemblyTitle("EventStore.ClientAPI")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Event Store LLP")] -[assembly: AssemblyProduct("EventStore.ClientAPI")] -[assembly: AssemblyCopyright("Copyright © Event Store LLP. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.0.0.0")] - [assembly: ComVisible(false)] [assembly: Guid("0bffd734-18c5-4575-9321-324ed1a3bbfb")] [assembly: InternalsVisibleTo("EventStore.Core.Tests.ClientAPI")] \ No newline at end of file From 16089050e8874fb48ec66732459d19e8fb4ec432 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 4 Sep 2017 13:14:02 +0300 Subject: [PATCH 11/44] Added appveyor build status --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01b358d..dfd2e8c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # netcore-client .NET Core Client -Direct port of the .NET client to .NET core targetting .netstandard1.3 and above +Direct port of the .NET client to .NET core targetting .netstandard 2.0 Works with EventStore server 4.0.0 and above [![wercker status](https://app.wercker.com/status/21204a69779b2b4543242fd543d0aaab/s/master "wercker status")](https://app.wercker.com/project/byKey/21204a69779b2b4543242fd543d0aaab) +[![Appveyor status](https://ci.appveyor.com/api/projects/status/8tcaw05oa59fkba2/branch/master?svg=true)](https://ci.appveyor.com/project/EventStore/clientapi-netcore/branch/master) \ No newline at end of file From 6154cc5b1fe847368b7afabc618f0fd816c8157f Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 4 Sep 2017 13:14:45 +0300 Subject: [PATCH 12/44] Fixed ProjectionManager GetResultsAsync And GetPartitionResultsAsync --- .../Projections/ProjectionsManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs index 97da93e..ebf6233 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs @@ -227,7 +227,7 @@ public Task GetPartitionStateAsync(string name, string partitionId, User public Task GetResultAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetState(_httpEndPoint, name, userCredentials); + return _client.GetResult(_httpEndPoint, name, userCredentials); } /// @@ -241,7 +241,7 @@ public Task GetPartitionResultAsync(string name, string partitionId, Use { Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(partitionId, "partitionId"); - return _client.GetPartitionStateAsync(_httpEndPoint, name, partitionId, userCredentials); + return _client.GetPartitionResultAsync(_httpEndPoint, name, partitionId, userCredentials); } /// From 93235d14de4b685f7604f053f281f35e89ebc725 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 4 Sep 2017 13:26:53 +0300 Subject: [PATCH 13/44] Fixes memory leak in subscription Uses do .. while rather than recursion --- .../EventStoreCatchUpSubscription.cs | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs index ed767c4..351f655 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs @@ -414,34 +414,31 @@ internal EventStoreAllCatchUpSubscription(IEventStoreConnection connection, /// protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) => - ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber); + ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastCommitPosition); private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos, - UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) + UserCredentials userCredentials, long? lastCommitPosition) { - var slice = await connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false); - await ReadEventsCallbackAsync(slice, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber).ConfigureAwait(false); + bool shouldStopOrDone; + do + { + var slice = await connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false); + shouldStopOrDone = await ReadEventsCallbackAsync(slice, lastCommitPosition).ConfigureAwait(false); + } while (!shouldStopOrDone); } - private async Task ReadEventsCallbackAsync(AllEventsSlice slice, IEventStoreConnection connection, bool resolveLinkTos, - UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) + private async Task ReadEventsCallbackAsync(AllEventsSlice slice, long? lastCommitPosition) { - if (!(await ProcessEventsAsync(lastCommitPosition, slice).ConfigureAwait(false)) && !ShouldStop) - { - await ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, - lastCommitPosition, lastEventNumber).ConfigureAwait(false); - } - else + bool shouldStopOrDone = ShouldStop || await ProcessEventsAsync(lastCommitPosition, slice).ConfigureAwait(false); + if (shouldStopOrDone && Verbose) { - if (Verbose) - { - Log.Debug( - "Catch-up Subscription {0} to {1}: finished reading events, nextReadPosition = {2}.", - SubscriptionName, - IsSubscribedToAll ? "" : StreamId, - _nextReadPosition); - } + Log.Debug( + "Catch-up Subscription {0} to {1}: finished reading events, nextReadPosition = {2}.", + SubscriptionName, + IsSubscribedToAll ? "" : StreamId, + _nextReadPosition); } + return shouldStopOrDone; } private async Task ProcessEventsAsync(long? lastCommitPosition, AllEventsSlice slice) @@ -537,7 +534,7 @@ internal EventStoreStreamCatchUpSubscription(IEventStoreConnection connection, protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) => ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastEventNumber); - + private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastEventNumber) { @@ -632,4 +629,4 @@ protected override async Task TryProcessAsync(ResolvedEvent e) } } } -} +} \ No newline at end of file From ad600794dd0bf52db06f6b1bd7d0110d892471f5 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 4 Sep 2017 13:30:19 +0300 Subject: [PATCH 14/44] Fixes argument name in ArgumentException --- .../PersistentSubscriptionSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs index 3079584..6275166 100644 --- a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs @@ -104,8 +104,8 @@ internal PersistentSubscriptionSettings(bool resolveLinkTos, long startFrom, boo TimeSpan checkPointAfter, int minCheckPointCount, int maxCheckPointCount, int maxSubscriberCount, string namedConsumerStrategy) { - if(messageTimeout.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("messageTimeout", "milliseconds must be less or equal to than int32.MaxValue"); - if(checkPointAfter.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("checkPointAfter", "milliseconds must be less or equal to than int32.MaxValue"); + if (messageTimeout.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(messageTimeout)); + if (checkPointAfter.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(checkPointAfter)); MessageTimeout = messageTimeout; ResolveLinkTos = resolveLinkTos; StartFrom = startFrom; From 009ff01211f1beb3b1d0d95995f3e88600952df1 Mon Sep 17 00:00:00 2001 From: Joseph Woodward Date: Mon, 4 Sep 2017 12:31:13 +0100 Subject: [PATCH 15/44] Update read me Updates to make it clearer what this package is, including the terms people will no doubt search for in Google, also added NuGet CLI commands and link to NuGet page. --- README.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index dfd2e8c..df57e34 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,24 @@ -# netcore-client -.NET Core Client +# EventStore .NET Core Client -Direct port of the .NET client to .NET core targetting .netstandard 2.0 +Official direct port of the Event Store .NET client to .NET Core targetting .netstandard 2.0 -Works with EventStore server 4.0.0 and above +Works with EventStore server 4.0.0 and above. [![wercker status](https://app.wercker.com/status/21204a69779b2b4543242fd543d0aaab/s/master "wercker status")](https://app.wercker.com/project/byKey/21204a69779b2b4543242fd543d0aaab) -[![Appveyor status](https://ci.appveyor.com/api/projects/status/8tcaw05oa59fkba2/branch/master?svg=true)](https://ci.appveyor.com/project/EventStore/clientapi-netcore/branch/master) \ No newline at end of file +[![Appveyor status](https://ci.appveyor.com/api/projects/status/8tcaw05oa59fkba2/branch/master?svg=true)](https://ci.appveyor.com/project/EventStore/clientapi-netcore/branch/master) + +## Installation + +You can install the Eventstore .NET Core client by copying and pasting the following command into your Package Manager Console within Visual Studio (Tools > NuGet Package Manager > Package Manager Console). + +```bash +Install-Package EventStore.ClientAPI.NetCore +``` + +Alternatively if you're using the .NET Core CLI then you can install the client via the command line interface with the following command: + +```bash +dotnet add package EventStore.ClientAPI.NetCore +``` + +For more information see the [EventStore.ClientAPI.NetCore NuGet page](https://www.nuget.org/packages/EventStore.ClientAPI.NetCore/). From fedb06d482b973ffb4126af7399e9d74fe0e39bb Mon Sep 17 00:00:00 2001 From: James Geall Date: Wed, 6 Sep 2017 17:03:55 +0300 Subject: [PATCH 16/44] Cleans up handling of creating connection from gossip seeds or uri when using connection string and settings improved docs and error messages when gossip seeds or uri not specified in a valid combination --- .../EventStoreConnection.cs | 97 +++++++++++-------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index 2c290c5..58d7601 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -37,7 +37,7 @@ public static IEventStoreConnection Create(string connectionString, string conne } /// - /// Creates a new to single node using default provided via a connectionstring + /// Creates a new to single node using the overriding them with values provided via the connectionstring /// /// Optional name of connection (will be generated automatically, if not provided) /// Pre-populated settings builder, optional. If not specified, a new builder will be created. @@ -47,11 +47,11 @@ public static IEventStoreConnection Create(string connectionString, ConnectionSe { var settings = ConnectionString.GetConnectionSettings(connectionString, builder); var uri = GetUriFromConnectionString(connectionString); - if(uri == null && (settings.GossipSeeds == null || settings.GossipSeeds.Length == 0)) + if (uri == null && (settings.GossipSeeds == null || settings.GossipSeeds.Length == 0)) { throw new Exception(string.Format("Did not find ConnectTo or GossipSeeds in the connection string.\n'{0}'", connectionString)); } - if(uri != null && settings.GossipSeeds != null && settings.GossipSeeds.Length > 0) + if (uri != null && settings.GossipSeeds != null && settings.GossipSeeds.Length > 0) { throw new NotSupportedException(string.Format("Setting ConnectTo as well as GossipSeeds on the connection string is currently not supported.\n{0}", connectionString)); } @@ -59,58 +59,75 @@ public static IEventStoreConnection Create(string connectionString, ConnectionSe } /// - /// Creates a new to single node using passed + /// Creates a new using the gossip seeds specified in the /// /// Optional name of connection (will be generated automatically, if not provided) /// The to apply to the new connection /// a new public static IEventStoreConnection Create(ConnectionSettings connectionSettings, string connectionName = null) { + if (connectionSettings.GossipSeeds == null || connectionSettings.GossipSeeds.Length == 0) + throw new ArgumentException("No gossip seeds specified", nameof(connectionSettings)); return Create(connectionSettings, (Uri)null, connectionName); } /// - /// Creates a new to single node using default + /// Creates a new /// /// Optional name of connection (will be generated automatically, if not provided) - /// The to apply to the new connection - /// The Uri to connect to. It can be tcp:// to point to a single node or discover:// to discover nodes via dns + /// The to apply to the new connection. If null the default settings will be used and the must not be null + /// The Uri to connect to. It can be tcp:// to point to a single node or discover:// to discover nodes via dns or null to connect using the gossip seeds from the /// a new - public static IEventStoreConnection Create(ConnectionSettings connectionSettings, Uri uri, string connectionName = null) + /// You must pass a uri or set gossip seeds in the connection settings. + public static IEventStoreConnection Create(ConnectionSettings connectionSettings, Uri uri, + string connectionName = null) { - var scheme = uri == null ? "" : uri.Scheme.ToLower(); - connectionSettings = connectionSettings ?? ConnectionSettings.Default; - var credential = GetCredentialFromUri(uri); - if (credential != null) - { - connectionSettings = new ConnectionSettings(connectionSettings.Log, connectionSettings.VerboseLogging, connectionSettings.MaxQueueSize, connectionSettings.MaxConcurrentItems, - connectionSettings.MaxRetries, connectionSettings.MaxReconnections, connectionSettings.RequireMaster, connectionSettings.ReconnectionDelay, connectionSettings.OperationTimeout, - connectionSettings.OperationTimeoutCheckPeriod, credential, connectionSettings.UseSslConnection, connectionSettings.TargetHost, - connectionSettings.ValidateServer, connectionSettings.FailOnNoServerResponse, connectionSettings.HeartbeatInterval, connectionSettings.HeartbeatTimeout, - connectionSettings.ClientConnectionTimeout, connectionSettings.ClusterDns, connectionSettings.GossipSeeds, connectionSettings.MaxDiscoverAttempts, - connectionSettings.ExternalGossipPort, connectionSettings.GossipTimeout, connectionSettings.PreferRandomNode); - } - if (scheme == "discover") - { - var clusterSettings = new ClusterSettings(uri.Host, connectionSettings.MaxDiscoverAttempts, uri.Port, connectionSettings.GossipTimeout, connectionSettings.PreferRandomNode); - Ensure.NotNull(connectionSettings, "connectionSettings"); - Ensure.NotNull(clusterSettings, "clusterSettings"); - - var endPointDiscoverer = new ClusterDnsEndPointDiscoverer(connectionSettings.Log, - clusterSettings.ClusterDns, - clusterSettings.MaxDiscoverAttempts, - clusterSettings.ExternalGossipPort, - clusterSettings.GossipSeeds, - clusterSettings.GossipTimeout, - clusterSettings.PreferRandomNode); - - return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); - } - - if (scheme == "tcp") + if (uri != null) { - return new EventStoreNodeConnection(connectionSettings, null, new SingleEndpointDiscoverer(uri, connectionSettings.UseSslConnection), connectionName); + var scheme = uri.Scheme.ToLower(); + var credential = GetCredentialFromUri(uri); + if (credential != null) + { + connectionSettings = new ConnectionSettings(connectionSettings.Log, connectionSettings.VerboseLogging, + connectionSettings.MaxQueueSize, connectionSettings.MaxConcurrentItems, + connectionSettings.MaxRetries, connectionSettings.MaxReconnections, + connectionSettings.RequireMaster, connectionSettings.ReconnectionDelay, + connectionSettings.OperationTimeout, + connectionSettings.OperationTimeoutCheckPeriod, credential, connectionSettings.UseSslConnection, + connectionSettings.TargetHost, + connectionSettings.ValidateServer, connectionSettings.FailOnNoServerResponse, + connectionSettings.HeartbeatInterval, connectionSettings.HeartbeatTimeout, + connectionSettings.ClientConnectionTimeout, connectionSettings.ClusterDns, + connectionSettings.GossipSeeds, connectionSettings.MaxDiscoverAttempts, + connectionSettings.ExternalGossipPort, connectionSettings.GossipTimeout, + connectionSettings.PreferRandomNode); + } + if (scheme == "discover") + { + var clusterSettings = new ClusterSettings(uri.Host, connectionSettings.MaxDiscoverAttempts, uri.Port, + connectionSettings.GossipTimeout, connectionSettings.PreferRandomNode); + Ensure.NotNull(connectionSettings, "connectionSettings"); + Ensure.NotNull(clusterSettings, "clusterSettings"); + + var endPointDiscoverer = new ClusterDnsEndPointDiscoverer(connectionSettings.Log, + clusterSettings.ClusterDns, + clusterSettings.MaxDiscoverAttempts, + clusterSettings.ExternalGossipPort, + clusterSettings.GossipSeeds, + clusterSettings.GossipTimeout, + clusterSettings.PreferRandomNode); + + return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, + connectionName); + } + + if (scheme == "tcp") + { + return new EventStoreNodeConnection(connectionSettings, null, + new SingleEndpointDiscoverer(uri, connectionSettings.UseSslConnection), connectionName); + } + throw new Exception(string.Format("Unknown scheme for connection '{0}'", scheme)); } if (connectionSettings.GossipSeeds != null && connectionSettings.GossipSeeds.Length > 0) { @@ -132,7 +149,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); } - throw new Exception(string.Format("Unknown scheme for connection '{0}'", scheme)); + throw new Exception($"Must specify uri or gossip seeds"); } private static UserCredentials GetCredentialFromUri(Uri uri) From e80161d3a75d8983e1b77a0977b9c964354c467a Mon Sep 17 00:00:00 2001 From: James Geall Date: Wed, 25 Oct 2017 14:18:03 +0300 Subject: [PATCH 17/44] Replaced IpEndpointExtensions by EndpointExtensions to create HttpUrls from IP or Dns Added schema for HttpUrl-creation to switch between http and https implemented schema to all ToHttpUrl-Extension-method-calls changed ProjectionsClient to use EndPoint instead of IPEndPoint changed ProjectionsManager constructor to take EndPoint Added httpShema to ProjectionsClient-methods as optional parameter Added httpSchema as optional paramter to ProjectionsManager constructor --- .../Internal/ClusterDnsEndPointDiscoverer.cs | 2 +- .../Projections/ProjectionsClient.cs | 84 +++++++++---------- .../Projections/ProjectionsManager.cs | 50 ++++++----- .../Transport.Http/EndpointExtensions.cs | 44 ++++++++++ .../Transport.Http/IPEndpointExtensions.cs | 23 ----- .../UserManagement/UsersClient.cs | 48 +++++------ .../UserManagement/UsersManager.cs | 7 +- 7 files changed, 143 insertions(+), 115 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs delete mode 100644 src/EventStore.ClientAPI.NetCore/Transport.Http/IPEndpointExtensions.cs diff --git a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs index a626837..7df33d9 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs @@ -177,7 +177,7 @@ private ClusterMessages.ClusterInfoDto TryGetGossipFrom(GossipSeed endPoint) ClusterMessages.ClusterInfoDto result = null; var completed = new ManualResetEventSlim(false); - var url = endPoint.EndPoint.ToHttpUrl("/gossip?format=json"); + var url = endPoint.EndPoint.ToHttpUrl(EndpointExtensions.HTTP_SCHEMA, "/gossip?format=json"); _client.Get( url, null, diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs index 20039c6..7c2e9eb 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs @@ -21,50 +21,50 @@ public ProjectionsClient(ILogger log, TimeSpan operationTimeout) _client = new HttpAsyncClient(_operationTimeout); } - public Task Enable(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task Enable(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/projection/{0}/command/enable", name), string.Empty, userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/command/enable", name), string.Empty, userCredentials, HttpStatusCode.OK); } - public Task Disable(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task Disable(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/projection/{0}/command/disable", name), string.Empty, userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/command/disable", name), string.Empty, userCredentials, HttpStatusCode.OK); } - public Task Abort(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task Abort(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/projection/{0}/command/abort", name), string.Empty, userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/command/abort", name), string.Empty, userCredentials, HttpStatusCode.OK); } - public Task CreateOneTime(IPEndPoint endPoint, string query, UserCredentials userCredentials = null) + public Task CreateOneTime(EndPoint endPoint, string query, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/projections/onetime?type=JS"), query, userCredentials, HttpStatusCode.Created); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/projections/onetime?type=JS"), query, userCredentials, HttpStatusCode.Created); } - public Task CreateTransient(IPEndPoint endPoint, string name, string query, UserCredentials userCredentials = null) + public Task CreateTransient(EndPoint endPoint, string name, string query, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { return SendPost( - endPoint.ToHttpUrl("/projections/transient?name={0}&type=JS", name), + endPoint.ToHttpUrl(httpSchema, "/projections/transient?name={0}&type=JS", name), query, userCredentials, HttpStatusCode.Created); } - public Task CreateContinuous(IPEndPoint endPoint, string name, string query, bool trackEmitted, UserCredentials userCredentials = null) + public Task CreateContinuous(EndPoint endPoint, string name, string query, bool trackEmitted, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/projections/continuous?name={0}&type=JS&emit=1&trackemittedstreams={1}", name, trackEmitted), + return SendPost(endPoint.ToHttpUrl(httpSchema, "/projections/continuous?name={0}&type=JS&emit=1&trackemittedstreams={1}", name, trackEmitted), query, userCredentials, HttpStatusCode.Created); } [Obsolete("Use 'Task> ListAll' instead")] - public Task ListAllAsString(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task ListAllAsString(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/any"), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/any"), userCredentials, HttpStatusCode.OK); } - public Task> ListAll(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task> ListAll(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/any"), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/any"), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -74,14 +74,14 @@ public Task> ListAll(IPEndPoint endPoint, UserCredential } [Obsolete("Use 'Task> ListOneTime' instead")] - public Task ListOneTimeAsString(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task ListOneTimeAsString(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/onetime"), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/onetime"), userCredentials, HttpStatusCode.OK); } - public Task> ListOneTime(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task> ListOneTime(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/onetime"), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/onetime"), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -91,14 +91,14 @@ public Task> ListOneTime(IPEndPoint endPoint, UserCreden } [Obsolete("Use 'Task> ListContinuous' instead")] - public Task ListContinuousAsString(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task ListContinuousAsString(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/continuous"), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/continuous"), userCredentials, HttpStatusCode.OK); } - public Task> ListContinuous(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task> ListContinuous(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projections/continuous"), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projections/continuous"), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -107,49 +107,49 @@ public Task> ListContinuous(IPEndPoint endPoint, UserCre }); } - public Task GetStatus(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task GetStatus(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}", name), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}", name), userCredentials, HttpStatusCode.OK); } - public Task GetState(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task GetState(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/state", name), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/state", name), userCredentials, HttpStatusCode.OK); } - public Task GetPartitionStateAsync(IPEndPoint endPoint, string name, string partition, UserCredentials userCredentials = null) + public Task GetPartitionStateAsync(EndPoint endPoint, string name, string partition, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/state?partition={1}", name, partition), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/state?partition={1}", name, partition), userCredentials, HttpStatusCode.OK); } - public Task GetResult(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task GetResult(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/result", name), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/result", name), userCredentials, HttpStatusCode.OK); } - public Task GetPartitionResultAsync(IPEndPoint endPoint, string name, string partition, UserCredentials userCredentials = null) + public Task GetPartitionResultAsync(EndPoint endPoint, string name, string partition, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/result?partition={1}", name, partition), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/result?partition={1}", name, partition), userCredentials, HttpStatusCode.OK); } - public Task GetStatistics(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task GetStatistics(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/statistics", name), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/statistics", name), userCredentials, HttpStatusCode.OK); } - public Task GetQuery(IPEndPoint endPoint, string name, UserCredentials userCredentials = null) + public Task GetQuery(EndPoint endPoint, string name, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/projection/{0}/query", name), userCredentials, HttpStatusCode.OK); + return SendGet(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/query", name), userCredentials, HttpStatusCode.OK); } - public Task UpdateQuery(IPEndPoint endPoint, string name, string query, UserCredentials userCredentials = null) + public Task UpdateQuery(EndPoint endPoint, string name, string query, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPut(endPoint.ToHttpUrl("/projection/{0}/query?type=JS", name), query, userCredentials, HttpStatusCode.OK); + return SendPut(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/query?type=JS", name), query, userCredentials, HttpStatusCode.OK); } - public Task Delete(IPEndPoint endPoint, string name, bool deleteEmittedStreams, UserCredentials userCredentials = null) + public Task Delete(EndPoint endPoint, string name, bool deleteEmittedStreams, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendDelete(endPoint.ToHttpUrl("/projection/{0}?deleteEmittedStreams={1}", name, deleteEmittedStreams), userCredentials, HttpStatusCode.OK); + return SendDelete(endPoint.ToHttpUrl(httpSchema, "/projection/{0}?deleteEmittedStreams={1}", name, deleteEmittedStreams), userCredentials, HttpStatusCode.OK); } private Task SendGet(string url, UserCredentials userCredentials, int expectedCode) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs index ebf6233..582a79e 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.SystemData; +using EventStore.ClientAPI.Transport.Http; namespace EventStore.ClientAPI.Projections { @@ -14,7 +15,8 @@ namespace EventStore.ClientAPI.Projections public class ProjectionsManager { private readonly ProjectionsClient _client; - private readonly IPEndPoint _httpEndPoint; + private readonly EndPoint _httpEndPoint; + private readonly string _httpSchema; /// /// Creates a new instance of . @@ -22,13 +24,15 @@ public class ProjectionsManager /// An instance of to use for logging. /// HTTP endpoint of an Event Store server. /// - public ProjectionsManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan operationTimeout) + /// HTTP endpoint schema http|https. + public ProjectionsManager(ILogger log, EndPoint httpEndPoint, TimeSpan operationTimeout, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { Ensure.NotNull(log, "log"); Ensure.NotNull(httpEndPoint, "httpEndPoint"); _client = new ProjectionsClient(log, operationTimeout); _httpEndPoint = httpEndPoint; + _httpSchema = httpSchema; } /// @@ -40,7 +44,7 @@ public ProjectionsManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan operati public Task EnableAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.Enable(_httpEndPoint, name, userCredentials); + return _client.Enable(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -52,7 +56,7 @@ public Task EnableAsync(string name, UserCredentials userCredentials = null) public Task DisableAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.Disable(_httpEndPoint, name, userCredentials); + return _client.Disable(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -64,7 +68,7 @@ public Task DisableAsync(string name, UserCredentials userCredentials = null) public Task AbortAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.Abort(_httpEndPoint, name, userCredentials); + return _client.Abort(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -75,7 +79,7 @@ public Task AbortAsync(string name, UserCredentials userCredentials = null) public Task CreateOneTimeAsync(string query, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(query, "query"); - return _client.CreateOneTime(_httpEndPoint, query, userCredentials); + return _client.CreateOneTime(_httpEndPoint, query, userCredentials, _httpSchema); } /// @@ -88,7 +92,7 @@ public Task CreateTransientAsync(string name, string query, UserCredentials user { Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(query, "query"); - return _client.CreateTransient(_httpEndPoint, name, query, userCredentials); + return _client.CreateTransient(_httpEndPoint, name, query, userCredentials, _httpSchema); } /// @@ -114,7 +118,7 @@ public Task CreateContinuousAsync(string name, string query, bool trackEmittedSt Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(query, "query"); - return _client.CreateContinuous(_httpEndPoint, name, query, trackEmittedStreams, userCredentials); + return _client.CreateContinuous(_httpEndPoint, name, query, trackEmittedStreams, userCredentials, _httpSchema); } /// @@ -125,7 +129,7 @@ public Task CreateContinuousAsync(string name, string query, bool trackEmittedSt [Obsolete("Use 'Task> ListAll' instead")] public Task ListAllAsStringAsync(UserCredentials userCredentials = null) { - return _client.ListAllAsString(_httpEndPoint, userCredentials); + return _client.ListAllAsString(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -135,7 +139,7 @@ public Task ListAllAsStringAsync(UserCredentials userCredentials = null) /// List of all ProjectionDetails items containing projection statuses. public Task> ListAllAsync(UserCredentials userCredentials = null) { - return _client.ListAll(_httpEndPoint, userCredentials); + return _client.ListAll(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -146,7 +150,7 @@ public Task> ListAllAsync(UserCredentials userCredential [Obsolete("Use 'Task> ListOneTime' instead")] public Task ListOneTimeAsStringAsync(UserCredentials userCredentials = null) { - return _client.ListOneTimeAsString(_httpEndPoint, userCredentials); + return _client.ListOneTimeAsString(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -156,7 +160,7 @@ public Task ListOneTimeAsStringAsync(UserCredentials userCredentials = n /// List of one-time ProjectionDetails items containing projection statuses. public Task> ListOneTimeAsync(UserCredentials userCredentials = null) { - return _client.ListOneTime(_httpEndPoint, userCredentials); + return _client.ListOneTime(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -167,7 +171,7 @@ public Task> ListOneTimeAsync(UserCredentials userCreden [Obsolete("Use 'Task> ListContinuous' instead")] public Task ListContinuousAsStringAsync(UserCredentials userCredentials = null) { - return _client.ListContinuousAsString(_httpEndPoint, userCredentials); + return _client.ListContinuousAsString(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -177,7 +181,7 @@ public Task ListContinuousAsStringAsync(UserCredentials userCredentials /// List of continuous ProjectionDetails items containing projection statuses. public Task> ListContinuousAsync(UserCredentials userCredentials = null) { - return _client.ListContinuous(_httpEndPoint, userCredentials); + return _client.ListContinuous(_httpEndPoint, userCredentials, _httpSchema); } /// @@ -189,7 +193,7 @@ public Task> ListContinuousAsync(UserCredentials userCre public Task GetStatusAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetStatus(_httpEndPoint, name, userCredentials); + return _client.GetStatus(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -201,7 +205,7 @@ public Task GetStatusAsync(string name, UserCredentials userCredentials public Task GetStateAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetState(_httpEndPoint, name, userCredentials); + return _client.GetState(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -215,7 +219,7 @@ public Task GetPartitionStateAsync(string name, string partitionId, User { Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(partitionId, "partitionId"); - return _client.GetPartitionStateAsync(_httpEndPoint, name, partitionId, userCredentials); + return _client.GetPartitionStateAsync(_httpEndPoint, name, partitionId, userCredentials, _httpSchema); } /// @@ -227,7 +231,7 @@ public Task GetPartitionStateAsync(string name, string partitionId, User public Task GetResultAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetResult(_httpEndPoint, name, userCredentials); + return _client.GetResult(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -241,7 +245,7 @@ public Task GetPartitionResultAsync(string name, string partitionId, Use { Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(partitionId, "partitionId"); - return _client.GetPartitionResultAsync(_httpEndPoint, name, partitionId, userCredentials); + return _client.GetPartitionResultAsync(_httpEndPoint, name, partitionId, userCredentials, _httpSchema); } /// @@ -253,7 +257,7 @@ public Task GetPartitionResultAsync(string name, string partitionId, Use public Task GetStatisticsAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetStatistics(_httpEndPoint, name, userCredentials); + return _client.GetStatistics(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -265,7 +269,7 @@ public Task GetStatisticsAsync(string name, UserCredentials userCredenti public Task GetQueryAsync(string name, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.GetQuery(_httpEndPoint, name, userCredentials); + return _client.GetQuery(_httpEndPoint, name, userCredentials, _httpSchema); } /// @@ -279,7 +283,7 @@ public Task UpdateQueryAsync(string name, string query, UserCredentials userCred Ensure.NotNullOrEmpty(name, "name"); Ensure.NotNullOrEmpty(query, "query"); - return _client.UpdateQuery(_httpEndPoint, name, query, userCredentials); + return _client.UpdateQuery(_httpEndPoint, name, query, userCredentials, _httpSchema); } /// @@ -303,7 +307,7 @@ public Task DeleteAsync(string name, UserCredentials userCredentials = null) public Task DeleteAsync(string name, bool deleteEmittedStreams, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(name, "name"); - return _client.Delete(_httpEndPoint, name, deleteEmittedStreams, userCredentials); + return _client.Delete(_httpEndPoint, name, deleteEmittedStreams, userCredentials, _httpSchema); } } } diff --git a/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs b/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs new file mode 100644 index 0000000..622b3e8 --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs @@ -0,0 +1,44 @@ +using System.Net; + +namespace EventStore.ClientAPI.Transport.Http +{ + internal static class EndpointExtensions + { + public const string HTTP_SCHEMA = "http"; + public const string HTTPS_SCHEMA = "https"; + public static string ToHttpUrl(this EndPoint endPoint, string schema, string rawUrl) + { + if (endPoint is IPEndPoint) + { + var ipEndPoint = endPoint as IPEndPoint; + return CreateHttpUrl(schema, ipEndPoint.Address.ToString(), ipEndPoint.Port, rawUrl != null ? rawUrl.TrimStart('/') : string.Empty); + } + if (endPoint is DnsEndPoint) + { + var dnsEndpoint = endPoint as DnsEndPoint; + return CreateHttpUrl(schema, dnsEndpoint.Host, dnsEndpoint.Port, rawUrl != null ? rawUrl.TrimStart('/') : string.Empty); + } + return null; + } + + public static string ToHttpUrl(this EndPoint endPoint, string schema, string formatString, params object[] args) + { + if (endPoint is IPEndPoint) + { + var ipEndPoint = endPoint as IPEndPoint; + return CreateHttpUrl(schema, ipEndPoint.Address.ToString(), ipEndPoint.Port, string.Format(formatString.TrimStart('/'), args)); + } + if (endPoint is DnsEndPoint) + { + var dnsEndpoint = endPoint as DnsEndPoint; + return CreateHttpUrl(schema, dnsEndpoint.Host, dnsEndpoint.Port, string.Format(formatString.TrimStart('/'), args)); + } + return null; + } + + private static string CreateHttpUrl(string schema, string host, int port, string path) + { + return $"{schema}://{host}:{port}/{path}"; + } + } +} diff --git a/src/EventStore.ClientAPI.NetCore/Transport.Http/IPEndpointExtensions.cs b/src/EventStore.ClientAPI.NetCore/Transport.Http/IPEndpointExtensions.cs deleted file mode 100644 index 67050a1..0000000 --- a/src/EventStore.ClientAPI.NetCore/Transport.Http/IPEndpointExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Net; - -namespace EventStore.ClientAPI.Transport.Http -{ - internal static class IPEndPointExtensions - { - public static string ToHttpUrl(this IPEndPoint endPoint, string rawUrl = null) - { - return string.Format("http://{0}:{1}/{2}", - endPoint.Address, - endPoint.Port, - rawUrl != null ? rawUrl.TrimStart('/') : string.Empty); - } - - public static string ToHttpUrl(this IPEndPoint endPoint, string formatString, params object[] args) - { - return string.Format("http://{0}:{1}/{2}", - endPoint.Address, - endPoint.Port, - string.Format(formatString.TrimStart('/'), args)); - } - } -} diff --git a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs index c8862d1..19d3223 100644 --- a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs +++ b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs @@ -23,24 +23,24 @@ public UsersClient(ILogger log, TimeSpan operationTimeout) _client = new HttpAsyncClient(_operationTimeout); } - public Task Enable(IPEndPoint endPoint, string login, UserCredentials userCredentials = null) + public Task Enable(EndPoint endPoint, string login, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/users/{0}/command/enable", login), string.Empty, userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/users/{0}/command/enable", login), string.Empty, userCredentials, HttpStatusCode.OK); } - public Task Disable(IPEndPoint endPoint, string login, UserCredentials userCredentials = null) + public Task Disable(EndPoint endPoint, string login, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/users/{0}/command/disable", login), string.Empty, userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/users/{0}/command/disable", login), string.Empty, userCredentials, HttpStatusCode.OK); } - public Task Delete(IPEndPoint endPoint, string login, UserCredentials userCredentials = null) + public Task Delete(EndPoint endPoint, string login, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendDelete(endPoint.ToHttpUrl("/users/{0}", login), userCredentials, HttpStatusCode.OK); + return SendDelete(endPoint.ToHttpUrl(httpSchema, "/users/{0}", login), userCredentials, HttpStatusCode.OK); } - public Task> ListAll(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task> ListAll(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/users/"), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/users/"), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -49,9 +49,9 @@ public Task> ListAll(IPEndPoint endPoint, UserCredentials user }); } - public Task GetCurrentUser(IPEndPoint endPoint, UserCredentials userCredentials = null) + public Task GetCurrentUser(EndPoint endPoint, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/users/$current"), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/users/$current"), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -60,9 +60,9 @@ public Task GetCurrentUser(IPEndPoint endPoint, UserCredentials use }); } - public Task GetUser(IPEndPoint endPoint, string login, UserCredentials userCredentials = null) + public Task GetUser(EndPoint endPoint, string login, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendGet(endPoint.ToHttpUrl("/users/{0}", login), userCredentials, HttpStatusCode.OK) + return SendGet(endPoint.ToHttpUrl(httpSchema, "/users/{0}", login), userCredentials, HttpStatusCode.OK) .ContinueWith(x => { if (x.IsFaulted) throw x.Exception; @@ -71,29 +71,29 @@ public Task GetUser(IPEndPoint endPoint, string login, UserCredenti }); } - public Task CreateUser(IPEndPoint endPoint, UserCreationInformation newUser, - UserCredentials userCredentials = null) + public Task CreateUser(EndPoint endPoint, UserCreationInformation newUser, + UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { var userJson = newUser.ToJson(); - return SendPost(endPoint.ToHttpUrl("/users/"), userJson, userCredentials, HttpStatusCode.Created); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/users/"), userJson, userCredentials, HttpStatusCode.Created); } - public Task UpdateUser(IPEndPoint endPoint, string login, UserUpdateInformation updatedUser, - UserCredentials userCredentials) + public Task UpdateUser(EndPoint endPoint, string login, UserUpdateInformation updatedUser, + UserCredentials userCredentials, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPut(endPoint.ToHttpUrl("/users/{0}", login), updatedUser.ToJson(), userCredentials, HttpStatusCode.OK); + return SendPut(endPoint.ToHttpUrl(httpSchema, "/users/{0}", login), updatedUser.ToJson(), userCredentials, HttpStatusCode.OK); } - public Task ChangePassword(IPEndPoint endPoint, string login, ChangePasswordDetails changePasswordDetails, - UserCredentials userCredentials) + public Task ChangePassword(EndPoint endPoint, string login, ChangePasswordDetails changePasswordDetails, + UserCredentials userCredentials, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/users/{0}/command/change-password", login), changePasswordDetails.ToJson(), userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/users/{0}/command/change-password", login), changePasswordDetails.ToJson(), userCredentials, HttpStatusCode.OK); } - public Task ResetPassword(IPEndPoint endPoint, string login, ResetPasswordDetails resetPasswordDetails, - UserCredentials userCredentials = null) + public Task ResetPassword(EndPoint endPoint, string login, ResetPasswordDetails resetPasswordDetails, + UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { - return SendPost(endPoint.ToHttpUrl("/users/{0}/command/reset-password", login), resetPasswordDetails.ToJson(), userCredentials, HttpStatusCode.OK); + return SendPost(endPoint.ToHttpUrl(httpSchema, "/users/{0}/command/reset-password", login), resetPasswordDetails.ToJson(), userCredentials, HttpStatusCode.OK); } private Task SendGet(string url, UserCredentials userCredentials, int expectedCode) diff --git a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersManager.cs b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersManager.cs index 020e3f5..24eed7c 100644 --- a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersManager.cs +++ b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersManager.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.SystemData; +using EventStore.ClientAPI.Transport.Http; namespace EventStore.ClientAPI.UserManagement { @@ -15,7 +16,8 @@ public class UsersManager { private readonly UsersClient _client; - private readonly IPEndPoint _httpEndPoint; + private readonly EndPoint _httpEndPoint; + private readonly string _httpSchema; /// /// Creates a new instance of . @@ -23,13 +25,14 @@ public class UsersManager /// An instance of to use for logging. /// HTTP endpoint of an Event Store server. /// - public UsersManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan operationTimeout) + public UsersManager(ILogger log, EndPoint httpEndPoint, TimeSpan operationTimeout, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { Ensure.NotNull(log, "log"); Ensure.NotNull(httpEndPoint, "httpEndPoint"); _client = new UsersClient(log, operationTimeout); _httpEndPoint = httpEndPoint; + _httpSchema = httpSchema; } /// From 176f9752dbbae9ff6d1564d4ff7aa29886735041 Mon Sep 17 00:00:00 2001 From: James Geall Date: Wed, 25 Oct 2017 14:28:14 +0300 Subject: [PATCH 18/44] Update TaskCompletionSource to use TaskCreationOptions.RunContinuationsAsynchronously --- .../ManualResetEventSlimExtensions.cs | 2 +- .../EventStorePersistentSubscription.cs | 2 +- .../Internal/EventStoreNodeConnection.cs | 74 +++++++++---------- .../Projections/ProjectionsClient.cs | 8 +- .../UserManagement/UsersClient.cs | 8 +- 5 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/ManualResetEventSlimExtensions.cs b/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/ManualResetEventSlimExtensions.cs index 76e4edf..b873939 100644 --- a/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/ManualResetEventSlimExtensions.cs +++ b/src/EventStore.ClientAPI.NetCore/Common/Utils/Threading/ManualResetEventSlimExtensions.cs @@ -12,7 +12,7 @@ public static Task AsTask(this ManualResetEventSlim resetEvent) public static Task AsTask(this ManualResetEventSlim resetEvent, int timeoutMs) { - TaskCompletionSource tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); RegisteredWaitHandle registration = ThreadPool.RegisterWaitForSingleObject(resetEvent.WaitHandle, (state, timedOut) => { diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs index 40faca0..001e1e8 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs @@ -30,7 +30,7 @@ internal override Task StartSubscription( Func onEventAppeared, Action onSubscriptionDropped, ConnectionSettings settings) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _handler.EnqueueMessage(new StartPersistentSubscriptionMessage(source, subscriptionId, streamId, bufferSize, userCredentials, onEventAppeared, onSubscriptionDropped, settings.MaxRetries, settings.OperationTimeout)); diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs index 1f5d0dc..46870bf 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs @@ -60,7 +60,7 @@ internal EventStoreNodeConnection(ConnectionSettings settings, ClusterSettings c public Task ConnectAsync() { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _handler.EnqueueMessage(new StartConnectionMessage(source, _endPointDiscoverer)); return source.Task; } @@ -84,7 +84,7 @@ public Task DeleteStreamAsync(string stream, long expectedVersion, { Ensure.NotNullOrEmpty(stream, "stream"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new DeleteStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, hardDelete, userCredentials)); return source.Task; @@ -112,7 +112,7 @@ public Task AppendToStreamAsync(string stream, long expectedVersion Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNull(events, "events"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new AppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, events, userCredentials)); return source.Task; @@ -126,7 +126,7 @@ public Task ConditionalAppendToStreamAsync(string stream Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNull(events, "events"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new ConditionalAppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, events, userCredentials)); return source.Task; @@ -137,7 +137,7 @@ public Task StartTransactionAsync(string stream, long exp { Ensure.NotNullOrEmpty(stream, "stream"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new StartTransactionOperation(Settings.Log, source, Settings.RequireMaster, stream, expectedVersion, this, userCredentials)); return source.Task; @@ -155,7 +155,7 @@ Task IEventStoreTransactionConnection.TransactionalWriteAsync(EventStoreTransact Ensure.NotNull(transaction, "transaction"); Ensure.NotNull(events, "events"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new TransactionalWriteOperation(Settings.Log, source, Settings.RequireMaster, transaction.TransactionId, events, userCredentials)); return source.Task; @@ -166,7 +166,7 @@ Task IEventStoreTransactionConnection.CommitTransactionAsync(EventS { Ensure.NotNull(transaction, "transaction"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new CommitTransactionOperation(Settings.Log, source, Settings.RequireMaster, transaction.TransactionId, userCredentials)); return source.Task; @@ -177,7 +177,7 @@ public Task ReadEventAsync(string stream, long eventNumber, boo { Ensure.NotNullOrEmpty(stream, "stream"); if (eventNumber < -1) throw new ArgumentOutOfRangeException(nameof(eventNumber)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadEventOperation(Settings.Log, source, stream, eventNumber, resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); @@ -190,7 +190,7 @@ public Task ReadStreamEventsForwardAsync(string stream, long Ensure.Nonnegative(start, "start"); Ensure.Positive(count, "count"); if(count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsForwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); @@ -202,7 +202,7 @@ public Task ReadStreamEventsBackwardAsync(string stream, long Ensure.NotNullOrEmpty(stream, "stream"); Ensure.Positive(count, "count"); if (count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsBackwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); @@ -213,7 +213,7 @@ public Task ReadAllEventsForwardAsync(Position position, int max { Ensure.Positive(maxCount, "maxCount"); if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsForwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); @@ -224,7 +224,7 @@ public Task ReadAllEventsBackwardAsync(Position position, int ma { Ensure.Positive(maxCount, "maxCount"); if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsBackwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); EnqueueOperation(operation); @@ -250,7 +250,7 @@ public Task SubscribeToStreamAsync( Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNull(eventAppeared, "eventAppeared"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _handler.EnqueueMessage(new StartSubscriptionMessage(source, stream, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, Settings.MaxRetries, Settings.OperationTimeout)); @@ -302,7 +302,7 @@ public Task SubscribeToAllAsync( { Ensure.NotNull(eventAppeared, "eventAppeared"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _handler.EnqueueMessage(new StartSubscriptionMessage(source, string.Empty, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, Settings.MaxRetries, Settings.OperationTimeout)); @@ -407,7 +407,7 @@ public Task CreatePersistentSubscriptionAsync(string stream, string groupName, P Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new CreatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); return source.Task; } @@ -417,40 +417,40 @@ public Task UpdatePersistentSubscriptionAsync(string stream, string groupName, P Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new UpdatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); return source.Task; } -/* + /* - public Task CreatePersistentSubscriptionForAllAsync(string groupName, PersistentSubscriptionSettings settings, UserCredentials userCredentials = null) - { - Ensure.NotNullOrEmpty(groupName, "groupName"); - Ensure.NotNull(settings, "settings"); - var source = new TaskCompletionSource(); - EnqueueOperation(new CreatePersistentSubscriptionOperation(_settings.Log, source, SystemStreams.AllStream, groupName, settings, userCredentials)); - return source.Task; - } + public Task CreatePersistentSubscriptionForAllAsync(string groupName, PersistentSubscriptionSettings settings, UserCredentials userCredentials = null) + { + Ensure.NotNullOrEmpty(groupName, "groupName"); + Ensure.NotNull(settings, "settings"); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + EnqueueOperation(new CreatePersistentSubscriptionOperation(_settings.Log, source, SystemStreams.AllStream, groupName, settings, userCredentials)); + return source.Task; + } -*/ + */ public Task DeletePersistentSubscriptionAsync(string stream, string groupName, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EnqueueOperation(new DeletePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, userCredentials)); return source.Task; } -/* + /* - public Task DeletePersistentSubscriptionForAllAsync(string groupName, UserCredentials userCredentials = null) - { - Ensure.NotNullOrEmpty(groupName, "groupName"); - var source = new TaskCompletionSource(); - EnqueueOperation(new DeletePersistentSubscriptionOperation(_settings.Log, source, SystemStreams.AllStream, groupName, userCredentials)); - return source.Task; - } + public Task DeletePersistentSubscriptionForAllAsync(string groupName, UserCredentials userCredentials = null) + { + Ensure.NotNullOrEmpty(groupName, "groupName"); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + EnqueueOperation(new DeletePersistentSubscriptionOperation(_settings.Log, source, SystemStreams.AllStream, groupName, userCredentials)); + return source.Task; + } -*/ + */ public Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, StreamMetadata metadata, UserCredentials userCredentials = null) { @@ -463,7 +463,7 @@ public Task SetStreamMetadataAsync(string stream, long expectedMeta if (SystemStreams.IsMetastream(stream)) throw new ArgumentException(string.Format("Setting metadata for metastream '{0}' is not supported.", stream), nameof(stream)); - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var metaevent = new EventData(Guid.NewGuid(), SystemEventTypes.StreamMetadata, true, metadata ?? Empty.ByteArray, null); EnqueueOperation(new AppendToStreamOperation(Settings.Log, diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs index 7c2e9eb..80e1887 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs @@ -154,7 +154,7 @@ public Task Delete(EndPoint endPoint, string name, bool deleteEmittedStreams, Us private Task SendGet(string url, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Get(url, userCredentials, response => @@ -176,7 +176,7 @@ private Task SendGet(string url, UserCredentials userCredentials, int ex private Task SendDelete(string url, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Delete(url, userCredentials, response => @@ -198,7 +198,7 @@ private Task SendDelete(string url, UserCredentials userCredentials, int private Task SendPut(string url, string content, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Put(url, content, "application/json", @@ -222,7 +222,7 @@ private Task SendPut(string url, string content, UserCredentials userCredentials private Task SendPost(string url, string content, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Post(url, content, "application/json", diff --git a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs index 19d3223..a1ab9ce 100644 --- a/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs +++ b/src/EventStore.ClientAPI.NetCore/UserManagement/UsersClient.cs @@ -98,7 +98,7 @@ public Task ResetPassword(EndPoint endPoint, string login, ResetPasswordDetails private Task SendGet(string url, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Get(url, userCredentials, response => @@ -120,7 +120,7 @@ private Task SendGet(string url, UserCredentials userCredentials, int ex private Task SendDelete(string url, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Delete(url, userCredentials, response => @@ -142,7 +142,7 @@ private Task SendDelete(string url, UserCredentials userCredentials, int private Task SendPut(string url, string content, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Put(url, content, "application/json", @@ -166,7 +166,7 @@ private Task SendPut(string url, string content, UserCredentials userCredentials private Task SendPost(string url, string content, UserCredentials userCredentials, int expectedCode) { - var source = new TaskCompletionSource(); + var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _client.Post(url, content, "application/json", From 1e4a77158b187edc68e0b85be57e578d04ef9a39 Mon Sep 17 00:00:00 2001 From: James Geall Date: Wed, 25 Oct 2017 14:38:28 +0300 Subject: [PATCH 19/44] Allow changing of custom metadata properties in the client StreamMetadataBuilder --- .../StreamMetadataBuilder.cs | 83 +++++++++---------- 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs b/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs index 02b2947..d224e38 100644 --- a/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using EventStore.ClientAPI.Common.Utils; using Newtonsoft.Json.Linq; @@ -19,9 +20,16 @@ public class StreamMetadataBuilder private string[] _aclDelete; private string[] _aclMetaRead; private string[] _aclMetaWrite; - private readonly IDictionary _customMetadata; + /// + /// All existing custom property keys. + /// + /// + /// Returns a copy of the key list so it's safe to enumerate whilst removing custom properties. + /// + public IEnumerable CustomPropertyKeys => _customMetadata.Keys.ToList(); + internal StreamMetadataBuilder( long? maxCount = null, TimeSpan? maxAge = null, @@ -45,7 +53,6 @@ internal StreamMetadataBuilder( _aclMetaWrite = aclMetaWrite; _customMetadata = customMetadata == null ? new Dictionary() : new Dictionary(customMetadata); } - /// /// Builds a from a . /// @@ -55,11 +62,11 @@ public static implicit operator StreamMetadata(StreamMetadataBuilder builder) { return builder.Build(); } - /// /// Builds a from a . /// - public StreamMetadata Build() { + public StreamMetadata Build() + { var acl = this._aclRead == null && this._aclWrite == null && this._aclDelete == null @@ -69,7 +76,6 @@ public StreamMetadata Build() { : new StreamAcl(this._aclRead, this._aclWrite, this._aclDelete, this._aclMetaRead, this._aclMetaWrite); return new StreamMetadata(this._maxCount, this._maxAge, this._truncateBefore, this._cacheControl, acl, this._customMetadata); } - /// /// Sets the maximum number of events allowed in the stream. /// @@ -81,7 +87,6 @@ public StreamMetadataBuilder SetMaxCount(long maxCount) _maxCount = maxCount; return this; } - /// /// Sets the maximum age of events allowed in the stream. /// @@ -93,7 +98,6 @@ public StreamMetadataBuilder SetMaxAge(TimeSpan maxAge) _maxAge = maxAge; return this; } - /// /// Sets the event number from which previous events can be scavenged. /// @@ -105,7 +109,6 @@ public StreamMetadataBuilder SetTruncateBefore(long truncateBefore) _truncateBefore = truncateBefore; return this; } - /// /// Sets the amount of time for which the stream head is cachable. /// @@ -117,7 +120,6 @@ public StreamMetadataBuilder SetCacheControl(TimeSpan cacheControl) _cacheControl = cacheControl; return this; } - /// /// Sets a single role name with read permission for the stream. /// @@ -128,7 +130,6 @@ public StreamMetadataBuilder SetReadRole(string role) _aclRead = role == null ? null : new[] { role }; return this; } - /// /// Sets role names with read permission for the stream. /// @@ -139,7 +140,6 @@ public StreamMetadataBuilder SetReadRoles(string[] roles) _aclRead = roles; return this; } - /// /// Sets a single role name with write permission for the stream. /// @@ -150,7 +150,6 @@ public StreamMetadataBuilder SetWriteRole(string role) _aclWrite = role == null ? null : new[] { role }; return this; } - /// /// Sets role names with write permission for the stream. /// @@ -161,7 +160,6 @@ public StreamMetadataBuilder SetWriteRoles(string[] roles) _aclWrite = roles; return this; } - /// /// Sets a single role name with delete permission for the stream. /// @@ -172,7 +170,6 @@ public StreamMetadataBuilder SetDeleteRole(string role) _aclDelete = role == null ? null : new[] { role }; return this; } - /// /// Sets role names with delete permission for the stream. /// @@ -183,7 +180,6 @@ public StreamMetadataBuilder SetDeleteRoles(string[] roles) _aclDelete = roles; return this; } - /// /// Sets a single role name with metadata read permission for the stream. /// @@ -194,7 +190,6 @@ public StreamMetadataBuilder SetMetadataReadRole(string role) _aclMetaRead = role == null ? null : new[] { role }; return this; } - /// /// Sets role names with metadata read permission for the stream. /// @@ -205,7 +200,6 @@ public StreamMetadataBuilder SetMetadataReadRoles(string[] roles) _aclMetaRead = roles; return this; } - /// /// Sets a single role name with metadata write permission for the stream. /// @@ -216,7 +210,6 @@ public StreamMetadataBuilder SetMetadataWriteRole(string role) _aclMetaWrite = role == null ? null : new[] { role }; return this; } - /// /// Sets role names with metadata write permission for the stream. /// @@ -227,7 +220,6 @@ public StreamMetadataBuilder SetMetadataWriteRoles(string[] roles) _aclMetaWrite = roles; return this; } - /// /// Sets a custom metadata property. /// @@ -236,10 +228,9 @@ public StreamMetadataBuilder SetMetadataWriteRoles(string[] roles) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, string value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -248,10 +239,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, string value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, int value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -260,10 +250,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, int value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, int? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -272,10 +261,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, int? value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, long value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -284,10 +272,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, long value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, long? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -296,10 +283,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, long? value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, float value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -308,10 +294,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, float value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, float? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -320,10 +305,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, float? value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, double value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -332,10 +316,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, double value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, double? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -344,10 +327,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, double? value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, decimal value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -356,10 +338,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, decimal value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, decimal? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -368,10 +349,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, decimal? value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, bool value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property. /// @@ -380,10 +360,9 @@ public StreamMetadataBuilder SetCustomProperty(string key, bool value) /// The builder. public StreamMetadataBuilder SetCustomProperty(string key, bool? value) { - _customMetadata.Add(key, value); + _customMetadata[key] = value; return this; } - /// /// Sets a custom metadata property to a string of raw JSON. /// @@ -392,8 +371,20 @@ public StreamMetadataBuilder SetCustomProperty(string key, bool? value) /// The builder. public StreamMetadataBuilder SetCustomPropertyWithValueAsRawJsonString(string key, string rawJson) { - _customMetadata.Add(key, JToken.Parse(rawJson)); + _customMetadata[key] = JToken.Parse(rawJson); return this; } + + /// + /// Removes a custom property. + /// + /// The key. + /// The builder. + public StreamMetadataBuilder RemoveCustomProperty(string key) + { + _customMetadata.Remove(key); + return this; + } + } } \ No newline at end of file From ae32f3143fdf751cf52fcaf74001cb47127cbb7c Mon Sep 17 00:00:00 2001 From: James Geall Date: Wed, 25 Oct 2017 15:05:27 +0300 Subject: [PATCH 20/44] Updated eventstore server versions --- scripts/installandruneventstore.ps1 | 2 +- wercker.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/installandruneventstore.ps1 b/scripts/installandruneventstore.ps1 index 5d40be6..7ede819 100644 --- a/scripts/installandruneventstore.ps1 +++ b/scripts/installandruneventstore.ps1 @@ -1,3 +1,3 @@ -(New-Object Net.WebClient).DownloadFile('http://download.geteventstore.com/binaries/EventStore-OSS-Win-v4.0.2.zip','c:\tools\eventstore.zip') +(New-Object Net.WebClient).DownloadFile('https://eventstore.org/downloads/EventStore-OSS-Win-v4.0.3.zip','c:\tools\eventstore.zip') 7z e C:\tools\eventstore.zip -oC:\tools\EventStore start-process -NoNewWindow "C:\tools\EventStore\EventStore.ClusterNode.exe" "--memdb --run-projections ALL" \ No newline at end of file diff --git a/wercker.yml b/wercker.yml index ce203f9..2709a44 100644 --- a/wercker.yml +++ b/wercker.yml @@ -17,9 +17,9 @@ build: name: install and run eventstore code: | apt-get install wget tzdata curl iproute2 -y - wget http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v4.0.0.tar.gz - tar xfv EventStore-OSS-Ubuntu-14.04-v4.0.0.tar.gz - pushd ./EventStore-OSS-Ubuntu-14.04-v4.0.0 + wget https://eventstore.org/downloads/EventStore-OSS-Ubuntu-14.04-v4.0.3.tar.gz + tar xfv EventStore-OSS-Ubuntu-14.04-v4.0.3.tar.gz + pushd ./EventStore-OSS-Ubuntu-14.04-v4.0.3 nohup ./eventstored --run-projections All --mem-db --log ~/logs & popd From 712ea517c09dabbcc1fb3033f9c9cee9b8344580 Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 26 Oct 2017 10:09:03 +0300 Subject: [PATCH 21/44] Version bump for release 4.0.3 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 14b2919..19770c0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 4.0.2.{build} +version: 4.0.3.{build} image: Visual Studio 2017 From 28755fa935138a65c800f9f5e350cfa311a17846 Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 26 Oct 2017 10:41:53 +0300 Subject: [PATCH 22/44] Updated unclear documentation on EventStoreAllCatchUpSubscription.Stop(TimeSpan timeout) --- .../EventStoreCatchUpSubscription.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs index 351f655..f701a80 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs @@ -136,9 +136,9 @@ internal Task StartAsync() } /// - /// Attempts to stop the subscription. + /// Attempts to stop the subscription blocking for completion of stop. /// - /// The amount of time within which the subscription should stop. + /// The maximum amount of time which the current thread will block waiting for the subscription to stop before throwing a TimeoutException. /// Thrown if the subscription fails to stop within it's timeout period. public void Stop(TimeSpan timeout) { From fe4cc4c24e41536fe2cc279a0d9991314aa2b8d8 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 11:41:24 +0200 Subject: [PATCH 23/44] fixed whiile updating system projections query, wasn't picking right type --- .../Projections/ProjectionsClient.cs | 7 +++++++ .../Projections/ProjectionsManager.cs | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs index 80e1887..e87ac51 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsClient.cs @@ -147,6 +147,13 @@ public Task UpdateQuery(EndPoint endPoint, string name, string query, UserCreden return SendPut(endPoint.ToHttpUrl(httpSchema, "/projection/{0}/query?type=JS", name), query, userCredentials, HttpStatusCode.OK); } + public Task UpdateQuery(EndPoint endPoint, string name, string query, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA, bool? emitEnabled = null) + { + var emit = emitEnabled.HasValue ? (emitEnabled.Value ? "1" : "0") : string.Empty; + var url = emitEnabled.HasValue ? "/projection/{0}/query?emit={1}" : "/projection/{0}/query"; + return SendPut(endPoint.ToHttpUrl(httpSchema, url, name, emit), query, userCredentials, HttpStatusCode.OK); + } + public Task Delete(EndPoint endPoint, string name, bool deleteEmittedStreams, UserCredentials userCredentials = null, string httpSchema = EndpointExtensions.HTTP_SCHEMA) { return SendDelete(endPoint.ToHttpUrl(httpSchema, "/projection/{0}?deleteEmittedStreams={1}", name, deleteEmittedStreams), userCredentials, HttpStatusCode.OK); diff --git a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs index 582a79e..cb78f84 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/ProjectionsManager.cs @@ -286,6 +286,21 @@ public Task UpdateQueryAsync(string name, string query, UserCredentials userCred return _client.UpdateQuery(_httpEndPoint, name, query, userCredentials, _httpSchema); } + /// + /// Asynchronously updates the definition of a query. + /// + /// The name of the query. + /// The JavaScript source code of the query. + /// Credentials for the operation. + /// Allow projection to send events to other streams + public Task UpdateQueryAsync(string name, string query, bool? emitEnabled = null, UserCredentials userCredentials = null) + { + Ensure.NotNullOrEmpty(name, "name"); + Ensure.NotNullOrEmpty(query, "query"); + + return _client.UpdateQuery(_httpEndPoint, name, query, userCredentials, _httpSchema, emitEnabled); + } + /// /// Asynchronously deletes a projection /// From 9495aeab2010ff65340175dd483afeb33b00069d Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 16:26:12 +0200 Subject: [PATCH 24/44] Add support for retry count to persistent subscriptions --- ...onnectToPersistentSubscriptionOperation.cs | 6 +- .../ClientOperations/SubscriptionOperation.cs | 23 +++--- .../VolatileSubscriptionOperation.cs | 2 +- .../EventStorePersistentSubscription.cs | 42 +++++++++- .../EventStorePersistentSubscriptionBase.cs | 26 +++--- .../IEventStoreConnection.cs | 4 +- .../IEventStoreConnectionExtensions.cs | 79 ++++++++++++++++++- .../Internal/EventStoreNodeConnection.cs | 4 +- .../Internal/Messages.cs | 4 +- .../Messages/ClientMessage.cs | 16 ++-- .../ResolvedEvent.cs | 10 ++- .../FakeEventStoreConnection.cs | 22 ++++-- ...ersistent_subscription_with_permissions.cs | 2 +- ...ent_subscription_with_permissions_async.cs | 2 +- ...to_persistent_subscription_with_retries.cs | 65 +++++++++++++++ 15 files changed, 251 insertions(+), 56 deletions(-) create mode 100644 test/EventStore.ClientAPI.NetCore.Tests/connect_to_persistent_subscription_with_retries.cs diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs index 1a6008d..dd4ea08 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/ConnectToPersistentSubscriptionOperation.cs @@ -9,13 +9,13 @@ namespace EventStore.ClientAPI.ClientOperations { - internal class ConnectToPersistentSubscriptionOperation : SubscriptionOperation, IConnectToPersistentSubscriptions + internal class ConnectToPersistentSubscriptionOperation : SubscriptionOperation, IConnectToPersistentSubscriptions { private readonly string _groupName; private readonly int _bufferSize; private string _subscriptionId; - public ConnectToPersistentSubscriptionOperation(ILogger log, TaskCompletionSource source, string groupName, int bufferSize, string streamId, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) + public ConnectToPersistentSubscriptionOperation(ILogger log, TaskCompletionSource source, string groupName, int bufferSize, string streamId, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) : base(log, source, streamId, false, userCredentials, eventAppeared, subscriptionDropped, verboseLogging, getConnection) { _groupName = groupName; @@ -46,7 +46,7 @@ protected override bool InspectPackage(TcpPackage package, out InspectionResult if (package.Command == TcpCommand.PersistentSubscriptionStreamEventAppeared) { var dto = package.Data.Deserialize(); - EventAppeared(new ResolvedEvent(dto.Event)); + EventAppeared(new PersistentSubscriptionResolvedEvent(new ResolvedEvent(dto.Event), dto.RetryCount)); result = new InspectionResult(InspectionDecision.DoNothing, "StreamEventAppeared"); return true; } diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs index 38bc5cd..2e6ea5b 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/SubscriptionOperation.cs @@ -10,14 +10,21 @@ namespace EventStore.ClientAPI.ClientOperations { - internal abstract class SubscriptionOperation : ISubscriptionOperation where T : EventStoreSubscription + internal interface IResolvedEvent + { + string OriginalStreamId{ get; } + long OriginalEventNumber { get; } + RecordedEvent OriginalEvent { get; } + Position? OriginalPosition { get; } + } + internal abstract class SubscriptionOperation : ISubscriptionOperation where T : EventStoreSubscription where TE: IResolvedEvent { private readonly ILogger _log; private readonly TaskCompletionSource _source; protected readonly string _streamId; protected readonly bool _resolveLinkTos; protected readonly UserCredentials _userCredentials; - protected readonly Func _eventAppeared; + protected readonly Func _eventAppeared; private readonly Action _subscriptionDropped; private readonly bool _verboseLogging; protected readonly Func _getConnection; @@ -33,7 +40,7 @@ protected SubscriptionOperation(ILogger log, string streamId, bool resolveLinkTos, UserCredentials userCredentials, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) @@ -84,7 +91,6 @@ private TcpPackage CreateUnsubscriptionPackage() } protected abstract bool InspectPackage(TcpPackage package, out InspectionResult result); - public InspectionResult InspectPackage(TcpPackage package) { try @@ -97,13 +103,6 @@ public InspectionResult InspectPackage(TcpPackage package) switch (package.Command) { - case TcpCommand.StreamEventAppeared: - { - var dto = package.Data.Deserialize(); - EventAppeared(new ResolvedEvent(dto.Event)); - return new InspectionResult(InspectionDecision.DoNothing, "StreamEventAppeared"); - } - case TcpCommand.SubscriptionDropped: { var dto = package.Data.Deserialize(); @@ -240,7 +239,7 @@ protected void ConfirmSubscription(long lastCommitPosition, long? lastEventNumbe protected abstract T CreateSubscriptionObject(long lastCommitPosition, long? lastEventNumber); - protected void EventAppeared(ResolvedEvent e) + protected void EventAppeared(TE e) { if (_unsubscribed != 0) return; diff --git a/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs b/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs index 179e620..361733d 100644 --- a/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs +++ b/src/EventStore.ClientAPI.NetCore/ClientOperations/VolatileSubscriptionOperation.cs @@ -7,7 +7,7 @@ namespace EventStore.ClientAPI.ClientOperations { - internal class VolatileSubscriptionOperation : SubscriptionOperation + internal class VolatileSubscriptionOperation : SubscriptionOperation { public VolatileSubscriptionOperation(ILogger log, TaskCompletionSource source, string streamId, bool resolveLinkTos, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, bool verboseLogging, Func getConnection) : base(log, source, streamId, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, verboseLogging, getConnection) diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs index 001e1e8..701c0e2 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscription.cs @@ -1,10 +1,48 @@ using System; using System.Threading.Tasks; +using EventStore.ClientAPI.ClientOperations; using EventStore.ClientAPI.Internal; using EventStore.ClientAPI.SystemData; namespace EventStore.ClientAPI { + internal struct PersistentSubscriptionResolvedEvent : IResolvedEvent + { + /// + /// + /// + public readonly int? RetryCount; + /// + /// + /// + public readonly ResolvedEvent Event; + + /// + /// + /// + /// + /// + internal PersistentSubscriptionResolvedEvent(ResolvedEvent @event, int? retryCount) + { + Event = @event; + RetryCount = retryCount; + } + + string IResolvedEvent.OriginalStreamId => Event.OriginalStreamId; + + long IResolvedEvent.OriginalEventNumber => Event.OriginalEventNumber; + + RecordedEvent IResolvedEvent.OriginalEvent => Event.OriginalEvent; + + Position? IResolvedEvent.OriginalPosition => Event.OriginalPosition; + + /// + /// + /// + /// + /// + public static implicit operator ResolvedEvent(PersistentSubscriptionResolvedEvent x) => x.Event; + } /// /// Represents a persistent subscription connection. /// @@ -14,7 +52,7 @@ public class EventStorePersistentSubscription : EventStorePersistentSubscription internal EventStorePersistentSubscription( string subscriptionId, string streamId, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped, UserCredentials userCredentials, ILogger log, bool verboseLogging, ConnectionSettings settings, EventStoreConnectionLogicHandler handler, int bufferSize = 10, bool autoAck = true) @@ -27,7 +65,7 @@ internal EventStorePersistentSubscription( internal override Task StartSubscription( string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, - Func onEventAppeared, + Func onEventAppeared, Action onSubscriptionDropped, ConnectionSettings settings) { var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs index 9297793..b97640c 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs @@ -21,7 +21,7 @@ public abstract class EventStorePersistentSubscriptionBase private readonly string _subscriptionId; private readonly string _streamId; - private readonly Func _eventAppeared; + private readonly Func _eventAppeared; private readonly Action _subscriptionDropped; private readonly UserCredentials _userCredentials; private readonly ILogger _log; @@ -30,7 +30,7 @@ public abstract class EventStorePersistentSubscriptionBase private readonly bool _autoAck; private PersistentEventStoreSubscription _subscription; - private readonly ConcurrentQueue _queue = new ConcurrentQueue(); + private readonly ConcurrentQueue _queue = new ConcurrentQueue(); private int _isProcessing; private DropData _dropData; @@ -40,7 +40,7 @@ public abstract class EventStorePersistentSubscriptionBase internal EventStorePersistentSubscriptionBase(string subscriptionId, string streamId, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped, UserCredentials userCredentials, ILogger log, @@ -77,7 +77,7 @@ internal Task Start() internal abstract Task StartSubscription( string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, - Func onEventAppeared, + Func onEventAppeared, Action onSubscriptionDropped, ConnectionSettings settings); @@ -168,7 +168,7 @@ private void EnqueueSubscriptionDropNotification(SubscriptionDropReason reason, var dropData = new DropData(reason, error); if (Interlocked.CompareExchange(ref _dropData, dropData, null) == null) { - Enqueue(DropSubscriptionEvent); + Enqueue(new PersistentSubscriptionResolvedEvent(DropSubscriptionEvent, null)); } } @@ -177,13 +177,13 @@ private void OnSubscriptionDropped(EventStoreSubscription subscription, Subscrip EnqueueSubscriptionDropNotification(reason, exception); } - private Task OnEventAppeared(EventStoreSubscription subscription, ResolvedEvent resolvedEvent) + private Task OnEventAppeared(EventStoreSubscription subscription, PersistentSubscriptionResolvedEvent resolvedEvent) { Enqueue(resolvedEvent); return Task.CompletedTask; } - private void Enqueue(ResolvedEvent resolvedEvent) + private void Enqueue(PersistentSubscriptionResolvedEvent resolvedEvent) { _queue.Enqueue(resolvedEvent); if (Interlocked.CompareExchange(ref _isProcessing, 1, 0) == 0) @@ -200,11 +200,11 @@ private async void ProcessQueue() Thread.Sleep(1); } else - { - ResolvedEvent e; + { + PersistentSubscriptionResolvedEvent e; while (_queue.TryDequeue(out e)) { - if (e.Equals(DropSubscriptionEvent)) // drop subscription artificial ResolvedEvent + if (e.Event.Equals(DropSubscriptionEvent)) // drop subscription artificial ResolvedEvent { if (_dropData == null) throw new Exception("Drop reason not specified."); DropSubscription(_dropData.Reason, _dropData.Error); @@ -217,13 +217,13 @@ private async void ProcessQueue() } try { - await _eventAppeared(this, e).ConfigureAwait(false); + await _eventAppeared(this, e, e.RetryCount).ConfigureAwait(false); if (_autoAck) - _subscription.NotifyEventsProcessed(new[] { e.OriginalEvent.EventId }); + _subscription.NotifyEventsProcessed(new[] { e.Event.OriginalEvent.EventId }); if (_verbose) _log.Debug("Persistent Subscription to {0}: processed event ({1}, {2}, {3} @ {4}).", _streamId, - e.OriginalEvent.EventStreamId, e.OriginalEvent.EventNumber, e.OriginalEvent.EventType, e.OriginalEventNumber); + e.Event.OriginalEvent.EventStreamId, e.Event.OriginalEvent.EventNumber, e.Event.OriginalEvent.EventType, e.Event.OriginalEventNumber); } catch (Exception exc) { diff --git a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs index e191a90..f4e8db9 100644 --- a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs @@ -357,7 +357,7 @@ Task SubscribeToAllAsync( EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( string stream, string groupName, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -384,7 +384,7 @@ EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( Task ConnectToPersistentSubscriptionAsync( string stream, string groupName, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, diff --git a/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs b/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs index f9dce42..af5f306 100644 --- a/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs +++ b/src/EventStore.ClientAPI.NetCore/IEventStoreConnectionExtensions.cs @@ -16,7 +16,7 @@ private static Func ToTask(Action eventAppeared(subscription, e); return Task.CompletedTask; }; - + /// /// Asynchronously subscribes to a single event stream. New events /// written to the stream while the subscription is active will be @@ -214,7 +214,44 @@ public static EventStorePersistentSubscriptionBase ConnectToPersistentSubscripti ); /// - /// Asynchronously subscribes to a persistent subscription(competing consumer) on event store + /// Subscribes to a persistent subscription(competing consumer) on event store + /// + /// The connection to subscribe to + /// The subscription group to connect to + /// The stream to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The buffer size to use for the persistent subscription + /// Whether the subscription should automatically acknowledge messages processed. + /// If not set the receiver is required to explicitly acknowledge messages through the subscription. + /// This will connect you to a persistent subscription group for a stream. The subscription group + /// must first be created with CreatePersistentSubscriptionAsync many connections + /// can connect to the same group and they will be treated as competing consumers within the group. + /// If one connection dies work will be balanced across the rest of the consumers in the group. If + /// you attempt to connect to a group that does not exist you will be given an exception. + /// + /// An representing the subscription + public static EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( + this IEventStoreConnection target, + string stream, + string groupName, + Func eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int bufferSize = 10, + bool autoAck = true) => + target.ConnectToPersistentSubscription( + stream, + groupName, + (s,e, i) => eventAppeared(s,e), + subscriptionDropped, + userCredentials, + bufferSize, + autoAck + ); + /// + /// Subscribes to a persistent subscription(competing consumer) on event store /// /// The connection to subscribe to /// The subscription group to connect to @@ -251,6 +288,44 @@ public static Task ConnectToPersistentSubs autoAck ); + /// + /// Subscribes to a persistent subscription(competing consumer) on event store + /// + /// The connection to subscribe to + /// The subscription group to connect to + /// The stream to subscribe to + /// An action invoked when a new event is received over the subscription + /// An action invoked if the subscription is dropped + /// User credentials to use for the operation + /// The buffer size to use for the persistent subscription + /// Whether the subscription should automatically acknowledge messages processed. + /// If not set the receiver is required to explicitly acknowledge messages through the subscription. + /// This will connect you to a persistent subscription group for a stream. The subscription group + /// must first be created with CreatePersistentSubscriptionAsync many connections + /// can connect to the same group and they will be treated as competing consumers within the group. + /// If one connection dies work will be balanced across the rest of the consumers in the group. If + /// you attempt to connect to a group that does not exist you will be given an exception. + /// + /// An representing the subscription + public static Task ConnectToPersistentSubscriptionAsync( + this IEventStoreConnection target, + string stream, + string groupName, + Func eventAppeared, + Action subscriptionDropped = null, + UserCredentials userCredentials = null, + int bufferSize = 10, + bool autoAck = true) => + target.ConnectToPersistentSubscriptionAsync( + stream, + groupName, + (s,e, i) => eventAppeared(s,e), + subscriptionDropped, + userCredentials, + bufferSize, + autoAck + ); + /// /// Subscribes to all events. Existing events from lastCheckpoint /// onwards are read from the Event Store and presented to the user of diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs index 46870bf..4ebd527 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs @@ -345,7 +345,7 @@ public EventStoreAllCatchUpSubscription SubscribeToAllFrom( public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( string stream, string groupName, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, @@ -366,7 +366,7 @@ public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( public Task ConnectToPersistentSubscriptionAsync( string stream, string groupName, - Func eventAppeared, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, diff --git a/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs b/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs index 51f52e4..f42151b 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/Messages.cs @@ -136,13 +136,13 @@ internal class StartPersistentSubscriptionMessage : Message public readonly string StreamId; public readonly int BufferSize; public readonly UserCredentials UserCredentials; - public readonly Func EventAppeared; + public readonly Func EventAppeared; public readonly Action SubscriptionDropped; public readonly int MaxRetries; public readonly TimeSpan Timeout; - public StartPersistentSubscriptionMessage(TaskCompletionSource source, string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, int maxRetries, TimeSpan timeout) + public StartPersistentSubscriptionMessage(TaskCompletionSource source, string subscriptionId, string streamId, int bufferSize, UserCredentials userCredentials, Func eventAppeared, Action subscriptionDropped, int maxRetries, TimeSpan timeout) { Ensure.NotNull(source, "source"); Ensure.NotNull(eventAppeared, "eventAppeared"); diff --git a/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs b/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs index fdf253f..8740549 100644 --- a/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs +++ b/src/EventStore.ClientAPI.NetCore/Messages/ClientMessage.cs @@ -1037,12 +1037,16 @@ public partial class PersistentSubscriptionStreamEventAppeared [ProtoMember(1, IsRequired = true, Name = @"event", DataFormat = DataFormat.Default)] public readonly ResolvedIndexedEvent Event; - private PersistentSubscriptionStreamEventAppeared() { } - - public PersistentSubscriptionStreamEventAppeared(ResolvedIndexedEvent @event) - { - Event = @event; - } + [ProtoMember(2, IsRequired = false, Name=@"retryCount", DataFormat = DataFormat.TwosComplement)] + public readonly int? RetryCount; + + private PersistentSubscriptionStreamEventAppeared() {} + + public PersistentSubscriptionStreamEventAppeared(ResolvedIndexedEvent @event, int? retryCount) + { + Event = @event; + RetryCount = retryCount; + } } [ProtoContract(Name = @"SubscribeToStream")] diff --git a/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs b/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs index 2515c11..ab5ae8c 100644 --- a/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs +++ b/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs @@ -1,11 +1,12 @@ -using EventStore.ClientAPI.Messages; +using EventStore.ClientAPI.ClientOperations; +using EventStore.ClientAPI.Messages; namespace EventStore.ClientAPI { /// /// A structure representing a single event or an resolved link event. /// - public struct ResolvedEvent + public struct ResolvedEvent : IResolvedEvent { /// /// The event, or the resolved link event if this is @@ -61,5 +62,10 @@ internal ResolvedEvent(ClientMessage.ResolvedIndexedEvent evnt) Link = evnt.Link == null ? null : new RecordedEvent(evnt.Link); OriginalPosition = null; } + + Position? IResolvedEvent.OriginalPosition => OriginalPosition; + RecordedEvent IResolvedEvent.OriginalEvent => OriginalEvent; + long IResolvedEvent.OriginalEventNumber=> OriginalEventNumber; + string IResolvedEvent.OriginalStreamId => OriginalStreamId; } } \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs b/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs index d3cc962..7141c9c 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/FakeEventStoreConnection.cs @@ -11,6 +11,7 @@ internal class FakeEventStoreConnection : IEventStoreConnection private Func> _readAllEventsForwardAsync; private Func> _readStreamEventsForwardAsync; private Func, Action, Task> _subscribeToStreamAsync; + private Func, Action, Task> _subscribeToAllAsync; public void Dispose() { @@ -140,14 +141,26 @@ public EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( throw new NotImplementedException(); } + public void HandleSubscribeToAllAsync(Func, Action, Task> callback) + { + _subscribeToAllAsync = callback; + } + public Task SubscribeToAllAsync(bool resolveLinkTos, Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null) { - throw new NotImplementedException(); + return _subscribeToAllAsync(resolveLinkTos, eventAppeared, subscriptionDropped); } public EventStorePersistentSubscriptionBase ConnectToPersistentSubscription(string stream, string groupName, - Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, + Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, + bool autoAck = true) + { + throw new NotImplementedException(); + } + + public Task ConnectToPersistentSubscriptionAsync(string stream, string groupName, Func eventAppeared, + Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) { throw new NotImplementedException(); @@ -259,10 +272,5 @@ public void OnConnected(ClientConnectionEventArgs e) var handler = Connected; if (handler != null) handler(this, e); } - - public Task ConnectToPersistentSubscriptionAsync(string stream, string groupName, Func eventAppeared, Action subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) - { - throw new NotImplementedException(); - } } } \ No newline at end of file diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs index 9ee7a1b..98e9e76 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions.cs @@ -16,7 +16,7 @@ protected override void When() _conn.ConnectToPersistentSubscription( "nonexisting2", "foo", - (sub, e) => + (sub, e, i) => { Console.Write("appeared"); return Task.CompletedTask; diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs index c7d8c20..4fc69e9 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_non_existing_persistent_subscription_with_permissions_async.cs @@ -16,7 +16,7 @@ protected override void When() _conn.ConnectToPersistentSubscriptionAsync( "nonexisting2", "foo", - (sub, e) => + (sub, e, i) => { Console.Write("appeared"); return Task.CompletedTask; diff --git a/test/EventStore.ClientAPI.NetCore.Tests/connect_to_persistent_subscription_with_retries.cs b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_persistent_subscription_with_retries.cs new file mode 100644 index 0000000..b5ffeb7 --- /dev/null +++ b/test/EventStore.ClientAPI.NetCore.Tests/connect_to_persistent_subscription_with_retries.cs @@ -0,0 +1,65 @@ +using EventStore.ClientAPI; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace EventStore.Core.Tests.ClientAPI +{ + [TestFixture, Category("LongRunning")] + public class connect_to_persistent_subscription_with_retries : SpecificationWithConnection + { + private readonly string _stream = Guid.NewGuid().ToString("N"); + private readonly PersistentSubscriptionSettings _settings = PersistentSubscriptionSettings.Create() + .DoNotResolveLinkTos() + .StartFromBeginning(); + + private readonly AutoResetEvent _resetEvent = new AutoResetEvent(false); + private readonly Guid _id = Guid.NewGuid(); + int? _retryCount; + private const string _group = "retries"; + + protected override void Given() + { + _conn.CreatePersistentSubscriptionAsync(_stream, _group, _settings, + DefaultData.AdminCredentials).Wait(); + _conn.ConnectToPersistentSubscription( + _stream, + _group, + HandleEvent, + (sub, reason, ex) => { }, + DefaultData.AdminCredentials,autoAck:false); + + } + + protected override void When() + { + _conn.AppendToStreamAsync(_stream, ExpectedVersion.Any, DefaultData.AdminCredentials, + new EventData(_id, "test", true, Encoding.UTF8.GetBytes("{'foo' : 'bar'}"), new byte[0])).Wait(); + } + + private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent, int? retryCount) + { + if (retryCount > 4) + { + _retryCount = retryCount; + sub.Acknowledge(resolvedEvent); + _resetEvent.Set(); + } + else + { + sub.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Retry, "Not yet tried enough times"); + } + return Task.CompletedTask; + } + + [Test] + public void events_are_retried_until_success() + { + Assert.IsTrue(_resetEvent.WaitOne(TimeSpan.FromSeconds(10))); + Assert.AreEqual(5, _retryCount); + } + } +} From 4ba8e21db4d8c9f907035768b75f2d0eb702f178 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 16:42:44 +0200 Subject: [PATCH 25/44] Creates A Public Constants Class for Client Use It is helpful to expose certain constants for use by users of the ClientAPI. Specifically in this case, the `MaxReadSize` value as it limits how the user interacts with the connection. Exposing the constant will allow the user to use it in the various "Read..." method calls without having to dig into the source code to find the maximum or fail and find it via trial and error. This change creates a new, public `ClientApiConstants` class that exposes a single `MaxReadSize` property that is set as the value of `Consts.MaxReadSize`. It also revises all of the previous `Consts.MaxReadSize` usages to use the new public version. In looking at the usages of the other properties in the `Consts` class, they did not seem as useful in normal usage of `ClientAPI`, so they were not replicated in `ClientApiConstants`. I left the bare value setting of the `Consts.MaxReadSize` so the values could continue to be set in a central location. --- .../CatchUpSubscriptionSettings.cs | 2 +- .../ClientApiConstants.cs | 13 +++++++++++++ .../Internal/EventStoreNodeConnection.cs | 8 ++++---- 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/ClientApiConstants.cs diff --git a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs index 50ec220..906665e 100644 --- a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs @@ -54,7 +54,7 @@ public class CatchUpSubscriptionSettings public CatchUpSubscriptionSettings(int maxLiveQueueSize, int readBatchSize, bool verboseLogging, bool resolveLinkTos, string subscriptionName = "") { Ensure.Positive(readBatchSize, "readBatchSize"); Ensure.Positive(maxLiveQueueSize, "maxLiveQueueSize"); - if (readBatchSize > Consts.MaxReadSize) throw new ArgumentException(string.Format("Read batch size should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); + if (readBatchSize > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Read batch size should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); MaxLiveQueueSize = maxLiveQueueSize; ReadBatchSize = readBatchSize; VerboseLogging = verboseLogging; diff --git a/src/EventStore.ClientAPI.NetCore/ClientApiConstants.cs b/src/EventStore.ClientAPI.NetCore/ClientApiConstants.cs new file mode 100644 index 0000000..86e13a5 --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/ClientApiConstants.cs @@ -0,0 +1,13 @@ +namespace EventStore.ClientAPI +{ + /// + /// Various constant values that may be useful when working with the ClientAPI. + /// + public static class ClientApiConstants + { + /// + /// The maximum number of events that can be read in a single operation. + /// + public static readonly int MaxReadSize = Consts.MaxReadSize; + } +} \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs index 4ebd527..dafa923 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs @@ -189,7 +189,7 @@ public Task ReadStreamEventsForwardAsync(string stream, long Ensure.NotNullOrEmpty(stream, "stream"); Ensure.Nonnegative(start, "start"); Ensure.Positive(count, "count"); - if(count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); + if(count > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsForwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); @@ -201,7 +201,7 @@ public Task ReadStreamEventsBackwardAsync(string stream, long { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.Positive(count, "count"); - if (count > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); + if (count > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsBackwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); @@ -212,7 +212,7 @@ public Task ReadStreamEventsBackwardAsync(string stream, long public Task ReadAllEventsForwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.Positive(maxCount, "maxCount"); - if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); + if (maxCount > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsForwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); @@ -223,7 +223,7 @@ public Task ReadAllEventsForwardAsync(Position position, int max public Task ReadAllEventsBackwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.Positive(maxCount, "maxCount"); - if (maxCount > Consts.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", Consts.MaxReadSize)); + if (maxCount > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsBackwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); From 119a94c95c70bf778525063e04e9536b10b7191f Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 17:19:11 +0200 Subject: [PATCH 26/44] Fixes to documentation and formatting --- .../CatchUpSubscriptionSettings.cs | 27 +- .../ClusterSettings.cs | 22 +- .../ConnectionSettings.cs | 32 +- .../ConnectionSettingsBuilder.cs | 43 +-- .../EventReadResult.cs | 8 +- .../EventStoreCatchUpSubscription.cs | 4 +- .../EventStoreConnection.cs | 2 +- .../GossipSeedClusterSettingsBuilder.cs | 7 +- .../IEventStoreConnection.cs | 273 +++++++++--------- .../PersistentSubscriptionSettings.cs | 32 +- .../ResolvedEvent.cs | 2 +- .../StreamEventsSlice.cs | 8 +- .../StreamMetadata.cs | 14 +- .../StreamMetadataBuilder.cs | 1 - 14 files changed, 236 insertions(+), 239 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs index 906665e..d6cc329 100644 --- a/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/CatchUpSubscriptionSettings.cs @@ -3,37 +3,37 @@ namespace EventStore.ClientAPI { /// - /// Settings for + /// Settings for . /// public class CatchUpSubscriptionSettings { /// - /// The maximum amount to cache when processing from live subscription. Going above will drop subscription. + /// The maximum amount of events to cache when processing from a live subscription. Going above this value will drop the subscription. /// public readonly int MaxLiveQueueSize; /// - /// The number of events to read per batch when reading history + /// The number of events to read per batch when reading the history. /// public readonly int ReadBatchSize; /// - /// Enables verbose logging on the subscription + /// Enables verbose logging on the subscription. /// public readonly bool VerboseLogging; /// - /// Whether or not to resolve link events + /// Whether to resolve link events. /// public readonly bool ResolveLinkTos; /// - /// The name of subscription. + /// The name of the subscription. /// public readonly string SubscriptionName; /// - /// Returns default settings + /// Returns default settings. /// public static readonly CatchUpSubscriptionSettings Default = new CatchUpSubscriptionSettings( Consts.CatchUpDefaultMaxPushQueueSize, @@ -42,15 +42,14 @@ public class CatchUpSubscriptionSettings resolveLinkTos: true, subscriptionName: String.Empty ); - /// - /// Constructs a object + /// Constructs a object. /// - /// The maximum amount to buffer when processing from live subscription. Going above will drop subscription. - /// The number of events to read per batch when reading history - /// Enables verbose logging on the subscription - /// Whether or not to resolve link events - /// The name of subscription. + /// The maximum amount of events to buffer when processing from a live subscription. Going above this amount will drop the subscription. + /// The number of events to read per batch when reading through history. + /// Enables verbose logging on the subscription. + /// Whether to resolve link events. + /// The name of the subscription. public CatchUpSubscriptionSettings(int maxLiveQueueSize, int readBatchSize, bool verboseLogging, bool resolveLinkTos, string subscriptionName = "") { Ensure.Positive(readBatchSize, "readBatchSize"); Ensure.Positive(maxLiveQueueSize, "maxLiveQueueSize"); diff --git a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs index 9566aca..45feb30 100644 --- a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs @@ -46,12 +46,12 @@ public static ClusterSettingsBuilder Create() public bool PreferRandomNode; /// - /// Used if we're connecting with gossip seeds + /// Used if connecting with gossip seeds. /// - /// Endpoints for seeding gossip - /// Maximum number of attempts to discover the cluster - /// Timeout for cluster gossip - /// Whether to prefer a random node selection or master + /// Endpoints for seeding gossip. + /// Maximum number of attempts to discover the cluster. + /// Timeout for cluster gossip. + /// Whether to prefer a random node selection or master. internal ClusterSettings(GossipSeed[] gossipSeeds, int maxDiscoverAttempts, TimeSpan gossipTimeout, bool preferRandomNode) { ClusterDns = ""; @@ -63,13 +63,13 @@ internal ClusterSettings(GossipSeed[] gossipSeeds, int maxDiscoverAttempts, Time } /// - /// Used if we're discovering via DNS + /// Used if discovering via DNS. /// - /// The DNS name to use for discovering endpoints - /// The maximum number of attempts for discovering endpoints - /// The well-known endpoint on which cluster managers are running - /// Timeout for cluster gossip - /// Whether to prefer a random node selection or master + /// The DNS name to use for discovering endpoints. + /// The maximum number of attempts for discovering endpoints. + /// The well-known endpoint on which cluster managers are running. + /// Timeout for cluster gossip. + /// Whether to prefer a random node selection or master. internal ClusterSettings(string clusterDns, int maxDiscoverAttempts, int externalGossipPort, TimeSpan gossipTimeout, bool preferRandomNode) { Ensure.NotNullOrEmpty(clusterDns, "clusterDns"); diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs index 56c0c11..152cca0 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs @@ -6,7 +6,7 @@ namespace EventStore.ClientAPI { /// /// A object is an immutable representation of the settings for an - /// . A object can be built using + /// . You can build a object using /// a , either via the method, or via /// the constructor of . /// @@ -15,53 +15,53 @@ public sealed class ConnectionSettings private static readonly Lazy DefaultSettings = new Lazy(() => Create(), true); /// - /// The default + /// The default . /// public static ConnectionSettings Default { get { return DefaultSettings.Value; } } /// - /// Creates a new set of + /// Creates a new set of . /// - /// A that can be used to build up a + /// A you can use to build up a . public static ConnectionSettingsBuilder Create() { return new ConnectionSettingsBuilder(); } /// - /// The that this connection will use + /// The that this connection will use. /// public readonly ILogger Log; /// - /// Whether or not do excessive logging of internal logic. + /// Whether to use excessive logging of internal logic. /// public readonly bool VerboseLogging; /// - /// The maximum number of outstanding items allowed in the queue + /// The maximum number of outstanding items allowed in the queue. /// public readonly int MaxQueueSize; /// - /// The maximum number of allowed asynchronous operations to be in process + /// The maximum number of allowed asynchronous operations to be in process. /// public readonly int MaxConcurrentItems; /// - /// The maximum number of retry attempts + /// The maximum number of retry attempts. /// public readonly int MaxRetries; /// - /// The maximum number of times to allow for reconnection + /// The maximum number of times to allow for reconnection. /// public readonly int MaxReconnections; /// - /// Whether or not to require EventStore to refuse serving read or write request if it is not master + /// Whether to require EventStore to refuse serving read or write request if it is not master. /// public readonly bool RequireMaster; /// - /// The amount of time to delay before attempting to reconnect + /// The amount of time to delay before attempting to reconnect. /// public readonly TimeSpan ReconnectionDelay; /// - /// The amount of time before an operation is considered to have timed out + /// The amount of time before an operation is considered to have timed out. /// public readonly TimeSpan OperationTimeout; /// @@ -73,7 +73,7 @@ public static ConnectionSettingsBuilder Create() /// public readonly UserCredentials DefaultUserCredentials; /// - /// Whether or not the connection is encrypted using SSL. + /// Whether the connection is encrypted using SSL. /// public readonly bool UseSslConnection; /// @@ -81,12 +81,12 @@ public static ConnectionSettingsBuilder Create() /// public readonly string TargetHost; /// - /// Whether or not to validate the server SSL certificate. + /// Whether to validate the server SSL certificate. /// public readonly bool ValidateServer; /// - /// Whether or not to raise an error if no response is received from the server for an operation. + /// Whether to raise an error if no response is received from the server for an operation. /// public readonly bool FailOnNoServerResponse; /// diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs index 490b598..1c1edfa 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs @@ -48,7 +48,7 @@ internal ConnectionSettingsBuilder() } /// - /// Configures the connection to output log messages to the given . + /// Configures the connection to output log messages to the given . You should implement this interface using another library such as NLog or log4net. /// /// The to use. /// @@ -89,7 +89,7 @@ public ConnectionSettingsBuilder UseFileLogger(string filename) } /// - /// Turns on verbose internal logic logging. + /// Turns on verbose internal logic logging. By contains default information about connection, disconnection and errors, but you can customize output. /// /// public ConnectionSettingsBuilder EnableVerboseLogging() @@ -99,7 +99,7 @@ public ConnectionSettingsBuilder EnableVerboseLogging() } /// - /// Sets the limit for number of outstanding operations + /// Sets the limit for number of outstanding operations. /// /// The new limit of outstanding operations /// @@ -112,7 +112,7 @@ public ConnectionSettingsBuilder LimitOperationsQueueTo(int limit) } /// - /// Limits the number of concurrent operations that this connection can have + /// Limits the number of concurrent operations that this connection can have. /// /// /// @@ -125,7 +125,7 @@ public ConnectionSettingsBuilder LimitConcurrentOperationsTo(int limit) } /// - /// Limits the number of operation attempts + /// Limits the number of operation attempts. /// /// /// @@ -138,7 +138,7 @@ public ConnectionSettingsBuilder LimitAttemptsForOperationTo(int limit) } /// - /// Limits the number of operation retries + /// Limits the number of operation retries. /// /// /// @@ -151,7 +151,7 @@ public ConnectionSettingsBuilder LimitRetriesForOperationTo(int limit) } /// - /// Allows infinite operation retry attempts + /// Allows infinite operation retry attempts. /// /// public ConnectionSettingsBuilder KeepRetrying() @@ -161,7 +161,7 @@ public ConnectionSettingsBuilder KeepRetrying() } /// - /// Limits the number of reconnections this connection can try to make + /// Limits the number of reconnections this connection can try to make. /// /// /// @@ -174,7 +174,7 @@ public ConnectionSettingsBuilder LimitReconnectionsTo(int limit) } /// - /// Allows infinite reconnection attempts + /// Allows infinite reconnection attempts. /// /// public ConnectionSettingsBuilder KeepReconnecting() @@ -184,7 +184,7 @@ public ConnectionSettingsBuilder KeepReconnecting() } /// - /// Requires all write and read requests to be served only by master (cluster version only) + /// Requires all write and read requests to be served only by master (cluster version only). /// /// public ConnectionSettingsBuilder PerformOnMasterOnly() @@ -194,7 +194,7 @@ public ConnectionSettingsBuilder PerformOnMasterOnly() } /// - /// Allow for writes to be forwarded and read requests served locally if node is not master (cluster version only) + /// Allow for writes to be forwarded and read requests served locally if node is not master (cluster version only). /// /// public ConnectionSettingsBuilder PerformOnAnyNode() @@ -204,7 +204,7 @@ public ConnectionSettingsBuilder PerformOnAnyNode() } /// - /// Sets the delay between reconnection attempts + /// Sets the delay between reconnection attempts. /// /// /// @@ -215,7 +215,7 @@ public ConnectionSettingsBuilder SetReconnectionDelayTo(TimeSpan reconnectionDel } /// - /// Sets the operation timeout duration + /// Sets the operation timeout duration. /// /// /// @@ -237,7 +237,7 @@ public ConnectionSettingsBuilder SetTimeoutCheckPeriodTo(TimeSpan timeoutCheckPe } /// - /// Sets the default to be used for this connection. + /// Sets the default used for this connection. /// If user credentials are not given for an operation, these credentials will be used. /// /// @@ -264,7 +264,7 @@ public ConnectionSettingsBuilder UseSslConnection(string targetHost, bool valida } /// - /// Marks that no response from server should cause an error on the request + /// Marks that no response from server should cause an error on the request. /// /// public ConnectionSettingsBuilder FailOnNoServerResponse() @@ -274,7 +274,7 @@ public ConnectionSettingsBuilder FailOnNoServerResponse() } /// - /// Sets how often heartbeats should be expected on the connection (lower values detect broken sockets faster) + /// Sets how often heartbeats should be expected on the connection (lower values detect broken sockets faster). /// /// /// @@ -285,7 +285,7 @@ public ConnectionSettingsBuilder SetHeartbeatInterval(TimeSpan interval) } /// - /// Sets how long to wait without heartbeats before determining a connection to be dead (must be longer than heartbeat interval) + /// Sets how long to wait without heartbeats before determining a connection to be dead (must be longer than heartbeat interval). /// /// /// @@ -378,10 +378,11 @@ public ConnectionSettingsBuilder SetClusterGossipPort(int clusterGossipPort) /// /// Sets gossip seed endpoints for the client. /// - /// Note that this should be the external HTTP endpoint of the server, as it is required - /// for the client to exchange gossip with the server. The standard port which should be - /// used here is 2113. - /// + /// + /// This should be the external HTTP endpoint of the server, as it is required + /// for the client to exchange gossip with the server. The standard port is 2113. + /// + /// /// If the server requires a specific Host header to be sent as part of the gossip /// request, use the overload of this method taking instead. /// diff --git a/src/EventStore.ClientAPI.NetCore/EventReadResult.cs b/src/EventStore.ClientAPI.NetCore/EventReadResult.cs index 7cca733..3d1c095 100644 --- a/src/EventStore.ClientAPI.NetCore/EventReadResult.cs +++ b/src/EventStore.ClientAPI.NetCore/EventReadResult.cs @@ -4,17 +4,17 @@ namespace EventStore.ClientAPI { /// - /// A Event Read Result is the result of a single event read operation to the event store. + /// A event read result is the result of a single event read operation to Event Store. /// public class EventReadResult { /// - /// The representing the status of this read attempt + /// The representing the status of this read attempt. /// public readonly EventReadStatus Status; /// - /// The name of the stream read + /// The name of the stream read. /// public readonly string Stream; @@ -24,7 +24,7 @@ public class EventReadResult public readonly long EventNumber; /// - /// The event read represented as + /// The event read represented as . /// public readonly ResolvedEvent? Event; diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs index f701a80..d5fb49d 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs @@ -430,7 +430,7 @@ private async Task ReadEventsInternalAsync(IEventStoreConnection connection, boo private async Task ReadEventsCallbackAsync(AllEventsSlice slice, long? lastCommitPosition) { bool shouldStopOrDone = ShouldStop || await ProcessEventsAsync(lastCommitPosition, slice).ConfigureAwait(false); - if (shouldStopOrDone && Verbose) + if(shouldStopOrDone && Verbose) { Log.Debug( "Catch-up Subscription {0} to {1}: finished reading events, nextReadPosition = {2}.", @@ -534,7 +534,7 @@ internal EventStoreStreamCatchUpSubscription(IEventStoreConnection connection, protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastCommitPosition, long? lastEventNumber) => ReadEventsInternalAsync(connection, resolveLinkTos, userCredentials, lastEventNumber); - + private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos, UserCredentials userCredentials, long? lastEventNumber) { diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index 58d7601..28867be 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -37,7 +37,7 @@ public static IEventStoreConnection Create(string connectionString, string conne } /// - /// Creates a new to single node using the overriding them with values provided via the connectionstring + /// Creates a new to single node using default provided via a connectionstring /// /// Optional name of connection (will be generated automatically, if not provided) /// Pre-populated settings builder, optional. If not specified, a new builder will be created. diff --git a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs index 9d1b95d..450547b 100644 --- a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs @@ -17,10 +17,9 @@ public class GossipSeedClusterSettingsBuilder /// /// Sets gossip seed endpoints for the client. - /// - /// Note that this should be the external HTTP endpoint of the server, as it is required - /// for the client to exchange gossip with the server. The standard port which should be - /// used here is 2113. + /// TODO: This was a note. + /// This should be the external HTTP endpoint of the server, as it is required + /// for the client to exchange gossip with the server. The standard port is 2113. /// /// If the server requires a specific Host header to be sent as part of the gossip /// request, use the overload of this method taking instead. diff --git a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs index f4e8db9..f6cbd47 100644 --- a/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/IEventStoreConnection.cs @@ -7,40 +7,40 @@ namespace EventStore.ClientAPI { /// - /// Maintains a full duplex connection to the EventStore + /// Maintains a full duplex connection to Event Store. /// /// - /// An operates quite differently than say a SqlConnection. Normally + /// An operates differently than a SqlConnection. Normally /// when using an you want to keep the connection open for a much longer of time than /// when you use a SqlConnection. If you prefer the usage pattern of using(new Connection()) .. then you would likely /// want to create a FlyWeight on top of the . /// /// Another difference is that with the all operations are handled in a full async manner /// (even if you call the synchronous behaviors). Many threads can use an at the same - /// time or a single thread can make many asynchronous requests. To get the most performance out of the connection + /// time or a single thread can make many asynchronous requests. To get the best performance out of the connection /// it is generally recommended to use it in this way. /// public interface IEventStoreConnection : IDisposable { /// - /// Gets the name of this connection. A connection name can be used for disambiguation + /// Gets the name of this connection. A connection name is useful for disambiguation /// in log files. /// string ConnectionName { get; } /// - /// Connects the asynchronously to a destination + /// Connects the asynchronously to a destination. /// - /// A that can be waited upon. + /// A to wait upon. Task ConnectAsync(); /// - /// Closes this + /// Closes this . /// void Close(); /// - /// Deletes a stream from the Event Store asynchronously + /// Deletes a stream from Event Store asynchronously. /// /// The name of the stream to delete. /// The expected version that the streams should have when being deleted. @@ -49,111 +49,110 @@ public interface IEventStoreConnection : IDisposable Task DeleteStreamAsync(string stream, long expectedVersion, UserCredentials userCredentials = null); /// - /// Deletes a stream from the Event Store asynchronously + /// Deletes a stream from Event Store asynchronously. /// /// The name of the stream to delete. /// The expected version that the streams should have when being deleted. - /// Indicator for tombstoning vs soft-deleting the stream. Tombstoned streams can never be recreated. Soft-deleted streams - /// can be written to again, but the EventNumber sequence will not start from 0. + /// Indicator for tombstoning vs soft-deleting the stream. Tombstoned streams can never be recreated. Soft-deleted streams can be written to again, but the EventNumber sequence will not start from 0. /// The optional user credentials to perform operation with. /// A containing the results of the delete stream operation. Task DeleteStreamAsync(string stream, long expectedVersion, bool hardDelete, UserCredentials userCredentials = null); /// - /// Appends Events asynchronously to a stream. + /// Appends events asynchronously to a stream. /// /// /// When appending events to a stream the choice can - /// make a very large difference in the observed behavior. For example, if no stream exists + /// make a large difference in the observed behavior. For example, if no stream exists /// and ExpectedVersion.Any is used, a new stream will be implicitly created when appending. - /// + /// TODO: Link above and below? /// There are also differences in idempotency between different types of calls. - /// If you specify an ExpectedVersion aside from ExpectedVersion.Any the Event Store - /// will give you an idempotency guarantee. If using ExpectedVersion.Any the Event Store - /// will do its best to provide idempotency but does not guarantee idempotency + /// If you specify an ExpectedVersion aside from ExpectedVersion.Any, Event Store + /// will give you an idempotency guarantee. If using ExpectedVersion.Any, Event Store + /// will do its best to provide idempotency but does not guarantee idempotency. /// - /// The name of the stream to append events to - /// The of the stream to append to - /// The events to append to the stream + /// The name of the stream to append events to. + /// The of the stream to append to. + /// The events to append to the stream. /// A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, params EventData[] events); /// - /// Appends Events asynchronously to a stream. + /// Appends events asynchronously to a stream. /// /// /// When appending events to a stream the choice can - /// make a very large difference in the observed behavior. For example, if no stream exists + /// make a large difference in the observed behavior. For example, if no stream exists /// and ExpectedVersion.Any is used, a new stream will be implicitly created when appending. - /// + /// /// There are also differences in idempotency between different types of calls. - /// If you specify an ExpectedVersion aside from ExpectedVersion.Any the Event Store - /// will give you an idempotency guarantee. If using ExpectedVersion.Any the Event Store - /// will do its best to provide idempotency but does not guarantee idempotency + /// If you specify an ExpectedVersion aside from ExpectedVersion.Any, Event Store + /// will give you an idempotency guarantee. If using ExpectedVersion.Any, Event Store + /// will do its best to provide idempotency but does not guarantee idempotency. /// - /// The name of the stream to append events to - /// The of the stream to append to + /// The name of the stream to append events to. + /// The of the stream to append to. /// The optional user credentials to perform operation with. - /// The events to append to the stream + /// The events to append to the stream. /// A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, UserCredentials userCredentials, params EventData[] events); /// - /// Appends Events asynchronously to a stream. + /// Appends events asynchronously to a stream. /// /// /// When appending events to a stream the choice can - /// make a very large difference in the observed behavior. For example, if no stream exists + /// make a large difference in the observed behavior. For example, if no stream exists /// and ExpectedVersion.Any is used, a new stream will be implicitly created when appending. /// /// There are also differences in idempotency between different types of calls. - /// If you specify an ExpectedVersion aside from ExpectedVersion.Any the Event Store - /// will give you an idempotency guarantee. If using ExpectedVersion.Any the Event Store - /// will do its best to provide idempotency but does not guarantee idempotency + /// If you specify an ExpectedVersion aside from ExpectedVersion.Any, Event Store + /// will give you an idempotency guarantee. If using ExpectedVersion.Any, Event Store + /// will do its best to provide idempotency but does not guarantee idempotency. /// - /// The name of the stream to append events to - /// The of the stream to append to - /// The events to append to the stream + /// The name of the stream to append events to. + /// The of the stream to append to. + /// The events to append to the stream. /// The optional user credentials to perform operation with. ///A containing the results of the write operation. Task AppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null); /// - /// Appends Events asynchronously to a stream if the stream version matches the . + /// Appends events asynchronously to a stream if the stream version matches the . /// /// /// When appending events to a stream the choice can - /// make a very large difference in the observed behavior. For example, if no stream exists + /// make a large difference in the observed behavior. For example, if no stream exists /// and ExpectedVersion.Any is used, a new stream will be implicitly created when appending. /// /// There are also differences in idempotency between different types of calls. - /// If you specify an ExpectedVersion aside from ExpectedVersion.Any the Event Store - /// will give you an idempotency guarantee. If using ExpectedVersion.Any the Event Store - /// will do its best to provide idempotency but does not guarantee idempotency + /// If you specify an ExpectedVersion aside from ExpectedVersion.Any, Event Store + /// will give you an idempotency guarantee. If using ExpectedVersion.Any, Event Store + /// will do its best to provide idempotency but does not guarantee idempotency. /// - /// The name of the stream to append events to - /// The of the stream to append to - /// The events to append to the stream + /// The name of the stream to append events to. + /// The of the stream to append to. + /// The events to append to the stream. /// The optional user credentials to perform operation with. /// A describing if the operation succeeded and, if not, the reason for failure (which can be either stream version mismatch or trying to write to a deleted stream). Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null); /// - /// Starts a transaction in the event store on a given stream asynchronously + /// Starts an asynchronous transaction in Event Store on a given stream. /// /// /// A allows the calling of multiple writes with multiple - /// round trips over long periods of time between the caller and the event store. This method + /// round trips over long periods of time between the caller and Event Store. This method /// is only available through the TCP interface and no equivalent exists for the RESTful interface. /// - /// The stream to start a transaction on - /// The expected version of the stream at the time of starting the transaction + /// The stream to start a transaction on. + /// The expected version of the stream at the time of starting the transaction. /// The optional user credentials to perform operation with. /// A representing a multi-request transaction. Task StartTransactionAsync(string stream, long expectedVersion, UserCredentials userCredentials = null); /// - /// Continues transaction by provided transaction ID. + /// Continues specified transaction. /// /// /// A allows the calling of multiple writes with multiple @@ -176,43 +175,43 @@ public interface IEventStoreConnection : IDisposable Task ReadEventAsync(string stream, long eventNumber, bool resolveLinkTos, UserCredentials userCredentials = null); /// - /// Reads count Events from an Event Stream forwards (e.g. oldest to newest) starting from position start + /// Asynchronously reads count events from an event stream forwards (e.g. oldest to newest) starting from position start. /// - /// The stream to read from - /// The starting point to read from - /// The count of items to read - /// Whether to resolve LinkTo events automatically + /// The stream to read from. + /// The starting point to read from. + /// The count of items to read. + /// Whether to resolve LinkTo events automatically. /// The optional user credentials to perform operation with. /// A containing the results of the read operation. Task ReadStreamEventsForwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null); /// - /// Reads count events from an Event Stream backwards (e.g. newest to oldest) from position asynchronously + /// Asynchronously reads count events from an event stream backwards (e.g. newest to oldest) from position. /// - /// The Event Stream to read from - /// The position to start reading from - /// The count to read from the position - /// Whether to resolve LinkTo events automatically + /// The stream to read from. + /// The position to start reading from. + /// The count to read from the position. + /// Whether to resolve LinkTo events automatically. /// The optional user credentials to perform operation with. /// A containing the results of the read operation. Task ReadStreamEventsBackwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null); /// - /// Reads All Events in the node forward asynchronously (e.g. beginning to end) + /// Asynchronously reads all events in the node forward (e.g. beginning to end). /// - /// The position to start reading from - /// The maximum count to read - /// Whether to resolve LinkTo events automatically + /// The position to start reading from. + /// The maximum count to read. + /// Whether to resolve LinkTo events automatically. /// The optional user credentials to perform operation with. /// A containing the records read. Task ReadAllEventsForwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null); /// - /// Reads All Events in the node backwards (e.g. end to beginning) + /// Asynchronously reads all events in the node backwards (e.g. end to beginning). /// - /// The position to start reading from - /// The maximum count to read - /// Whether to resolve Link events automatically + /// The position to start reading from. + /// The maximum count to read. + /// Whether to resolve Link events automatically. /// The optional user credentials to perform operation with. /// A containing the records read. Task ReadAllEventsBackwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null); @@ -222,11 +221,11 @@ public interface IEventStoreConnection : IDisposable /// written to the stream while the subscription is active will be /// pushed to the client. /// - /// The stream to subscribe to - /// Whether to resolve Link events automatically - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation + /// The stream to subscribe to. + /// Whether to resolve Link events automatically. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. /// A representing the subscription. Task SubscribeToStreamAsync( string stream, @@ -257,15 +256,15 @@ Task SubscribeToStreamAsync( /// is desired, use the event number of the last event processed which /// appeared on the subscription. /// - /// NOTE: Using here will result in missing + /// Using here will result in missing /// the first event in the stream. - /// Whether to resolve Link events automatically - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked when the subscription switches to newly-pushed events - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The batch size to use during the read phase - /// The name of subscription + /// Whether to resolve Link events automatically. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked when the subscription switches to newly-pushed events. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The batch size to use during the read phase. + /// The name of subscription. /// An representing the subscription. [Obsolete("This method will be obsoleted in the next major version please switch to the overload with a settings object")] EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( @@ -293,7 +292,7 @@ EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( /// switches from the reading /// phase to the live subscription phase. /// - /// The stream to subscribe to + /// The stream to subscribe to. /// The event number from which to start. /// /// To receive all events in the stream, use . @@ -301,13 +300,13 @@ EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( /// is desired, use the event number of the last event processed which /// appeared on the subscription. /// - /// NOTE: Using here will result in missing + /// Using here will result in missing /// the first event in the stream. - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked when the subscription switches to newly-pushed events - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The for the subscription + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked when the subscription switches to newly-pushed events. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The for the subscription. /// An representing the subscription. EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( string stream, @@ -321,14 +320,14 @@ EventStoreStreamCatchUpSubscription SubscribeToStreamFrom( /// - /// Asynchronously subscribes to all events in the Event Store. New + /// Asynchronously subscribes to all events in Event Store. New /// events written to the stream while the subscription is active /// will be pushed to the client. /// - /// Whether to resolve Link events automatically - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation + /// Whether to resolve Link events automatically. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. /// A representing the subscription. Task SubscribeToAllAsync( bool resolveLinkTos, @@ -337,18 +336,18 @@ Task SubscribeToAllAsync( UserCredentials userCredentials = null); /// - /// Subscribes to a persistent subscription(competing consumer) on event store + /// Subscribes to a persistent subscription (competing consumer) on an event store. /// - /// The subscription group to connect to - /// The stream to subscribe to - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The buffer size to use for the persistent subscription + /// The subscription group to connect to. + /// The stream to subscribe to. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The buffer size to use for the persistent subscription. /// Whether the subscription should automatically acknowledge messages processed. /// If not set the receiver is required to explicitly acknowledge messages through the subscription. /// This will connect you to a persistent subscription group for a stream. The subscription group - /// must first be created with CreatePersistentSubscriptionAsync many connections + /// must first be created with CreatePersistentSubscriptionAsync. Many connections /// can connect to the same group and they will be treated as competing consumers within the group. /// If one connection dies work will be balanced across the rest of the consumers in the group. If /// you attempt to connect to a group that does not exist you will be given an exception. @@ -364,18 +363,18 @@ EventStorePersistentSubscriptionBase ConnectToPersistentSubscription( bool autoAck = true); /// - /// Asynchronously subscribes to a persistent subscription(competing consumer) on event store + /// Asynchronously subscribes to a persistent subscription (competing consumer) on an event store. /// - /// The subscription group to connect to - /// The stream to subscribe to - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The buffer size to use for the persistent subscription + /// The subscription group to connect to. + /// The stream to subscribe to. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The buffer size to use for the persistent subscription. /// Whether the subscription should automatically acknowledge messages processed. /// If not set the receiver is required to explicitly acknowledge messages through the subscription. /// This will connect you to a persistent subscription group for a stream. The subscription group - /// must first be created with CreatePersistentSubscriptionAsync many connections + /// must first be created with CreatePersistentSubscriptionAsync. Many connections /// can connect to the same group and they will be treated as competing consumers within the group. /// If one connection dies work will be balanced across the rest of the consumers in the group. If /// you attempt to connect to a group that does not exist you will be given an exception. @@ -419,7 +418,7 @@ EventStorePersistentSubscription ConnectToPersistentSubscriptionForAll( /// /// Subscribes to all events. Existing events from lastCheckpoint - /// onwards are read from the Event Store and presented to the user of + /// onwards are read from Event Store and presented to the user of /// as if they had been pushed. /// /// Once the end of the stream is read the subscription is @@ -437,15 +436,15 @@ EventStorePersistentSubscription ConnectToPersistentSubscriptionForAll( /// is desired, use the position representing the last event processed which /// appeared on the subscription. /// - /// NOTE: Using here will result in missing + /// Using here will result in missing /// the first event in the stream. - /// Whether to resolve Link events automatically - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked when the subscription switches to newly-pushed events - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The batch size to use during the read phase - /// The name of subscription + /// Whether to resolve Link events automatically. + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked when the subscription switches to newly-pushed events. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The batch size to use during the read phase. + /// The name of subscription. /// An representing the subscription. [Obsolete("This overload will be removed in the next major release please use the overload with a settings object")] EventStoreAllCatchUpSubscription SubscribeToAllFrom( @@ -460,7 +459,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// /// Subscribes to a all events. Existing events from lastCheckpoint - /// onwards are read from the Event Store and presented to the user of + /// onwards are read from Event Store and presented to the user of /// as if they had been pushed. /// /// Once the end of the stream is read the subscription is @@ -478,13 +477,13 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// is desired, use the position representing the last event processed which /// appeared on the subscription. /// - /// NOTE: Using here will result in missing + /// Using here will result in missing /// the first event in the stream. - /// A Task invoked and awaited when a new event is received over the subscription - /// An action invoked when the subscription switches to newly-pushed events - /// An action invoked if the subscription is dropped - /// User credentials to use for the operation - /// The for the subscription + /// A Task invoked and awaited when a new event is received over the subscription. + /// An action invoked when the subscription switches to newly-pushed events. + /// An action invoked if the subscription is dropped. + /// User credentials to use for the operation. + /// The for the subscription. /// An representing the subscription. EventStoreAllCatchUpSubscription SubscribeToAllFrom( Position? lastCheckpoint, @@ -508,10 +507,10 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( */ /// - /// Asynchronously update a persistent subscription group on a stream + /// Asynchronously update a persistent subscription group on a stream. /// - /// The name of the stream to create the persistent subscription on - /// The name of the group to create + /// The name of the stream to create the persistent subscription on. + /// The name of the group to create. /// The for the subscription /// The credentials to be used for this operation. /// A that can be waited upon. @@ -519,22 +518,22 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// - /// Asynchronously create a persistent subscription group on a stream + /// Asynchronously create a persistent subscription group on a stream. /// - /// The name of the stream to create the persistent subscription on - /// The name of the group to create - /// The for the subscription + /// The name of the stream to create the persistent subscription on. + /// The name of the group to create. + /// The for the subscription. /// The credentials to be used for this operation. /// A that can be waited upon. Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials); /// - /// Asynchronously delete a persistent subscription group on a stream + /// Asynchronously delete a persistent subscription group on a stream. /// - /// The name of the stream to delete the persistent subscription on - /// The name of the group to delete - /// User credentials to use for the operation + /// The name of the stream to delete the persistent subscription on. + /// The name of the group to delete. + /// User credentials to use for the operation. /// A that can be waited upon. Task DeletePersistentSubscriptionAsync(string stream, string groupName, UserCredentials userCredentials = null); @@ -554,7 +553,7 @@ EventStoreAllCatchUpSubscription SubscribeToAllFrom( /// The name of the stream for which to set metadata. /// The expected version for the write to the metadata stream. /// A representing the new metadata. - /// User credentials to use for the operation + /// User credentials to use for the operation. /// A containing the results of the write operation. Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, StreamMetadata metadata, UserCredentials userCredentials = null); diff --git a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs index 6275166..43ecb30 100644 --- a/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/PersistentSubscriptionSettings.cs @@ -4,8 +4,8 @@ namespace EventStore.ClientAPI { /// - /// Represents the settings for a . This should not be used - /// directly, but instead created via a + /// Represents the settings for a . You should not use + /// this directly, but instead created via a . /// public class PersistentSubscriptionSettings { @@ -32,57 +32,57 @@ public static PersistentSubscriptionSettingsBuilder Create() /// - /// Whether or not the should resolve linkTo events to their linked events. + /// Whether the should resolve linkTo events to their linked events. /// public readonly bool ResolveLinkTos; /// - /// Where the subscription should start from (position) + /// Which event position in the stream the subscription should start from. /// public readonly long StartFrom; /// - /// Whether or not in depth latency statistics should be tracked on this subscription. + /// Whether to track latency statistics on this subscription. /// public readonly bool ExtraStatistics; /// - /// The amount of time after which a message should be considered to be timedout and retried. + /// The amount of time after which to consider a message as timedout and retried. /// public readonly TimeSpan MessageTimeout; /// - /// The maximum number of retries (due to timeout) before a message get considered to be parked + /// The maximum number of retries (due to timeout) before a message is considered to be parked. /// public int MaxRetryCount; /// - /// The size of the buffer listening to live messages as they happen + /// The size of the buffer (in-memory) listening to live messages as they happen before paging occurs. /// public int LiveBufferSize; /// - /// The number of events read at a time when paging in history + /// The number of events read at a time when paging through history. /// public int ReadBatchSize; /// - /// The number of events to cache when paging through history + /// The number of events to cache when paging through history. /// public int HistoryBufferSize; /// - /// The amount of time to try to checkpoint after + /// The amount of time to try to checkpoint after. /// public readonly TimeSpan CheckPointAfter; /// - /// The minimum number of messages to checkpoint + /// The minimum number of messages to write to a checkpoint. /// public readonly int MinCheckPointCount; /// - /// The maximum number of messages to checkpoint if this number is a reached a checkpoint will be forced. + /// The maximum number of messages not checkpointed before forcing a checkpoint. /// public readonly int MaxCheckPointCount; @@ -97,15 +97,15 @@ public static PersistentSubscriptionSettingsBuilder Create() public string NamedConsumerStrategy; /// - /// Constructs a new + /// Constructs a new . /// internal PersistentSubscriptionSettings(bool resolveLinkTos, long startFrom, bool extraStatistics, TimeSpan messageTimeout, int maxRetryCount, int liveBufferSize, int readBatchSize, int historyBufferSize, TimeSpan checkPointAfter, int minCheckPointCount, int maxCheckPointCount, int maxSubscriberCount, string namedConsumerStrategy) { - if (messageTimeout.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(messageTimeout)); - if (checkPointAfter.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(checkPointAfter)); + if(messageTimeout.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(messageTimeout)); + if(checkPointAfter.TotalMilliseconds > Int32.MaxValue) throw new ArgumentException("milliseconds must be less or equal to than int32.MaxValue", nameof(checkPointAfter)); MessageTimeout = messageTimeout; ResolveLinkTos = resolveLinkTos; StartFrom = startFrom; diff --git a/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs b/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs index ab5ae8c..403b697 100644 --- a/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs +++ b/src/EventStore.ClientAPI.NetCore/ResolvedEvent.cs @@ -24,7 +24,7 @@ public struct ResolvedEvent : IResolvedEvent /// /// If this represents a link event, the Link /// will be the , otherwise it will be the - /// Event. + /// event. /// public RecordedEvent OriginalEvent { get { return Link ?? Event; } } diff --git a/src/EventStore.ClientAPI.NetCore/StreamEventsSlice.cs b/src/EventStore.ClientAPI.NetCore/StreamEventsSlice.cs index 4018a98..99d7ec4 100644 --- a/src/EventStore.ClientAPI.NetCore/StreamEventsSlice.cs +++ b/src/EventStore.ClientAPI.NetCore/StreamEventsSlice.cs @@ -5,17 +5,17 @@ namespace EventStore.ClientAPI { /// - /// An Stream Events Slice represents the result of a single read operation to the event store. + /// A stream events slice represents the result of a single read operation to Event Store. /// public class StreamEventsSlice { /// - /// The representing the status of this read attempt + /// The representing the status of this read attempt. /// public readonly SliceReadStatus Status; /// - /// The name of the stream read + /// The name of the stream to read. /// public readonly string Stream; @@ -30,7 +30,7 @@ public class StreamEventsSlice public readonly ReadDirection ReadDirection; /// - /// The events read represented as + /// The events read represented as . /// public readonly ResolvedEvent[] Events; diff --git a/src/EventStore.ClientAPI.NetCore/StreamMetadata.cs b/src/EventStore.ClientAPI.NetCore/StreamMetadata.cs index b32ca3c..61ddf8d 100644 --- a/src/EventStore.ClientAPI.NetCore/StreamMetadata.cs +++ b/src/EventStore.ClientAPI.NetCore/StreamMetadata.cs @@ -48,7 +48,7 @@ public class StreamMetadata public IEnumerable> CustomMetadataAsRawJsons { get { return _customMetadata.Select(x => new KeyValuePair(x.Key, x.Value.ToString())); } - } + } private readonly IDictionary _customMetadata; @@ -70,7 +70,7 @@ internal StreamMetadata(long? maxCount, TimeSpan? maxAge, long? truncateBefore, TruncateBefore = truncateBefore; CacheControl = cacheControl; Acl = acl; - _customMetadata = customMetadata ?? Empty.CustomStreamMetadata; + _customMetadata = customMetadata ?? Empty.CustomStreamMetadata; } /// @@ -104,10 +104,10 @@ public StreamMetadataBuilder Copy() { if(Acl == null) return new StreamMetadataBuilder( - MaxCount, - MaxAge, - TruncateBefore, - CacheControl, + MaxCount, + MaxAge, + TruncateBefore, + CacheControl, customMetadata: _customMetadata); return new StreamMetadataBuilder( MaxCount, @@ -429,7 +429,7 @@ private static void Check(JsonToken type, JsonTextReader reader) { if (reader.TokenType != type) throw new Exception("Invalid JSON"); - } + } private static void Check(bool read, JsonTextReader reader) { diff --git a/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs b/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs index d224e38..7b38207 100644 --- a/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/StreamMetadataBuilder.cs @@ -3,7 +3,6 @@ using System.Linq; using EventStore.ClientAPI.Common.Utils; using Newtonsoft.Json.Linq; - namespace EventStore.ClientAPI { /// From b8545abacaf36f9f01a9061e8e3fb3b773c7441c Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 17:28:16 +0200 Subject: [PATCH 27/44] Version bump and update to eventstore server version --- appveyor.yml | 2 +- wercker.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 19770c0..da21a7c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 4.0.3.{build} +version: 4.1.0.{build} image: Visual Studio 2017 diff --git a/wercker.yml b/wercker.yml index 2709a44..a821e06 100644 --- a/wercker.yml +++ b/wercker.yml @@ -17,9 +17,9 @@ build: name: install and run eventstore code: | apt-get install wget tzdata curl iproute2 -y - wget https://eventstore.org/downloads/EventStore-OSS-Ubuntu-14.04-v4.0.3.tar.gz - tar xfv EventStore-OSS-Ubuntu-14.04-v4.0.3.tar.gz - pushd ./EventStore-OSS-Ubuntu-14.04-v4.0.3 + wget https://eventstore.org/downloads/EventStore-OSS-Ubuntu-14.04-v4.1.0.tar.gz + tar xfv EventStore-OSS-Ubuntu-14.04-v4.1.0.tar.gz + pushd ./EventStore-OSS-Ubuntu-14.04-v4.1.0 nohup ./eventstored --run-projections All --mem-db --log ~/logs & popd From 4888aa42b55d961924823dd33b0c2340583d5366 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 17:57:08 +0200 Subject: [PATCH 28/44] Appveyor now supports core testing without custom script --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index da21a7c..44eac44 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,9 +22,6 @@ build: publish_nuget: true verbosity: minimal -test_script: - - ps: .\scripts\appveyortest.ps1 - deploy: provider: NuGet on: From 81c0e03b8775ca7bf041d76c16662f77ec895a47 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 9 Feb 2018 18:07:19 +0200 Subject: [PATCH 29/44] Update appveyor server version --- scripts/installandruneventstore.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installandruneventstore.ps1 b/scripts/installandruneventstore.ps1 index 7ede819..65f2a2d 100644 --- a/scripts/installandruneventstore.ps1 +++ b/scripts/installandruneventstore.ps1 @@ -1,3 +1,3 @@ -(New-Object Net.WebClient).DownloadFile('https://eventstore.org/downloads/EventStore-OSS-Win-v4.0.3.zip','c:\tools\eventstore.zip') +(New-Object Net.WebClient).DownloadFile('https://eventstore.org/downloads/EventStore-OSS-Win-v4.1.0.zip','c:\tools\eventstore.zip') 7z e C:\tools\eventstore.zip -oC:\tools\EventStore start-process -NoNewWindow "C:\tools\EventStore\EventStore.ClusterNode.exe" "--memdb --run-projections ALL" \ No newline at end of file From 44a3bd9cc89d6629fe7a90d6d5244b93a9d6a345 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 16 Mar 2018 16:14:45 +0000 Subject: [PATCH 30/44] Added constructor overloads to allow supply of a Uri or DnsEndPoint --- .../Projections/QueryManager.cs | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs index 0e5797f..e98b758 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs @@ -1,10 +1,10 @@ -using System; -using System.Net; -using System.Threading.Tasks; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Common.Utils.Threading; using EventStore.ClientAPI.SystemData; using Newtonsoft.Json.Linq; +using System; +using System.Net; +using System.Threading.Tasks; namespace EventStore.ClientAPI.Projections { @@ -21,13 +21,38 @@ public class QueryManager /// Creates a new instance of . /// /// An instance of to use for logging. - /// HTTP endpoint of an Event Store server. + /// HTTP IP endpoint of an Event Store server. /// Timeout of projection API operations /// Timeout of query execution - public QueryManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) + public QueryManager(ILogger log, IPEndPoint ipHttpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) { _queryTimeout = queryTimeout; - _projectionsManager = new ProjectionsManager(log, httpEndPoint, projectionOperationTimeout); + _projectionsManager = new ProjectionsManager(log, ipHttpEndPoint, projectionOperationTimeout); + } + + /// + /// Creates a new instance of . + /// + /// An instance of to use for logging. + /// HTTP DNS endpoint of an Event Store server. + /// Timeout of projection API operations + /// Timeout of query execution + public QueryManager(ILogger log, DnsEndPoint dnsHttpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) + { + _queryTimeout = queryTimeout; + _projectionsManager = new ProjectionsManager(log, dnsHttpEndPoint, projectionOperationTimeout); + } + + /// + /// Creates a new instance of . + /// + /// An instance of to use for logging. + /// HTTP URI endpoint of an Event Store server. + /// Timeout of projection API operations + /// Timeout of query execution + public QueryManager(ILogger log, Uri uri, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) + : this(log, new DnsEndPoint(uri.Host, uri.Port), projectionOperationTimeout, queryTimeout) + { } /// @@ -80,4 +105,4 @@ private async Task GetStatusAsync(string name, UserCredentials userCrede return projectionStatus.ParseJson()["status"].ToString(); } } -} +} \ No newline at end of file From 58e4d78209d45a6e8b7800f1e2ffa9e1b0e37b1f Mon Sep 17 00:00:00 2001 From: James Geall Date: Sun, 2 Sep 2018 10:41:01 +0100 Subject: [PATCH 31/44] Revert divergent PR - will be moved to main repo and released with unified client --- .../Projections/QueryManager.cs | 39 ++++--------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs index e98b758..0e5797f 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs @@ -1,10 +1,10 @@ +using System; +using System.Net; +using System.Threading.Tasks; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Common.Utils.Threading; using EventStore.ClientAPI.SystemData; using Newtonsoft.Json.Linq; -using System; -using System.Net; -using System.Threading.Tasks; namespace EventStore.ClientAPI.Projections { @@ -21,38 +21,13 @@ public class QueryManager /// Creates a new instance of . /// /// An instance of to use for logging. - /// HTTP IP endpoint of an Event Store server. + /// HTTP endpoint of an Event Store server. /// Timeout of projection API operations /// Timeout of query execution - public QueryManager(ILogger log, IPEndPoint ipHttpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) + public QueryManager(ILogger log, IPEndPoint httpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) { _queryTimeout = queryTimeout; - _projectionsManager = new ProjectionsManager(log, ipHttpEndPoint, projectionOperationTimeout); - } - - /// - /// Creates a new instance of . - /// - /// An instance of to use for logging. - /// HTTP DNS endpoint of an Event Store server. - /// Timeout of projection API operations - /// Timeout of query execution - public QueryManager(ILogger log, DnsEndPoint dnsHttpEndPoint, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) - { - _queryTimeout = queryTimeout; - _projectionsManager = new ProjectionsManager(log, dnsHttpEndPoint, projectionOperationTimeout); - } - - /// - /// Creates a new instance of . - /// - /// An instance of to use for logging. - /// HTTP URI endpoint of an Event Store server. - /// Timeout of projection API operations - /// Timeout of query execution - public QueryManager(ILogger log, Uri uri, TimeSpan projectionOperationTimeout, TimeSpan queryTimeout) - : this(log, new DnsEndPoint(uri.Host, uri.Port), projectionOperationTimeout, queryTimeout) - { + _projectionsManager = new ProjectionsManager(log, httpEndPoint, projectionOperationTimeout); } /// @@ -105,4 +80,4 @@ private async Task GetStatusAsync(string name, UserCredentials userCrede return projectionStatus.ParseJson()["status"].ToString(); } } -} \ No newline at end of file +} From 23e92a29969283f39c22d072af9163504766c220 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 3 Sep 2018 09:34:10 +0100 Subject: [PATCH 32/44] Updates package dependencies and added default namespace --- .../EventStore.ClientAPI.NetCore.csproj | 60 +++++++++---------- .../EventStore.ClientAPI.NetCore.Tests.csproj | 8 +-- 2 files changed, 33 insertions(+), 35 deletions(-) mode change 100755 => 100644 src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj diff --git a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj old mode 100755 new mode 100644 index 51ca040..62cba69 --- a/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj +++ b/src/EventStore.ClientAPI.NetCore/EventStore.ClientAPI.NetCore.csproj @@ -1,32 +1,30 @@ - - - - netstandard2.0 - - - EventStore.ClientAPI - EventStore NetStandard ClientApi - Event Store LLP - Copyright © Event Store LLP. All rights reserved. - EventStore.ClientAPI - 4.0.2-alpha - - - The client API for the Event Store. Get the open source or commercial versions of the Event Store server from http://geteventstore.com - Event Store LLP - portable - EventStore.ClientAPI.NetCore - EventStore.ClientAPI.NetCore - eventstore;client;netstandard2.0 - http://geteventstore.com/assets/ouro-200.png - https://github.com/EventStore/netcore-client/blob/master/LICENSE.md - git - https://github.com/EventStore/ClientAPI.NetCore - - - - - - - + + + netstandard2.0 + EventStore.ClientAPI + + + EventStore.ClientAPI + EventStore NetStandard ClientApi + Event Store LLP + Copyright © Event Store LLP. All rights reserved. + EventStore.ClientAPI + 4.1.1-rc + + + The client API for the Event Store. Get the open source or commercial versions of the Event Store server from http://geteventstore.com + Event Store LLP + portable + EventStore.ClientAPI.NetCore + EventStore.ClientAPI.NetCore + eventstore;client;netstandard2.0 + http://geteventstore.com/assets/ouro-200.png + https://github.com/EventStore/netcore-client/blob/master/LICENSE.md + git + https://github.com/EventStore/ClientAPI.NetCore + + + + + diff --git a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj index a80677b..b0c215c 100755 --- a/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj +++ b/test/EventStore.ClientAPI.NetCore.Tests/EventStore.ClientAPI.NetCore.Tests.csproj @@ -21,10 +21,10 @@ - - - - + + + + From a97c439346ee2a6757c6d52baed92cedc010d50b Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 3 Sep 2018 09:40:49 +0100 Subject: [PATCH 33/44] Add PreferSlaveNode to Connection Builder EventStore/EventStore/#1557 --- .../ClusterSettings.cs | 14 +++++------ .../ConnectionSettings.cs | 6 ++--- .../ConnectionSettingsBuilder.cs | 16 +++++++++--- .../DnsClusterSettingsBuilder.cs | 16 +++++++++--- .../EventStoreConnection.cs | 12 ++++----- .../GossipSeedClusterSettingsBuilder.cs | 16 +++++++++--- .../Internal/ClusterDnsEndPointDiscoverer.cs | 24 +++++++++++------- .../NodePreference.cs | 25 +++++++++++++++++++ 8 files changed, 95 insertions(+), 34 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/NodePreference.cs diff --git a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs index 45feb30..c503d3b 100644 --- a/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ClusterSettings.cs @@ -43,7 +43,7 @@ public static ClusterSettingsBuilder Create() /// /// Prefer a randomly selected node. /// - public bool PreferRandomNode; + public NodePreference NodePreference; /// /// Used if connecting with gossip seeds. @@ -51,15 +51,15 @@ public static ClusterSettingsBuilder Create() /// Endpoints for seeding gossip. /// Maximum number of attempts to discover the cluster. /// Timeout for cluster gossip. - /// Whether to prefer a random node selection or master. - internal ClusterSettings(GossipSeed[] gossipSeeds, int maxDiscoverAttempts, TimeSpan gossipTimeout, bool preferRandomNode) + /// Whether to prefer slave, random, or master node selection. + internal ClusterSettings(GossipSeed[] gossipSeeds, int maxDiscoverAttempts, TimeSpan gossipTimeout, NodePreference nodePreference) { ClusterDns = ""; MaxDiscoverAttempts = maxDiscoverAttempts; ExternalGossipPort = 0; GossipTimeout = gossipTimeout; GossipSeeds = gossipSeeds; - PreferRandomNode = preferRandomNode; + NodePreference = nodePreference; } /// @@ -69,8 +69,8 @@ internal ClusterSettings(GossipSeed[] gossipSeeds, int maxDiscoverAttempts, Time /// The maximum number of attempts for discovering endpoints. /// The well-known endpoint on which cluster managers are running. /// Timeout for cluster gossip. - /// Whether to prefer a random node selection or master. - internal ClusterSettings(string clusterDns, int maxDiscoverAttempts, int externalGossipPort, TimeSpan gossipTimeout, bool preferRandomNode) + /// Whether to prefer slave, random, or master node selection. + internal ClusterSettings(string clusterDns, int maxDiscoverAttempts, int externalGossipPort, TimeSpan gossipTimeout, NodePreference nodePreference) { Ensure.NotNullOrEmpty(clusterDns, "clusterDns"); if (maxDiscoverAttempts < -1) @@ -82,7 +82,7 @@ internal ClusterSettings(string clusterDns, int maxDiscoverAttempts, int externa ExternalGossipPort = externalGossipPort; GossipTimeout = gossipTimeout; GossipSeeds = new GossipSeed[0]; - PreferRandomNode = preferRandomNode; + NodePreference = nodePreference; } } } diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs index 152cca0..5803a8e 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs @@ -124,7 +124,7 @@ public static ConnectionSettingsBuilder Create() /// /// Whether to randomly choose a node that's alive from the known nodes. /// - public readonly bool PreferRandomNode; + public readonly NodePreference NodePreference; /// /// The interval after which a client will time out during connection. @@ -154,7 +154,7 @@ internal ConnectionSettings(ILogger log, int maxDiscoverAttempts, int externalGossipPort, TimeSpan gossipTimeout, - bool preferRandomNode) + NodePreference nodePreference) { Ensure.NotNull(log, "log"); Ensure.Positive(maxQueueSize, "maxQueueSize"); @@ -189,7 +189,7 @@ internal ConnectionSettings(ILogger log, MaxDiscoverAttempts = maxDiscoverAttempts; ExternalGossipPort = externalGossipPort; GossipTimeout = gossipTimeout; - PreferRandomNode = preferRandomNode; + NodePreference = nodePreference; } } } diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs index 1c1edfa..b95ea42 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs @@ -40,7 +40,7 @@ public class ConnectionSettingsBuilder private int _gossipExternalHttpPort = Consts.DefaultClusterManagerExternalHttpPort; private TimeSpan _gossipTimeout = TimeSpan.FromSeconds(1); private GossipSeed[] _gossipSeeds; - private bool _preferRandomNode = false; + private NodePreference _nodePreference = NodePreference.Master; internal ConnectionSettingsBuilder() @@ -350,7 +350,17 @@ public ConnectionSettingsBuilder SetGossipTimeout(TimeSpan timeout) /// A for further configuration. public ConnectionSettingsBuilder PreferRandomNode() { - _preferRandomNode = true; + _nodePreference = NodePreference.Random; + return this; + } + + /// + /// Whether to prioritize choosing a slave node that's alive from the known nodes. + /// + /// A for further configuration. + public ConnectionSettingsBuilder PreferSlaveNode() + { + _nodePreference = NodePreference.Slave; return this; } @@ -454,7 +464,7 @@ public ConnectionSettings Build() _maxDiscoverAttempts, _gossipExternalHttpPort, _gossipTimeout, - _preferRandomNode); + _nodePreference); } } } \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs index 3786afc..837967d 100644 --- a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs @@ -14,7 +14,7 @@ public class DnsClusterSettingsBuilder private int _maxDiscoverAttempts = Consts.DefaultMaxClusterDiscoverAttempts; private int _managerExternalHttpPort = Consts.DefaultClusterManagerExternalHttpPort; private TimeSpan _gossipTimeout = TimeSpan.FromSeconds(1); - private bool _preferRandomNode = false; + private NodePreference _nodePreference = NodePreference.Master; /// /// Sets the DNS name under which cluster nodes are listed. @@ -60,7 +60,17 @@ public DnsClusterSettingsBuilder SetGossipTimeout(TimeSpan timeout) /// A for further configuration. public DnsClusterSettingsBuilder PreferRandomNode() { - _preferRandomNode = true; + _nodePreference = NodePreference.Random; + return this; + } + + /// + /// Whether to prioritize choosing a slave node that's alive from the known nodes. + /// + /// A for further configuration. + public DnsClusterSettingsBuilder PreferSlaveNode() + { + _nodePreference = NodePreference.Slave; return this; } @@ -103,7 +113,7 @@ public ClusterSettings Build() { this._maxDiscoverAttempts, this._managerExternalHttpPort, this._gossipTimeout, - this._preferRandomNode); + this._nodePreference); } } } \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index 28867be..85a3855 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -101,12 +101,12 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings connectionSettings.ClientConnectionTimeout, connectionSettings.ClusterDns, connectionSettings.GossipSeeds, connectionSettings.MaxDiscoverAttempts, connectionSettings.ExternalGossipPort, connectionSettings.GossipTimeout, - connectionSettings.PreferRandomNode); + connectionSettings.NodePreference); } if (scheme == "discover") { var clusterSettings = new ClusterSettings(uri.Host, connectionSettings.MaxDiscoverAttempts, uri.Port, - connectionSettings.GossipTimeout, connectionSettings.PreferRandomNode); + connectionSettings.GossipTimeout, connectionSettings.NodePreference); Ensure.NotNull(connectionSettings, "connectionSettings"); Ensure.NotNull(clusterSettings, "clusterSettings"); @@ -116,7 +116,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings clusterSettings.ExternalGossipPort, clusterSettings.GossipSeeds, clusterSettings.GossipTimeout, - clusterSettings.PreferRandomNode); + clusterSettings.NodePreference); return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); @@ -134,7 +134,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings var clusterSettings = new ClusterSettings(connectionSettings.GossipSeeds, connectionSettings.MaxDiscoverAttempts, connectionSettings.GossipTimeout, - connectionSettings.PreferRandomNode); + connectionSettings.NodePreference); Ensure.NotNull(connectionSettings, "connectionSettings"); Ensure.NotNull(clusterSettings, "clusterSettings"); @@ -144,7 +144,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings clusterSettings.ExternalGossipPort, clusterSettings.GossipSeeds, clusterSettings.GossipTimeout, - clusterSettings.PreferRandomNode); + clusterSettings.NodePreference); return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); @@ -210,7 +210,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings clusterSettings.ExternalGossipPort, clusterSettings.GossipSeeds, clusterSettings.GossipTimeout, - clusterSettings.PreferRandomNode); + clusterSettings.NodePreference); return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); } diff --git a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs index 450547b..105864a 100644 --- a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs @@ -13,7 +13,7 @@ public class GossipSeedClusterSettingsBuilder private GossipSeed[] _gossipSeeds; private TimeSpan _gossipTimeout = TimeSpan.FromSeconds(1); private int _maxDiscoverAttempts = Consts.DefaultMaxClusterDiscoverAttempts; - private bool _preferRandomNode = false; + private NodePreference _nodePreference = NodePreference.Master; /// /// Sets gossip seed endpoints for the client. @@ -82,7 +82,17 @@ public GossipSeedClusterSettingsBuilder SetGossipTimeout(TimeSpan timeout) /// A for further configuration. public GossipSeedClusterSettingsBuilder PreferRandomNode() { - _preferRandomNode = true; + _nodePreference = NodePreference.Random; + return this; + } + + /// + /// hether to prioritize choosing a slave node that's alive from the known nodes. + /// + /// A for further configuration. + public GossipSeedClusterSettingsBuilder PreferSlaveNode() + { + _nodePreference = NodePreference.Slave; return this; } @@ -100,7 +110,7 @@ public static implicit operator ClusterSettings(GossipSeedClusterSettingsBuilder /// Builds a object from a . /// public ClusterSettings Build() { - return new ClusterSettings(this._gossipSeeds, this._maxDiscoverAttempts, this._gossipTimeout, this._preferRandomNode); + return new ClusterSettings(this._gossipSeeds, this._maxDiscoverAttempts, this._gossipTimeout, this._nodePreference); } } } diff --git a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs index 7df33d9..d76af0c 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs @@ -23,7 +23,7 @@ internal class ClusterDnsEndPointDiscoverer: IEndPointDiscoverer private readonly HttpAsyncClient _client; private ClusterMessages.MemberInfoDto[] _oldGossip; private TimeSpan _gossipTimeout; - private readonly bool _preferRandomNode; + private readonly NodePreference _nodePreference; public ClusterDnsEndPointDiscoverer(ILogger log, string clusterDns, @@ -31,7 +31,7 @@ public ClusterDnsEndPointDiscoverer(ILogger log, int managerExternalHttpPort, GossipSeed[] gossipSeeds, TimeSpan gossipTimeout, - bool preferRandomNode) + NodePreference nodePreference) { Ensure.NotNull(log, "log"); @@ -41,7 +41,7 @@ public ClusterDnsEndPointDiscoverer(ILogger log, _managerExternalHttpPort = managerExternalHttpPort; _gossipSeeds = gossipSeeds; _gossipTimeout = gossipTimeout; - _preferRandomNode = preferRandomNode; + _nodePreference = nodePreference; _client = new HttpAsyncClient(_gossipTimeout); } @@ -83,7 +83,7 @@ public async Task DiscoverAsync(IPEndPoint failedTcpEndPoint ) if (gossip == null || gossip.Members == null || gossip.Members.Length == 0) continue; - var bestNode = TryDetermineBestNode(gossip.Members, _preferRandomNode); + var bestNode = TryDetermineBestNode(gossip.Members, _nodePreference); if (bestNode != null) { _oldGossip = gossip.Members; @@ -210,7 +210,7 @@ private ClusterMessages.ClusterInfoDto TryGetGossipFrom(GossipSeed endPoint) return result; } - private NodeEndPoints? TryDetermineBestNode(IEnumerable members, bool preferRandomNode) + private NodeEndPoints? TryDetermineBestNode(IEnumerable members, NodePreference nodePreference) { var notAllowedStates = new[] { @@ -222,14 +222,20 @@ private ClusterMessages.ClusterInfoDto TryGetGossipFrom(GossipSeed endPoint) .Where(x => !notAllowedStates.Contains(x.State)) .OrderByDescending(x => x.State) .ToArray(); - if (preferRandomNode) + + switch (nodePreference) { - RandomShuffle(nodes, 0, nodes.Length - 1); + case NodePreference.Random: + RandomShuffle(nodes, 0, nodes.Length - 1); + break; + case NodePreference.Slave: + nodes = nodes.OrderBy(nodeEntry => nodeEntry.State != ClusterMessages.VNodeState.Slave).ToArray(); // OrderBy is a stable sort and only affects order of matching entries + break; } var node = nodes.FirstOrDefault(); - if (node == null) + if (node == default(ClusterMessages.MemberInfoDto)) { //_log.Info("Unable to locate suitable node. Gossip info:\n{0}.", string.Join("\n", members.Select(x => x.ToString()))); return null; @@ -243,4 +249,4 @@ private ClusterMessages.ClusterInfoDto TryGetGossipFrom(GossipSeed endPoint) return new NodeEndPoints(normTcp, secTcp); } } -} +} \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/NodePreference.cs b/src/EventStore.ClientAPI.NetCore/NodePreference.cs new file mode 100644 index 0000000..a7c5544 --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/NodePreference.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EventStore.ClientAPI +{ + /// + /// Indicates which order of preferred nodes for connecting to. + /// + public enum NodePreference + { + /// + /// When attempting connnection, prefers master node. + /// + Master, + /// + /// When attempting connnection, prefers slave node. + /// + Slave, + /// + /// When attempting connnection, has no node preference. + /// + Random + } +} From 4fbf7023485788be6d656d29181e1017152cd1c8 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 3 Sep 2018 11:11:40 +0100 Subject: [PATCH 34/44] Fixes issue with nunit trying to write output on 2 threads --- .../transaction.cs | 84 +++++++++---------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs b/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs index 0b31aff..aee95bb 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/transaction.cs @@ -1,18 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using EventStore.ClientAPI; using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Exceptions; using EventStore.Core.Tests.ClientAPI.Helpers; using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace EventStore.Core.Tests.ClientAPI { [TestFixture, Category("LongRunning")] - public class transaction + public class transaction { protected virtual IEventStoreConnection BuildConnection() @@ -30,7 +30,7 @@ public void should_start_on_non_existing_stream_with_correct_exp_ver_and_create_ store.ConnectAsync().Wait(); using (var transaction = store.StartTransactionAsync(stream, ExpectedVersion.NoStream).Result) { - transaction.WriteAsync(new[] {TestEvent.NewTestEvent()}).Wait(); + transaction.WriteAsync(new[] { TestEvent.NewTestEvent() }).Wait(); Assert.AreEqual(0, transaction.CommitAsync().Result.NextExpectedVersion); } } @@ -46,7 +46,7 @@ public void should_start_on_non_existing_stream_with_exp_ver_any_and_create_stre store.ConnectAsync().Wait(); using (var transaction = store.StartTransactionAsync(stream, ExpectedVersion.Any).Result) { - transaction.WriteAsync(new[] {TestEvent.NewTestEvent()}).Wait(); + transaction.WriteAsync(new[] { TestEvent.NewTestEvent() }).Wait(); Assert.AreEqual(0, transaction.CommitAsync().Result.NextExpectedVersion); } } @@ -134,53 +134,51 @@ public void should_commit_when_writing_with_exp_ver_any_even_while_somene_is_wri const int totalTranWrites = 500; const int totalPlainWrites = 500; - + //500 events during transaction ThreadPool.QueueUserWorkItem(_ => { - Assert.DoesNotThrow(() => { - using (var store = BuildConnection()) + using (var store = BuildConnection()) + { + store.ConnectAsync().Wait(); + using (var transaction = store.StartTransactionAsync(stream, ExpectedVersion.Any).Result) { - store.ConnectAsync().Wait(); - using (var transaction = store.StartTransactionAsync(stream, ExpectedVersion.Any).Result) - { - - var writes = new List(); - for (int i = 0; i < totalTranWrites; i++) - { - writes.Add(transaction.WriteAsync(TestEvent.NewTestEvent(i.ToString(), "trans write"))); - } - Task.WaitAll(writes.ToArray()); - transaction.CommitAsync().Wait(); - transWritesCompleted.Set(); + var writes = new List(); + for (int i = 0; i < totalTranWrites; i++) + { + writes.Add(transaction.WriteAsync(TestEvent.NewTestEvent(i.ToString(), "trans write"))); } + + Task.WaitAll(writes.ToArray()); + transaction.CommitAsync().Wait(); + transWritesCompleted.Set(); } - }); + } + }); //500 events to same stream in parallel ThreadPool.QueueUserWorkItem(_ => { - Assert.DoesNotThrow(() => { - using (var store = BuildConnection()) + using (var store = BuildConnection()) + { + store.ConnectAsync().Wait(); + var writes = new List(); + for (int i = 0; i < totalPlainWrites; i++) { - store.ConnectAsync().Wait(); - var writes = new List(); - for (int i = 0; i < totalPlainWrites; i++) - { - writes.Add(store.AppendToStreamAsync(stream, - ExpectedVersion.Any, - new[] {TestEvent.NewTestEvent(i.ToString(), "plain write")})); - } - Task.WaitAll(writes.ToArray()); - writesToSameStreamCompleted.Set(); + writes.Add(store.AppendToStreamAsync(stream, + ExpectedVersion.Any, + new[] { TestEvent.NewTestEvent(i.ToString(), "plain write") })); } - }); + + Task.WaitAll(writes.ToArray()); + writesToSameStreamCompleted.Set(); + } }); - transWritesCompleted.Wait(); - writesToSameStreamCompleted.Wait(); + Assert.DoesNotThrow(() => transWritesCompleted.Wait()); + Assert.DoesNotThrow(() => writesToSameStreamCompleted.Wait()); // check all written using (var store = BuildConnection()) @@ -206,7 +204,7 @@ public void should_fail_to_commit_if_started_with_correct_ver_but_committing_wit store.ConnectAsync().Wait(); using (var transaction = store.StartTransactionAsync(stream, ExpectedVersion.EmptyStream).Result) { - store.AppendToStreamAsync(stream, ExpectedVersion.EmptyStream, new[] {TestEvent.NewTestEvent()}).Wait(); + store.AppendToStreamAsync(stream, ExpectedVersion.EmptyStream, new[] { TestEvent.NewTestEvent() }).Wait(); transaction.WriteAsync(TestEvent.NewTestEvent()).Wait(); Assert.That(() => transaction.CommitAsync().Wait(), Throws.Exception.TypeOf().With.InnerException.TypeOf()); @@ -223,7 +221,7 @@ public void should_not_fail_to_commit_if_started_with_wrong_ver_but_committing_w store.ConnectAsync().Wait(); using (var transaction = store.StartTransactionAsync(stream, 0).Result) { - store.AppendToStreamAsync(stream, ExpectedVersion.EmptyStream, new[] {TestEvent.NewTestEvent()}).Wait(); + store.AppendToStreamAsync(stream, ExpectedVersion.EmptyStream, new[] { TestEvent.NewTestEvent() }).Wait(); transaction.WriteAsync(TestEvent.NewTestEvent()).Wait(); Assert.AreEqual(1, transaction.CommitAsync().Result.NextExpectedVersion); } @@ -259,11 +257,11 @@ public void idempotency_is_correct_for_explicit_transactions_with_expected_versi var e = new EventData(Guid.NewGuid(), "SomethingHappened", true, Helper.UTF8NoBom.GetBytes("{Value:42}"), null); var transaction1 = store.StartTransactionAsync(streamId, ExpectedVersion.Any).Result; - transaction1.WriteAsync(new[] {e}).Wait(); + transaction1.WriteAsync(new[] { e }).Wait(); Assert.AreEqual(0, transaction1.CommitAsync().Result.NextExpectedVersion); var transaction2 = store.StartTransactionAsync(streamId, ExpectedVersion.Any).Result; - transaction2.WriteAsync(new[] {e}).Wait(); + transaction2.WriteAsync(new[] { e }).Wait(); Assert.AreEqual(0, transaction2.CommitAsync().Result.NextExpectedVersion); var res = store.ReadStreamEventsForwardAsync(streamId, 0, 100, false).Result; From eea7d39998f946e7c73b70528437b17d60532f32 Mon Sep 17 00:00:00 2001 From: James Geall Date: Mon, 3 Sep 2018 11:46:47 +0100 Subject: [PATCH 35/44] Fix PreferSlaveNode to randomize slave node order This prevents preference of a single slave. --- .../Internal/ClusterDnsEndPointDiscoverer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs index d76af0c..661d12e 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs @@ -230,6 +230,7 @@ private ClusterMessages.ClusterInfoDto TryGetGossipFrom(GossipSeed endPoint) break; case NodePreference.Slave: nodes = nodes.OrderBy(nodeEntry => nodeEntry.State != ClusterMessages.VNodeState.Slave).ToArray(); // OrderBy is a stable sort and only affects order of matching entries + RandomShuffle(nodes, 0, nodes.Count(nodeEntry => nodeEntry.State == ClusterMessages.VNodeState.Slave) - 1); break; } From dee8accd50a9be837b3a58ca48e5ca850d60ca53 Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 6 Sep 2018 05:59:22 +0300 Subject: [PATCH 36/44] Remove Thread.Sleep from ClientAPI --- .../EventStoreCatchUpSubscription.cs | 4 +- .../EventStorePersistentSubscriptionBase.cs | 2 +- .../Internal/EventStoreNodeConnection.cs | 132 ++++++++++-------- .../read_all_events_backward_should.cs | 2 +- .../read_all_events_forward_should.cs | 2 +- .../read_event_should.cs | 6 +- .../read_event_stream_backward_should.cs | 4 +- .../read_event_stream_forward_should.cs | 6 +- 8 files changed, 84 insertions(+), 74 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs index d5fb49d..98fac26 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreCatchUpSubscription.cs @@ -455,7 +455,7 @@ private async Task ProcessEventsAsync(long? lastCommitPosition, AllEventsS : slice.NextPosition >= new Position(lastCommitPosition.Value, lastCommitPosition.Value); if (!done && slice.IsEndOfStream) - Thread.Sleep(1); // we are waiting for server to flush its data + await Task.Delay(1).ConfigureAwait(false); // we are waiting for server to flush its data return done; } @@ -595,7 +595,7 @@ private async Task ProcessEventsAsync(long? lastEventNumber, StreamEventsS } if (!done && slice.IsEndOfStream) - Thread.Sleep(1); // we are waiting for server to flush its data + await Task.Delay(1).ConfigureAwait(false); // we are waiting for server to flush its data return done; } diff --git a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs index b97640c..0a37376 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStorePersistentSubscriptionBase.cs @@ -197,7 +197,7 @@ private async void ProcessQueue() { if (_subscription == null) { - Thread.Sleep(1); + await Task.Delay(1).ConfigureAwait(false); } else { diff --git a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs index dafa923..a9058f6 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/EventStoreNodeConnection.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using EventStore.ClientAPI.ClientOperations; using EventStore.ClientAPI.Common; @@ -80,14 +79,15 @@ public Task DeleteStreamAsync(string stream, long expectedVersion, return DeleteStreamAsync(stream, expectedVersion, false, userCredentials); } - public Task DeleteStreamAsync(string stream, long expectedVersion, bool hardDelete, UserCredentials userCredentials = null) + public async Task DeleteStreamAsync(string stream, long expectedVersion, bool hardDelete, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new DeleteStreamOperation(Settings.Log, source, Settings.RequireMaster, - stream, expectedVersion, hardDelete, userCredentials)); - return source.Task; + var operation = new DeleteStreamOperation(Settings.Log, source, Settings.RequireMaster, + stream, expectedVersion, hardDelete, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } public Task AppendToStreamAsync(string stream, long expectedVersion, params EventData[] events) @@ -106,20 +106,21 @@ public Task AppendToStreamAsync(string stream, long expectedVersion // ReSharper restore RedundantCast } - public Task AppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null) + public async Task AppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null) { // ReSharper disable PossibleMultipleEnumeration Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new AppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, - stream, expectedVersion, events, userCredentials)); - return source.Task; + var operation = new AppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, + stream, expectedVersion, events, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); // ReSharper restore PossibleMultipleEnumeration } - public Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, + public async Task ConditionalAppendToStreamAsync(string stream, long expectedVersion, IEnumerable events, UserCredentials userCredentials = null) { // ReSharper disable PossibleMultipleEnumeration @@ -127,20 +128,22 @@ public Task ConditionalAppendToStreamAsync(string stream Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new ConditionalAppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, - stream, expectedVersion, events, userCredentials)); - return source.Task; + var operation = new ConditionalAppendToStreamOperation(Settings.Log, source, Settings.RequireMaster, + stream, expectedVersion, events, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); // ReSharper restore PossibleMultipleEnumeration } - public Task StartTransactionAsync(string stream, long expectedVersion, UserCredentials userCredentials = null) + public async Task StartTransactionAsync(string stream, long expectedVersion, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new StartTransactionOperation(Settings.Log, source, Settings.RequireMaster, - stream, expectedVersion, this, userCredentials)); - return source.Task; + var operation = new StartTransactionOperation(Settings.Log, source, Settings.RequireMaster, + stream, expectedVersion, this, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } public EventStoreTransaction ContinueTransaction(long transactionId, UserCredentials userCredentials = null) @@ -149,42 +152,44 @@ public EventStoreTransaction ContinueTransaction(long transactionId, UserCredent return new EventStoreTransaction(transactionId, userCredentials, this); } - Task IEventStoreTransactionConnection.TransactionalWriteAsync(EventStoreTransaction transaction, IEnumerable events, UserCredentials userCredentials) + async Task IEventStoreTransactionConnection.TransactionalWriteAsync(EventStoreTransaction transaction, IEnumerable events, UserCredentials userCredentials) { // ReSharper disable PossibleMultipleEnumeration Ensure.NotNull(transaction, "transaction"); Ensure.NotNull(events, "events"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new TransactionalWriteOperation(Settings.Log, source, Settings.RequireMaster, - transaction.TransactionId, events, userCredentials)); - return source.Task; + var operation = new TransactionalWriteOperation(Settings.Log, source, Settings.RequireMaster, + transaction.TransactionId, events, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + await source.Task.ConfigureAwait(false); // ReSharper restore PossibleMultipleEnumeration } - Task IEventStoreTransactionConnection.CommitTransactionAsync(EventStoreTransaction transaction, UserCredentials userCredentials) + async Task IEventStoreTransactionConnection.CommitTransactionAsync(EventStoreTransaction transaction, UserCredentials userCredentials) { Ensure.NotNull(transaction, "transaction"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new CommitTransactionOperation(Settings.Log, source, Settings.RequireMaster, - transaction.TransactionId, userCredentials)); - return source.Task; + var operation = new CommitTransactionOperation(Settings.Log, source, Settings.RequireMaster, + transaction.TransactionId, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - public Task ReadEventAsync(string stream, long eventNumber, bool resolveLinkTos, UserCredentials userCredentials = null) + public async Task ReadEventAsync(string stream, long eventNumber, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); if (eventNumber < -1) throw new ArgumentOutOfRangeException(nameof(eventNumber)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadEventOperation(Settings.Log, source, stream, eventNumber, resolveLinkTos, Settings.RequireMaster, userCredentials); - EnqueueOperation(operation); - return source.Task; + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - public Task ReadStreamEventsForwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null) + public async Task ReadStreamEventsForwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.Nonnegative(start, "start"); @@ -193,11 +198,11 @@ public Task ReadStreamEventsForwardAsync(string stream, long var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsForwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); - EnqueueOperation(operation); - return source.Task; + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - public Task ReadStreamEventsBackwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null) + public async Task ReadStreamEventsBackwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.Positive(count, "count"); @@ -205,37 +210,37 @@ public Task ReadStreamEventsBackwardAsync(string stream, long var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadStreamEventsBackwardOperation(Settings.Log, source, stream, start, count, resolveLinkTos, Settings.RequireMaster, userCredentials); - EnqueueOperation(operation); - return source.Task; + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - public Task ReadAllEventsForwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) + public async Task ReadAllEventsForwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.Positive(maxCount, "maxCount"); if (maxCount > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsForwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); - EnqueueOperation(operation); - return source.Task; + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - public Task ReadAllEventsBackwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) + public async Task ReadAllEventsBackwardAsync(Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null) { Ensure.Positive(maxCount, "maxCount"); if (maxCount > ClientApiConstants.MaxReadSize) throw new ArgumentException(string.Format("Count should be less than {0}. For larger reads you should page.", ClientApiConstants.MaxReadSize)); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var operation = new ReadAllEventsBackwardOperation(Settings.Log, source, position, maxCount, resolveLinkTos, Settings.RequireMaster, userCredentials); - EnqueueOperation(operation); - return source.Task; + await EnqueueOperation(operation).ConfigureAwait(false); + return await source.Task.ConfigureAwait(false); } - private void EnqueueOperation(IClientOperation operation) + private async Task EnqueueOperation(IClientOperation operation) { while (_handler.TotalOperationCount >= Settings.MaxQueueSize) { - Thread.Sleep(1); + await Task.Delay(1).ConfigureAwait(false); } _handler.EnqueueMessage(new StartOperationMessage(operation, Settings.MaxRetries, Settings.OperationTimeout)); } @@ -403,23 +408,25 @@ public EventStorePersistentSubscription ConnectToPersistentSubscriptionForAll( */ - public Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) { + public async Task CreatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new CreatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); - return source.Task; + var operation = new CreatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials); + await EnqueueOperation(operation).ConfigureAwait(false); + await source.Task.ConfigureAwait(false); } - public Task UpdatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) + public async Task UpdatePersistentSubscriptionAsync(string stream, string groupName, PersistentSubscriptionSettings settings, UserCredentials credentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); Ensure.NotNull(settings, "settings"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new UpdatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials)); - return source.Task; + var operation = new UpdatePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, settings, credentials); + await EnqueueOperation(operation).ConfigureAwait(false); + await source.Task.ConfigureAwait(false); } /* @@ -432,13 +439,14 @@ public Task CreatePersistentSubscriptionForA return source.Task; } - */ - public Task DeletePersistentSubscriptionAsync(string stream, string groupName, UserCredentials userCredentials = null) { +*/ + public async Task DeletePersistentSubscriptionAsync(string stream, string groupName, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); Ensure.NotNullOrEmpty(groupName, "groupName"); var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EnqueueOperation(new DeletePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, userCredentials)); - return source.Task; + var operation = new DeletePersistentSubscriptionOperation(Settings.Log, source, stream, groupName, userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + await source.Task.ConfigureAwait(false); } /* @@ -457,7 +465,7 @@ public Task SetStreamMetadataAsync(string stream, long expectedMeta return SetStreamMetadataAsync(stream, expectedMetastreamVersion, metadata.AsJsonBytes(), userCredentials); } - public Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, byte[] metadata, UserCredentials userCredentials = null) + public async Task SetStreamMetadataAsync(string stream, long expectedMetastreamVersion, byte[] metadata, UserCredentials userCredentials = null) { Ensure.NotNullOrEmpty(stream, "stream"); if (SystemStreams.IsMetastream(stream)) @@ -466,14 +474,16 @@ public Task SetStreamMetadataAsync(string stream, long expectedMeta var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var metaevent = new EventData(Guid.NewGuid(), SystemEventTypes.StreamMetadata, true, metadata ?? Empty.ByteArray, null); - EnqueueOperation(new AppendToStreamOperation(Settings.Log, - source, - Settings.RequireMaster, - SystemStreams.MetastreamOf(stream), - expectedMetastreamVersion, - new[] { metaevent }, - userCredentials)); - return source.Task; + var operation = new AppendToStreamOperation(Settings.Log, + source, + Settings.RequireMaster, + SystemStreams.MetastreamOf(stream), + expectedMetastreamVersion, + new[] {metaevent}, + userCredentials); + await EnqueueOperation(operation).ConfigureAwait(false); + + return await source.Task.ConfigureAwait(false); } public Task GetStreamMetadataAsync(string stream, UserCredentials userCredentials = null) diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs index aa2d157..a4b6ff2 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_backward_should.cs @@ -99,7 +99,7 @@ public void be_able_to_read_events_slice_at_time() public void throw_when_got_int_max_value_as_maxcount() { - Assert.Throws( + Assert.ThrowsAsync( () => _conn.ReadAllEventsBackwardAsync(Position.Start, int.MaxValue, resolveLinkTos: false)); } } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs index 3b2242a..8bd70a4 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_all_events_forward_should.cs @@ -96,7 +96,7 @@ public void return_partial_slice_if_not_enough_events() [Category("Network")] public void throw_when_got_int_max_value_as_maxcount() { - Assert.Throws( + Assert.ThrowsAsync( () => _conn.ReadAllEventsForwardAsync(Position.Start, int.MaxValue, resolveLinkTos: false)); } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs index c5f9e3e..f0bafbd 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_should.cs @@ -26,19 +26,19 @@ protected override void When() [Test, Category("Network")] public void throw_if_stream_id_is_null() { - Assert.Throws(() => _conn.ReadEventAsync(null, 0, resolveLinkTos: false)); + Assert.ThrowsAsync(() => _conn.ReadEventAsync(null, 0, resolveLinkTos: false)); } [Test, Category("Network")] public void throw_if_stream_id_is_empty() { - Assert.Throws(() => _conn.ReadEventAsync("", 0, resolveLinkTos: false)); + Assert.ThrowsAsync(() => _conn.ReadEventAsync("", 0, resolveLinkTos: false)); } [Test, Category("Network")] public void throw_if_event_number_is_less_than_minus_one() { - Assert.Throws(() => _conn.ReadEventAsync("stream", -2, resolveLinkTos: false)); + Assert.ThrowsAsync(() => _conn.ReadEventAsync("stream", -2, resolveLinkTos: false)); } [Test, Category("Network")] diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs index f474770..82260aa 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_backward_should.cs @@ -23,7 +23,7 @@ public void throw_if_count_le_zero() using (var store = BuildConnection()) { store.ConnectAsync().Wait(); - Assert.Throws(() => store.ReadStreamEventsBackwardAsync(stream, 0, 0, resolveLinkTos: false)); + Assert.ThrowsAsync(() => store.ReadStreamEventsBackwardAsync(stream, 0, 0, resolveLinkTos: false)); } } @@ -206,7 +206,7 @@ public void throw_when_got_int_max_value_as_maxcount() { store.ConnectAsync().Wait(); - Assert.Throws(() => store.ReadStreamEventsBackwardAsync("foo", StreamPosition.Start, int.MaxValue, resolveLinkTos: false)); + Assert.ThrowsAsync(() => store.ReadStreamEventsBackwardAsync("foo", StreamPosition.Start, int.MaxValue, resolveLinkTos: false)); } } diff --git a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs index d77bb41..5fc5f4e 100644 --- a/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs +++ b/test/EventStore.ClientAPI.NetCore.Tests/read_event_stream_forward_should.cs @@ -23,7 +23,7 @@ public void throw_if_count_le_zero() using (var store = BuildConnection()) { store.ConnectAsync().Wait(); - Assert.Throws(() => store.ReadStreamEventsForwardAsync(stream, 0, 0, resolveLinkTos: false)); + Assert.ThrowsAsync(() => store.ReadStreamEventsForwardAsync(stream, 0, 0, resolveLinkTos: false)); } } @@ -35,7 +35,7 @@ public void throw_if_start_lt_zero() using (var store = BuildConnection()) { store.ConnectAsync().Wait(); - Assert.Throws(() => store.ReadStreamEventsForwardAsync(stream, -1, 1, resolveLinkTos: false)); + Assert.ThrowsAsync(() => store.ReadStreamEventsForwardAsync(stream, -1, 1, resolveLinkTos: false)); } } @@ -138,7 +138,7 @@ public void throw_when_got_int_max_value_as_maxcount() { store.ConnectAsync().Wait(); - Assert.Throws(() => store.ReadStreamEventsForwardAsync("foo", StreamPosition.Start, int.MaxValue, resolveLinkTos: false)); + Assert.ThrowsAsync(() => store.ReadStreamEventsForwardAsync("foo", StreamPosition.Start, int.MaxValue, resolveLinkTos: false)); } } From 36091144db880a7dbf5a7efe42249b99634cbc9c Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 6 Sep 2018 14:41:13 +0300 Subject: [PATCH 37/44] KeepDiscovering option addedfor infinte nodes discovery attempts --- .../DnsClusterSettingsBuilder.cs | 10 ++++++++++ .../GossipSeedClusterSettingsBuilder.cs | 10 ++++++++++ .../Internal/ClusterDnsEndPointDiscoverer.cs | 10 +++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs index 837967d..9c0c2a1 100644 --- a/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/DnsClusterSettingsBuilder.cs @@ -54,6 +54,16 @@ public DnsClusterSettingsBuilder SetGossipTimeout(TimeSpan timeout) return this; } + /// + /// Allows infinite nodes discovery attempts. + /// + /// A for further configuration. + public DnsClusterSettingsBuilder KeepDiscovering() + { + _maxDiscoverAttempts = Int32.MaxValue; + return this; + } + /// /// Whether to randomly choose a node that's alive from the known nodes. /// diff --git a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs index 105864a..32f96d2 100644 --- a/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/GossipSeedClusterSettingsBuilder.cs @@ -50,6 +50,16 @@ public GossipSeedClusterSettingsBuilder SetGossipSeedEndPoints(params GossipSeed _gossipSeeds = gossipSeeds; return this; } + + /// + /// Allows infinite nodes discovery attempts. + /// + /// A for further configuration. + public GossipSeedClusterSettingsBuilder KeepDiscovering() + { + _maxDiscoverAttempts = Int32.MaxValue; + return this; + } /// /// Sets the maximum number of attempts for discovery. diff --git a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs index 661d12e..859a89a 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs @@ -47,6 +47,9 @@ public ClusterDnsEndPointDiscoverer(ILogger log, public async Task DiscoverAsync(IPEndPoint failedTcpEndPoint ) { + var maxDiscoverAttemptsStr = ""; + if(_maxDiscoverAttempts != Int32.MaxValue) + maxDiscoverAttemptsStr = "/" + _maxDiscoverAttempts; for (int attempt = 1; attempt <= _maxDiscoverAttempts; ++attempt) { //_log.Info("Discovering cluster. Attempt {0}/{1}...", attempt, _maxDiscoverAttempts); @@ -55,18 +58,19 @@ public async Task DiscoverAsync(IPEndPoint failedTcpEndPoint ) var endPoints = await DiscoverEndPoint(failedTcpEndPoint).ConfigureAwait(false); if (endPoints != null) { - _log.Info("Discovering attempt {0}/{1} successful: best candidate is {2}.", attempt, _maxDiscoverAttempts, endPoints); + _log.Info("Discovering attempt {0}{1} successful: best candidate is {2}.", attempt, maxDiscoverAttemptsStr, endPoints); return endPoints.Value; } _log.Info("Discovering attempt {0}/{1} failed: no candidate found.", attempt, _maxDiscoverAttempts); + } catch (Exception exc) { - _log.Info("Discovering attempt {0}/{1} failed with error: {2}.", attempt, _maxDiscoverAttempts, exc); + _log.Info("Discovering attempt {0}{1} failed with error: {2}.", attempt, maxDiscoverAttemptsStr, exc); } - Thread.Sleep(500); + await Task.Delay(500); } throw new ClusterException(string.Format("Failed to discover candidate in {0} attempts.", _maxDiscoverAttempts)); } From 515fc18ddd1f4a347d50df2227e91806444ffedb Mon Sep 17 00:00:00 2001 From: James Geall Date: Thu, 6 Sep 2018 23:24:51 +0100 Subject: [PATCH 38/44] Add operation timeouts facility --- .../ConnectionSettings.cs | 6 +++ .../ConnectionSettingsBuilder.cs | 13 +++++++ .../EventStoreConnection.cs | 2 +- .../Exceptions/OperationExpiredException.cs | 35 +++++++++++++++++ .../Internal/ClusterDnsEndPointDiscoverer.cs | 2 +- .../Internal/Consts.cs | 1 + .../Internal/OperationsManager.cs | 39 +++++++++++++++++-- 7 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/Exceptions/OperationExpiredException.cs diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs index 5803a8e..5397411 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettings.cs @@ -61,6 +61,10 @@ public static ConnectionSettingsBuilder Create() /// public readonly TimeSpan ReconnectionDelay; /// + /// The amount of time a request for an operation is permitted to be queued awaiting transmission to the server. + /// + public readonly TimeSpan QueueTimeout; + /// /// The amount of time before an operation is considered to have timed out. /// public readonly TimeSpan OperationTimeout; @@ -139,6 +143,7 @@ internal ConnectionSettings(ILogger log, int maxReconnections, bool requireMaster, TimeSpan reconnectionDelay, + TimeSpan queueTimeout, TimeSpan operationTimeout, TimeSpan operationTimeoutCheckPeriod, UserCredentials defaultUserCredentials, @@ -173,6 +178,7 @@ internal ConnectionSettings(ILogger log, MaxReconnections = maxReconnections; RequireMaster = requireMaster; ReconnectionDelay = reconnectionDelay; + QueueTimeout = queueTimeout; OperationTimeout = operationTimeout; OperationTimeoutCheckPeriod = operationTimeoutCheckPeriod; ClientConnectionTimeout = clientConnectionTimeout; diff --git a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs index b95ea42..ed8ef6f 100644 --- a/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs +++ b/src/EventStore.ClientAPI.NetCore/ConnectionSettingsBuilder.cs @@ -23,6 +23,7 @@ public class ConnectionSettingsBuilder private bool _requireMaster = Consts.DefaultRequireMaster; private TimeSpan _reconnectionDelay = Consts.DefaultReconnectionDelay; + private TimeSpan _queueTimeout = Consts.DefaultQueueTimeout; private TimeSpan _operationTimeout = Consts.DefaultOperationTimeout; private TimeSpan _operationTimeoutCheckPeriod = Consts.DefaultOperationTimeoutCheckPeriod; @@ -214,6 +215,17 @@ public ConnectionSettingsBuilder SetReconnectionDelayTo(TimeSpan reconnectionDel return this; } + /// + /// Sets the maximum permitted time a request may be queued awaiting transmission; if exceeded an is thrown. + /// + /// + /// + public ConnectionSettingsBuilder SetQueueTimeoutTo(TimeSpan queueTimeout) + { + _queueTimeout = queueTimeout; + return this; + } + /// /// Sets the operation timeout duration. /// @@ -449,6 +461,7 @@ public ConnectionSettings Build() _maxReconnections, _requireMaster, _reconnectionDelay, + _queueTimeout, _operationTimeout, _operationTimeoutCheckPeriod, _defaultUserCredentials, diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index 85a3855..fe76484 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -93,7 +93,7 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings connectionSettings.MaxQueueSize, connectionSettings.MaxConcurrentItems, connectionSettings.MaxRetries, connectionSettings.MaxReconnections, connectionSettings.RequireMaster, connectionSettings.ReconnectionDelay, - connectionSettings.OperationTimeout, + connectionSettings.QueueTimeout, connectionSettings.OperationTimeout, connectionSettings.OperationTimeoutCheckPeriod, credential, connectionSettings.UseSslConnection, connectionSettings.TargetHost, connectionSettings.ValidateServer, connectionSettings.FailOnNoServerResponse, diff --git a/src/EventStore.ClientAPI.NetCore/Exceptions/OperationExpiredException.cs b/src/EventStore.ClientAPI.NetCore/Exceptions/OperationExpiredException.cs new file mode 100644 index 0000000..47abe9f --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/Exceptions/OperationExpiredException.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EventStore.ClientAPI.Exceptions +{ + /// + /// Exception thrown if an operation expires before it can be scheduled. + /// + public class OperationExpiredException : EventStoreConnectionException + { + /// + /// Constructs a new . + /// + public OperationExpiredException() + { + } + + /// + /// Constructs a new . + /// + /// + public OperationExpiredException(string message) : base(message) + { + } + + /// + /// Constructs a new . + /// + public OperationExpiredException(string message, Exception innerException):base(message, innerException) + { + + } + } +} diff --git a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs index 859a89a..f227ffb 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/ClusterDnsEndPointDiscoverer.cs @@ -70,7 +70,7 @@ public async Task DiscoverAsync(IPEndPoint failedTcpEndPoint ) _log.Info("Discovering attempt {0}{1} failed with error: {2}.", attempt, maxDiscoverAttemptsStr, exc); } - await Task.Delay(500); + await Task.Delay(500).ConfigureAwait(false); } throw new ClusterException(string.Format("Failed to discover candidate in {0} attempts.", _maxDiscoverAttempts)); } diff --git a/src/EventStore.ClientAPI.NetCore/Internal/Consts.cs b/src/EventStore.ClientAPI.NetCore/Internal/Consts.cs index e2566e2..23bc70a 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/Consts.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/Consts.cs @@ -12,6 +12,7 @@ internal static class Consts public const bool DefaultRequireMaster = true; public static readonly TimeSpan DefaultReconnectionDelay = TimeSpan.FromMilliseconds(100); + public static readonly TimeSpan DefaultQueueTimeout = TimeSpan.Zero; //unlimited public static readonly TimeSpan DefaultOperationTimeout = TimeSpan.FromSeconds(7); public static readonly TimeSpan DefaultOperationTimeoutCheckPeriod = TimeSpan.FromSeconds(1); diff --git a/src/EventStore.ClientAPI.NetCore/Internal/OperationsManager.cs b/src/EventStore.ClientAPI.NetCore/Internal/OperationsManager.cs index ee9b56f..e86b486 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/OperationsManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/OperationsManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -54,7 +55,7 @@ internal class OperationsManager private readonly string _connectionName; private readonly ConnectionSettings _settings; private readonly Dictionary _activeOperations = new Dictionary(); - private readonly Queue _waitingOperations = new Queue(); + private readonly ConcurrentQueue _waitingOperations = new ConcurrentQueue(); private readonly List _retryPendingOperations = new List(); private readonly object _lock = new object(); private int _totalOperationCount; @@ -82,7 +83,8 @@ public void CleanUp() operation.Operation.Fail(connectionClosedException); } _activeOperations.Clear(); - _waitingOperations.Clear(); + while (_waitingOperations.TryDequeue(out _)) {} + _retryPendingOperations.Clear(); _totalOperationCount = 0; } @@ -175,14 +177,43 @@ public void TryScheduleWaitingOperations(TcpPackageConnection connection) Ensure.NotNull(connection, "connection"); lock(_lock) { - while (_waitingOperations.Count > 0 && _activeOperations.Count < _settings.MaxConcurrentItems) + // We don't want to transmit or retain expired requests, so we trim any from before the cutoff implied by the current time + var cutoff = _settings.QueueTimeout == TimeSpan.Zero ? (DateTime?)null : DateTime.UtcNow - _settings.QueueTimeout; + + OperationItem operation; + while (_activeOperations.Count < _settings.MaxConcurrentItems) + { + if (!_waitingOperations.TryDequeue(out operation)) + break; + if (cutoff == null || !TryExpireItem(cutoff.Value, operation)) + ExecuteOperation(operation, connection); + } + + if (cutoff != null) { - ExecuteOperation(_waitingOperations.Dequeue(), connection); + // In case the active operations queue is at capacity, we trim expired items from the front of the queue + while (_waitingOperations.TryPeek(out operation) && TryExpireItem(cutoff.Value, operation)) + { + _waitingOperations.TryDequeue(out operation); + } } _totalOperationCount = _activeOperations.Count + _waitingOperations.Count; } } + bool TryExpireItem(DateTime cutoffDate, OperationItem operation) + { + if (operation.CreatedTime > cutoffDate) + return false; + + var err = string.Format("EventStoreConnection '{0}': request expired.\n" + + "UTC now: {1:HH:mm:ss.fff}, operation: {2}.", + _connectionName, DateTime.UtcNow, operation); + _settings.Log.Debug(err); + operation.Operation.Fail(new OperationExpiredException(err)); + return true; + } + public void ExecuteOperation(OperationItem operation, TcpPackageConnection connection) { operation.ConnectionId = connection.ConnectionId; operation.LastUpdated = DateTime.UtcNow; From 652a0934928c592ce68622104233346680563876 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 7 Sep 2018 08:50:47 +0100 Subject: [PATCH 39/44] add ability to add custom node discovery --- .../EventStoreConnection.cs | 1 - .../IEndPointDiscoverer.cs | 18 +++++++++++++++ .../Internal/IEndPointDiscoverer.cs | 10 --------- .../Internal/SingleEndpointDiscoverer.cs | 4 +--- .../{Internal => }/NodeEndPoints.cs | 22 +++++++++++++++++-- 5 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs delete mode 100644 src/EventStore.ClientAPI.NetCore/Internal/IEndPointDiscoverer.cs rename src/EventStore.ClientAPI.NetCore/{Internal => }/NodeEndPoints.cs (52%) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index fe76484..ba916a5 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -4,7 +4,6 @@ using EventStore.ClientAPI.Common.Utils; using EventStore.ClientAPI.Internal; using System; -using EventStore.ClientApi.Core.Internal; using EventStore.ClientAPI.SystemData; namespace EventStore.ClientAPI diff --git a/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs new file mode 100644 index 0000000..6f2b7eb --- /dev/null +++ b/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs @@ -0,0 +1,18 @@ +using System.Net; +using System.Threading.Tasks; + +namespace EventStore.ClientAPI +{ + /// + /// Represents a way of discovering cluster endpoints this could be through gossip, consul, text files, etc + /// + public interface IEndPointDiscoverer + { + /// + /// Called to discover a new + /// + /// The The recently failed endpoint + /// + Task DiscoverAsync(IPEndPoint failedTcpEndPoint); + } +} \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/Internal/IEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/IEndPointDiscoverer.cs deleted file mode 100644 index f84f167..0000000 --- a/src/EventStore.ClientAPI.NetCore/Internal/IEndPointDiscoverer.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Net; -using System.Threading.Tasks; - -namespace EventStore.ClientAPI.Internal -{ - internal interface IEndPointDiscoverer - { - Task DiscoverAsync(IPEndPoint failedTcpEndPoint); - } -} \ No newline at end of file diff --git a/src/EventStore.ClientAPI.NetCore/Internal/SingleEndpointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/Internal/SingleEndpointDiscoverer.cs index d161efd..075e026 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/SingleEndpointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/Internal/SingleEndpointDiscoverer.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; -using EventStore.ClientAPI.Internal; -namespace EventStore.ClientApi.Core.Internal +namespace EventStore.ClientAPI.Internal { internal class SingleEndpointDiscoverer : IEndPointDiscoverer { diff --git a/src/EventStore.ClientAPI.NetCore/Internal/NodeEndPoints.cs b/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs similarity index 52% rename from src/EventStore.ClientAPI.NetCore/Internal/NodeEndPoints.cs rename to src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs index 44db2ae..5d7af11 100644 --- a/src/EventStore.ClientAPI.NetCore/Internal/NodeEndPoints.cs +++ b/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs @@ -1,13 +1,28 @@ using System; using System.Net; -namespace EventStore.ClientAPI.Internal +namespace EventStore.ClientAPI { - internal struct NodeEndPoints + /// + /// Represents a node and its possible endpoints + /// + public struct NodeEndPoints { + /// + /// The TCP endpoint of the node. + /// public readonly IPEndPoint TcpEndPoint; + + /// + /// The ssh endpoint of the node. + /// public readonly IPEndPoint SecureTcpEndPoint; + /// + /// Called to create a new NodeEndPoints + /// + /// The tcp endpoint of the node + /// he ssl endpoint of the node public NodeEndPoints(IPEndPoint tcpEndPoint, IPEndPoint secureTcpEndPoint) { if ((tcpEndPoint ?? secureTcpEndPoint) == null) throw new ArgumentException("Both endpoints are null."); @@ -15,6 +30,9 @@ public NodeEndPoints(IPEndPoint tcpEndPoint, IPEndPoint secureTcpEndPoint) SecureTcpEndPoint = secureTcpEndPoint; } + /// + /// Formats as a tring the endpoints + /// public override string ToString() { return string.Format("[{0}, {1}]", From 4c5b7a669cddb0e97c80753bb30300162c9b937e Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 7 Sep 2018 10:17:47 +0100 Subject: [PATCH 40/44] Add a new Create method to EventStoreNodeConnection to support custom IEndPointDiscoverer Fix typos in definitions --- .../EventStoreConnection.cs | 14 ++++++++++++++ .../IEndPointDiscoverer.cs | 6 +++--- src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs | 6 +++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs index ba916a5..342e3d9 100644 --- a/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs +++ b/src/EventStore.ClientAPI.NetCore/EventStoreConnection.cs @@ -213,5 +213,19 @@ public static IEventStoreConnection Create(ConnectionSettings connectionSettings return new EventStoreNodeConnection(connectionSettings, clusterSettings, endPointDiscoverer, connectionName); } + + /// + /// Creates a new using specific and a custom-defined + /// + /// The to apply to the new connection + /// The custom-defined to use for node discovery + /// Optional name of connection (will be generated automatically, if not provided) + /// a new + public static IEventStoreConnection Create(ConnectionSettings connectionSettings, IEndPointDiscoverer endPointDiscoverer, string connectionName = null) + { + Ensure.NotNull(connectionSettings, "settings"); + Ensure.NotNull(endPointDiscoverer, "endPointDiscoverer"); + return new EventStoreNodeConnection(connectionSettings, null, endPointDiscoverer, connectionName); + } } } diff --git a/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs b/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs index 6f2b7eb..e44ac5f 100644 --- a/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs +++ b/src/EventStore.ClientAPI.NetCore/IEndPointDiscoverer.cs @@ -1,17 +1,17 @@ using System.Net; using System.Threading.Tasks; -namespace EventStore.ClientAPI +namespace EventStore.ClientAPI { /// - /// Represents a way of discovering cluster endpoints this could be through gossip, consul, text files, etc + /// Represents a way of discovering cluster endpoints. This could be through gossip, consul, text files, etc /// public interface IEndPointDiscoverer { /// /// Called to discover a new /// - /// The The recently failed endpoint + /// The The recently failed endpoint /// Task DiscoverAsync(IPEndPoint failedTcpEndPoint); } diff --git a/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs b/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs index 5d7af11..523ec5f 100644 --- a/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs +++ b/src/EventStore.ClientAPI.NetCore/NodeEndPoints.cs @@ -9,12 +9,12 @@ namespace EventStore.ClientAPI public struct NodeEndPoints { /// - /// The TCP endpoint of the node. + /// The tcp endpoint of the node. /// public readonly IPEndPoint TcpEndPoint; /// - /// The ssh endpoint of the node. + /// The ssl endpoint of the node. /// public readonly IPEndPoint SecureTcpEndPoint; @@ -31,7 +31,7 @@ public NodeEndPoints(IPEndPoint tcpEndPoint, IPEndPoint secureTcpEndPoint) } /// - /// Formats as a tring the endpoints + /// Formats the endpoints as a string /// public override string ToString() { From e352d01a8aeb4a641fb6253a763d7dd96662f1cc Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 7 Sep 2018 10:26:31 +0100 Subject: [PATCH 41/44] Redirect DebugLogger to Trace for release builds Fixes EventStore/Eventstore#1575 --- .../Common/Log/DebugLogger.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Common/Log/DebugLogger.cs b/src/EventStore.ClientAPI.NetCore/Common/Log/DebugLogger.cs index 91c03dd..d3a803e 100644 --- a/src/EventStore.ClientAPI.NetCore/Common/Log/DebugLogger.cs +++ b/src/EventStore.ClientAPI.NetCore/Common/Log/DebugLogger.cs @@ -6,32 +6,32 @@ class DebugLogger : ILogger { public void Error(string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("ERROR", format, args)); + System.Diagnostics.Trace.WriteLine(Log("ERROR", format, args)); } public void Error(Exception ex, string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("ERROR", ex, format, args)); + System.Diagnostics.Trace.WriteLine(Log("ERROR", ex, format, args)); } public void Debug(string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("DEBUG", format, args)); + System.Diagnostics.Trace.WriteLine(Log("DEBUG", format, args)); } public void Debug(Exception ex, string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("DEBUG", ex, format, args)); + System.Diagnostics.Trace.WriteLine(Log("DEBUG", ex, format, args)); } public void Info(string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("INFO", format, args)); + System.Diagnostics.Trace.WriteLine(Log("INFO", format, args)); } public void Info(Exception ex, string format, params object[] args) { - System.Diagnostics.Debug.WriteLine(Log("INFO", ex, format, args)); + System.Diagnostics.Trace.WriteLine(Log("INFO", ex, format, args)); } From 0ad9c90a1d03206148567900499387962b6aec83 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 7 Sep 2018 10:35:44 +0100 Subject: [PATCH 42/44] fixed small typo --- src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs index 0e5797f..65657f0 100644 --- a/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs +++ b/src/EventStore.ClientAPI.NetCore/Projections/QueryManager.cs @@ -9,7 +9,7 @@ namespace EventStore.ClientAPI.Projections { /// - /// API for executinmg queries in the Event Store through C# code. Communicates + /// API for executing queries in the Event Store through C# code. Communicates /// with the Event Store over the RESTful API. /// public class QueryManager From 48b6ddf2eabf7864b9ddcc99c4f5b3a2f17957c1 Mon Sep 17 00:00:00 2001 From: James Geall Date: Fri, 7 Sep 2018 11:22:38 +0100 Subject: [PATCH 43/44] Handle IPv6 DNS entries Resolves EventStore/EventStore#1598 --- .../Transport.Http/EndpointExtensions.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs b/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs index 622b3e8..2b63e38 100644 --- a/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs +++ b/src/EventStore.ClientAPI.NetCore/Transport.Http/EndpointExtensions.cs @@ -11,7 +11,7 @@ public static string ToHttpUrl(this EndPoint endPoint, string schema, string raw if (endPoint is IPEndPoint) { var ipEndPoint = endPoint as IPEndPoint; - return CreateHttpUrl(schema, ipEndPoint.Address.ToString(), ipEndPoint.Port, rawUrl != null ? rawUrl.TrimStart('/') : string.Empty); + return CreateHttpUrl(schema, ipEndPoint.ToString(), rawUrl != null ? rawUrl.TrimStart('/') : string.Empty); } if (endPoint is DnsEndPoint) { @@ -26,7 +26,7 @@ public static string ToHttpUrl(this EndPoint endPoint, string schema, string for if (endPoint is IPEndPoint) { var ipEndPoint = endPoint as IPEndPoint; - return CreateHttpUrl(schema, ipEndPoint.Address.ToString(), ipEndPoint.Port, string.Format(formatString.TrimStart('/'), args)); + return CreateHttpUrl(schema, ipEndPoint.ToString(), string.Format(formatString.TrimStart('/'), args)); } if (endPoint is DnsEndPoint) { @@ -40,5 +40,10 @@ private static string CreateHttpUrl(string schema, string host, int port, string { return $"{schema}://{host}:{port}/{path}"; } + + private static string CreateHttpUrl(string schema, string address, string path) + { + return $"{schema}://{address}/{path}"; + } } } From 00b83ace32fb26cfd6ed48cf8101ac11c877eda5 Mon Sep 17 00:00:00 2001 From: James Nugent Date: Fri, 15 Feb 2019 10:50:18 -0600 Subject: [PATCH 44/44] Update README.md to deprecate repo --- README.md | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index df57e34..9211760 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,13 @@ -# EventStore .NET Core Client - -Official direct port of the Event Store .NET client to .NET Core targetting .netstandard 2.0 - -Works with EventStore server 4.0.0 and above. +# Deprecated -[![wercker status](https://app.wercker.com/status/21204a69779b2b4543242fd543d0aaab/s/master "wercker status")](https://app.wercker.com/project/byKey/21204a69779b2b4543242fd543d0aaab) -[![Appveyor status](https://ci.appveyor.com/api/projects/status/8tcaw05oa59fkba2/branch/master?svg=true)](https://ci.appveyor.com/project/EventStore/clientapi-netcore/branch/master) - -## Installation - -You can install the Eventstore .NET Core client by copying and pasting the following command into your Package Manager Console within Visual Studio (Tools > NuGet Package Manager > Package Manager Console). +# EventStore .NET Core Client -```bash -Install-Package EventStore.ClientAPI.NetCore -``` +This repository contained an Event Store .NET client for .NET Core, targetting netstandard-2.0. -Alternatively if you're using the .NET Core CLI then you can install the client via the command line interface with the following command: +As of version 5.0.0, the official client maintained as part of [github.com/EventStore/EventStore](github.com/EventStore/EventStore) now targets all supported .NET platforms: -```bash -dotnet add package EventStore.ClientAPI.NetCore -``` +- netstandard2.0 +- net452 +- net46 -For more information see the [EventStore.ClientAPI.NetCore NuGet page](https://www.nuget.org/packages/EventStore.ClientAPI.NetCore/). +This code and repository is not maintained.