public void SetUp() { // Create a response object and get the binary representation of it var streamMessage = new StreamMessage (); var response1 = new Response (); response1.Time = 42; response1.Error = "Foo"; var streamResponse1 = new StreamResponse (); streamResponse1.Id = 1263; var response2 = new Response (); response2.Time = 123; response2.Error = "Bar"; var streamResponse2 = new StreamResponse (); streamResponse2.Id = 3443; streamResponse2.Response = response2; streamMessage.Responses.Add (streamResponse1); streamMessage.Responses.Add (streamResponse2); expectedMessage = streamMessage; using (var stream = new MemoryStream ()) { expectedMessage.WriteDelimitedTo (stream); messageBytes = stream.ToArray (); } }
public void SetUp() { // Create a response object and get the binary representation of it var streamMessageBuilder = StreamMessage.CreateBuilder (); var responseBuilder1 = Response.CreateBuilder (); responseBuilder1.SetTime (42); responseBuilder1.SetError ("Foo"); var streamResponseBuilder1 = StreamResponse.CreateBuilder (); streamResponseBuilder1.SetId (1263); streamResponseBuilder1.SetResponse (responseBuilder1.Build ()); var responseBuilder2 = Response.CreateBuilder (); responseBuilder2.SetTime (123); responseBuilder2.SetError ("Bar"); var streamResponseBuilder2 = StreamResponse.CreateBuilder (); streamResponseBuilder2.SetId (3443); streamResponseBuilder2.SetResponse (responseBuilder2.Build ()); streamMessageBuilder.AddResponses (streamResponseBuilder1.Build ()); streamMessageBuilder.AddResponses (streamResponseBuilder2.Build ()); expectedMessage = streamMessageBuilder.Build (); using (var stream = new MemoryStream ()) { expectedMessage.WriteDelimitedTo (stream); messageBytes = stream.ToArray (); } }
public static Link Self(StreamMessage message) => new Link( Relations.Self, $"{message.StreamId}/{message.StreamVersion}");
protected override async Task <ReadAllPage> ReadAllForwardsInternal( long fromPositionExlusive, int maxCount, bool prefetch, ReadNextAllPage readNext, CancellationToken cancellationToken) { maxCount = maxCount == int.MaxValue ? maxCount - 1 : maxCount; long ordinal = fromPositionExlusive; using (var connection = _createConnection()) { await connection.OpenAsync(cancellationToken).NotOnCapturedContext(); var commandText = prefetch ? _scripts.ReadAllForwardWithData : _scripts.ReadAllForward; using (var command = new SqlCommand(commandText, connection)) { command.Parameters.AddWithValue("ordinal", ordinal); command.Parameters.AddWithValue("count", maxCount + 1); //Read extra row to see if at end or not var reader = await command .ExecuteReaderAsync(cancellationToken) .NotOnCapturedContext(); List <StreamMessage> messages = new List <StreamMessage>(); if (!reader.HasRows) { return(new ReadAllPage( fromPositionExlusive, fromPositionExlusive, true, ReadDirection.Forward, readNext, messages.ToArray())); } while (await reader.ReadAsync(cancellationToken).NotOnCapturedContext()) { if (messages.Count == maxCount) { messages.Add(default(StreamMessage)); } else { var streamId = reader.GetString(0); var streamVersion = reader.GetInt32(1); ordinal = reader.GetInt64(2); var eventId = reader.GetGuid(3); var created = reader.GetDateTime(4); var type = reader.GetString(5); var jsonMetadata = reader.GetString(6); Func <CancellationToken, Task <string> > getJsonData; if (prefetch) { var jsonData = reader.GetString(7); getJsonData = _ => Task.FromResult(jsonData); } else { var streamIdInfo = new StreamIdInfo(streamId); getJsonData = ct => GetJsonData(streamIdInfo.SqlStreamId.Id, streamVersion, ct); } var message = new StreamMessage(streamId, eventId, streamVersion, ordinal, created, type, jsonMetadata, getJsonData); messages.Add(message); } } bool isEnd = true; if (messages.Count == maxCount + 1) // An extra row was read, we're not at the end { isEnd = false; messages.RemoveAt(maxCount); } var nextPosition = messages[messages.Count - 1].Position + 1; return(new ReadAllPage( fromPositionExlusive, nextPosition, isEnd, ReadDirection.Forward, readNext, messages.ToArray())); } } }
public static Link Self(StreamMessage message) => new Link( Constants.Relations.Self, $"streams/{message.StreamId}/{message.StreamVersion}");
private async Task <StreamMessagesPage> ReadStreamInternal( SqlStreamId sqlStreamId, int start, int count, ReadDirection direction, SqlConnection connection, CancellationToken cancellationToken) { // To read backwards from end, need to use int MaxValue var streamVersion = start == StreamVersion.End ? int.MaxValue : start; string commandText; Func <List <StreamMessage>, int> getNextSequenceNumber; if (direction == ReadDirection.Forward) { commandText = _scripts.ReadStreamForward; getNextSequenceNumber = events => events.Last().StreamVersion + 1; } else { commandText = _scripts.ReadStreamBackward; getNextSequenceNumber = events => events.Last().StreamVersion - 1; } using (var command = new SqlCommand(commandText, connection)) { command.Parameters.AddWithValue("streamId", sqlStreamId.Id); command.Parameters.AddWithValue("count", count + 1); //Read extra row to see if at end or not command.Parameters.AddWithValue("StreamVersion", streamVersion); var messages = new List <StreamMessage>(); using (var reader = await command.ExecuteReaderAsync(cancellationToken).NotOnCapturedContext()) { if (!await reader.ReadAsync(cancellationToken).NotOnCapturedContext()) { return(new StreamMessagesPage( sqlStreamId.IdOriginal, PageReadStatus.StreamNotFound, start, -1, -1, direction, isEndOfStream: true)); } // Read Messages result set do { var streamVersion1 = reader.GetInt32(0); var ordinal = reader.GetInt64(1); var eventId = reader.GetGuid(2); var created = reader.GetDateTime(3); var type = reader.GetString(4); var jsonData = reader.GetString(5); var jsonMetadata = reader.GetString(6); var message = new StreamMessage( sqlStreamId.IdOriginal, eventId, streamVersion1, ordinal, created, type, jsonData, jsonMetadata); messages.Add(message); } while(await reader.ReadAsync(cancellationToken).NotOnCapturedContext()); // Read last message revision result set await reader.NextResultAsync(cancellationToken).NotOnCapturedContext(); await reader.ReadAsync(cancellationToken).NotOnCapturedContext(); var lastStreamVersion = reader.GetInt32(0); var isEnd = true; if (messages.Count == count + 1) { isEnd = false; messages.RemoveAt(count); } return(new StreamMessagesPage( sqlStreamId.IdOriginal, PageReadStatus.Success, start, getNextSequenceNumber(messages), lastStreamVersion, direction, isEnd, messages.ToArray())); } } }
public void ShouldGetASnapshotOnInvalidEpoch() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); var provider = new StateManager(_settings.Object, connector.Object); // Please note Sequence = 1 Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; // ...and Sequence = 3 Fixture update = new Fixture { Id = "ABC", Sequence = 3, MatchStatus = ((int)MatchStatus.MatchOver).ToString() }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); // STEP 4: send the update containing a wrong sequence number listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 5: check that ProcessStreamUpdate is called only once (due suspension)! connector.Verify(x => x.Suspend(It.Is<string>(y => y == "ABC"))); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Exactly(2)); resource.Verify(x => x.GetSnapshot(), Times.Exactly(2), "The streamlistener was supposed to acquire a new snapshot"); }
public void ShouldNotSuspendFixtureOnProperDisconnection() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.MarketFiltersDirectory).Returns("."); var provider = new StateManager(_settings.Object, connector.Object); Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(r => r.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object); listener.Start(); // just to be sure that we are streaming listener.IsStreaming.Should().BeTrue(); //Update snapshot sequence fixture.Sequence = 2; resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // send the update that contains the match status change listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); listener.ResourceOnStreamDisconnected(this, EventArgs.Empty); // STEP 3: Check the resoults listener.IsStreaming.Should().BeFalse(); listener.IsFixtureEnded.Should().BeTrue(); // suspend is called when the stream listener correctly handles the "IsFixtureEnded" case, // so we need to make sure that is only called once connector.Verify(x => x.Suspend(It.Is<string>(y => y == "ABC"))); }
public void MarkFixtureAsUnpublishedTest() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.DeltaRuleEnabled).Returns(true); var provider = new StateManager(_settings.Object, connector.Object); //var suspended = false; //Action<IMarketStateCollection> suspension_strategy = x => {suspended = true;}; //suspension.RegisterAction(suspension_strategy, SuspensionReason.FIXTURE_DELETED); // Please note Sequence = 1 Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 }; Market mkt = new Market { Id = "MKT" }; fixture.Markets.Add(mkt); // ...and Sequence = 3 Fixture update = new Fixture { Id = "ABCDE", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new [] {(int)EpochChangeReason.Deleted} }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABCDE"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); // STEP 3: let create at lea listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); connector.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>(y => y.Markets.All(k => k.IsSuspended)), It.IsAny<bool>())); update = new Fixture { Id = "ABCDE", Sequence = 3, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2 }; mkt = new Market {Id = "MKT"}; update.Markets.Add(mkt); update.Tags.Add("tag", "tag"); message = new StreamMessage { Content = update }; listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 4: if the delta rule was executed, the market would have been removed fixture.Markets.FirstOrDefault(x => x.Id == "MKT").Should().NotBeNull(); }
/// <summary> /// Called to parse the message received by the client. /// </summary> /// <param name="message">Request message.</param> public virtual void AcceptMessage(StreamMessage message) { XmlParseResult = Parser.Parse(message, MessageFields, KeyValues); }
public ProcessStreamMessage(StreamMessage message) { Message = message; _source = new TaskCompletionSource <object>(); }
private static void GetPassword(StreamMessage streamMessage, ClientRobot robot) { MessageService.SendPasswordChallenge(streamMessage); ValidPassword(streamMessage, robot); }
private static string GetExpectedPassword(StreamMessage streamMessage) { var asciiSum = streamMessage.AcceptedMessage.AsciiValues.Sum() - Constants.SplitterAscii.Sum(); return(asciiSum.ToString()); }
private static void GetUserName(StreamMessage streamMessage, ClientRobot robot) { MessageService.SendLoginChallenge(streamMessage); ValidUserName(streamMessage, robot); }
private static bool LoginIsValid(string expectedPassword, StreamMessage streamMessage) { return(expectedPassword == streamMessage.AcceptedMessage.DecodedData); }
public void ShouldNotSetIsFixtureEndedIfThereWasAnErrorProcessingSnapshot() { Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); Mock<ISettings> settings = new Mock<ISettings>(); settings.Setup(x => x.MarketFiltersDirectory).Returns("."); var provider = new StateManager(settings.Object,connector.Object); var suspensionManager = new SuspensionManager(provider, connector.Object); Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.SetupSequence(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)).Returns(null); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); // STEP 4: send the update containing a wrong sequence number listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 5: check that ProcessSnapshot is called only twice (first snapshot and when the fixture is ended, we get another one)! connector.Verify(x => x.Suspend(It.Is<string>(y => y == "ABC"))); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Once()); resource.Verify(x => x.GetSnapshot(), Times.AtLeast(2), "The StreamListener was supposed to acquire a new snapshot"); listener.IsFixtureEnded.Should().BeFalse(); listener.IsErrored.Should().BeTrue(); }
public void DoNotSuspendFixtureOnDisconeectIfDeletedTest() { // STEP 1: prepare stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); Mock<ISettings> settings = new Mock<ISettings>(); var provider = new StateManager(settings.Object, connector.Object); // STEP 3: prepare the fixture data Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot fixture.Markets.Add(new Market("MKT-1")); var mkt = new Market("MKT-2"); mkt.AddOrUpdateTagValue("traded_in_play", "false"); fixture.Markets.Add(mkt); // ...and MatchStatus=MatchOver Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 2, LastEpochChangeReason = new[] {(int)EpochChangeReason.Deleted} }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 4: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); // STEP 5: send the update listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 6: check the result, note tha MKT-2 is not in-play connector.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>(y => y.Id == "ABC" && y.Markets.Count == 0), It.IsAny<bool>())); }
public void DontSendSuspensionOnDisposingIfFixtureEndedOrDeletedTest() { // STEP 1: prepare data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); var provider = new StateManager(_settings.Object, connector.Object); bool disposed = false; bool matchover = false; bool deleted = false; Action<IMarketStateCollection> disponsing_strategy = x => {disposed = true;}; Action<IMarketStateCollection> matchover_strategy = x => { matchover = true; }; Action<IMarketStateCollection> deleted_strategy = x => { deleted = true; }; provider.SuspensionManager.RegisterAction(disponsing_strategy, SuspensionReason.FIXTURE_DISPOSING); provider.SuspensionManager.RegisterAction(deleted_strategy, SuspensionReason.FIXTURE_DELETED); provider.SuspensionManager.RegisterAction(matchover_strategy, SuspensionReason.SUSPENSION); Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 }; Market mkt = new Market { Id = "MKT" }; fixture.Markets.Add(mkt); Fixture update = new Fixture { Id = "ABCDE", Sequence = 2, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.Deleted } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABCDE"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); disposed.Should().BeFalse(); matchover.Should().BeFalse(); deleted.Should().BeFalse(); // STEP 3: send a delete command and check the result listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); //Update snapshot sequence fixture.Sequence = 2; resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); disposed.Should().BeFalse(); matchover.Should().BeFalse(); deleted.Should().BeTrue(); // STEP 4: reset the flags and send the dispose command // (no other suspension commands should be raised); disposed = false; matchover = false; deleted = false; listener.Dispose(); deleted.Should().BeFalse(); disposed.Should().BeFalse(); matchover.Should().BeFalse(); // STEP 5: do the same, but for MatchOver disposed = false; matchover = false; deleted = false; listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); disposed.Should().BeFalse(); matchover.Should().BeFalse(); deleted.Should().BeFalse(); update = new Fixture { Id = "ABCDE", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; message = new StreamMessage { Content = update }; // STEP 3: send a delete command and check the result listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); disposed.Should().BeFalse(); matchover.Should().BeTrue(); deleted.Should().BeFalse(); // STEP 4: reset the flags and send the dispose command // (no other suspension commands should be raised); disposed = false; matchover = false; deleted = false; listener.Dispose(); deleted.Should().BeFalse(); disposed.Should().BeFalse(); matchover.Should().BeFalse(); }
public override void Write(StreamMessage value) { codedOutputStream.WriteMessage(value.ToProtobufMessage()); codedOutputStream.Flush(); }
public void ShouldReturnOnAlreadyProcessedSequence() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); IStateManager provider = new StateManager(_settings.Object, connector.Object); // Please note Sequence = 3 Fixture fixture = new Fixture { Id = "ABC", Sequence = 3, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; // ...and Sequence = 2 Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString() }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); resource.Setup(x => x.Id).Returns("ABC"); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); connector.Verify(x => x.ProcessStreamUpdate(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never, "Update should be processed"); }
public void DoNotSuspendFixtureOnDisconnectIfMatchOverTest() { // STEP 1: prepare stub data Mock <IResourceFacade> resource = new Mock <IResourceFacade>(); Mock <IAdapterPlugin> connector = new Mock <IAdapterPlugin>(); Mock <IEventState> state = new Mock <IEventState>(); Mock <ISettings> settings = new Mock <ISettings>(); var provider = new StateManager(settings.Object, connector.Object); provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendInPlayMarketsStrategy, SuspensionReason.DISCONNECT_EVENT); // STEP 3: prepare the fixture data Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot fixture.Markets.Add(new Market("MKT-1")); var mkt = new Market("MKT-2"); mkt.AddOrUpdateTagValue("traded_in_play", "false"); fixture.Markets.Add(mkt); // ...and MatchStatus=MatchOver Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 4: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); //Update snapshot sequence fixture.Sequence = 2; resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 5: send the update listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // check that the fixture got suspended connector.Verify(x => x.Suspend(It.Is <string>(y => y == "ABC"))); connector.Verify(x => x.ProcessStreamUpdate(It.IsAny <Fixture>(), It.IsAny <bool>()), Times.Never); listener.ResourceOnStreamDisconnected(this, EventArgs.Empty); connector.Verify(x => x.ProcessStreamUpdate(It.IsAny <Fixture>(), It.IsAny <bool>()), Times.Never); }
internal void Main() { client = new TcpClient (); client.Connect (address, port); stream = client.GetStream (); stream.Write (Encoder.streamHelloMessage, 0, Encoder.streamHelloMessage.Length); stream.Write (clientIdentifier, 0, clientIdentifier.Length); var recvOkMessage = new byte [Encoder.okMessage.Length]; stream.Read (recvOkMessage, 0, Encoder.okMessage.Length); if (recvOkMessage.Equals (Encoder.okMessage)) throw new Exception ("Invalid hello message received from stream server. " + "Got " + Encoder.ToHexString (recvOkMessage)); this.codedStream = new CodedInputStream (stream); try { while (true) { var message = new StreamMessage (); codedStream.ReadMessage (message); foreach (var response in message.Responses) manager.Update (response.Id, response.Response); } } catch (IOException) { // Exit when the connection closes } }
protected override async Task <ReadAllPage> ReadAllForwardsInternal( long fromPosition, int maxCount, bool prefetch, ReadNextAllPage readNext, CancellationToken cancellationToken) { maxCount = maxCount == int.MaxValue ? maxCount - 1 : maxCount; long position = fromPosition; using (var connection = _createConnection()) { await connection.OpenAsync(cancellationToken).ConfigureAwait(false); var commandText = prefetch ? _scripts.ReadAllForwardWithData : _scripts.ReadAllForward; using (var command = new SqlCommand(commandText, connection)) { command.CommandTimeout = _commandTimeout; command.Parameters.AddWithValue("position", position); command.Parameters.AddWithValue("count", maxCount + 1); //Read extra row to see if at end or not var reader = await command .ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken) .ConfigureAwait(false); if (!reader.HasRows) { return(new ReadAllPage( fromPosition, fromPosition, true, ReadDirection.Forward, readNext, Array.Empty <StreamMessage>())); } var messages = new List <(StreamMessage, int?)>(); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { var ordinal = 0; var streamId = reader.GetString(ordinal++); var maxAge = reader.GetNullableInt32(ordinal++); var streamVersion = reader.GetInt32(ordinal++); position = reader.GetInt64(ordinal++); var eventId = reader.GetGuid(ordinal++); var created = reader.GetDateTime(ordinal++); var type = reader.GetString(ordinal++); var jsonMetadata = reader.GetString(ordinal++); Func <CancellationToken, Task <string> > getJsonData; if (prefetch) { var jsonData = await reader.GetTextReader(ordinal).ReadToEndAsync(); getJsonData = _ => Task.FromResult(jsonData); } else { var streamIdInfo = new StreamIdInfo(streamId); getJsonData = ct => GetJsonData(streamIdInfo.SqlStreamId.Id, streamVersion, ct); } var message = new StreamMessage(streamId, eventId, streamVersion, position, created, type, jsonMetadata, getJsonData); messages.Add((message, maxAge)); } bool isEnd = true; if (messages.Count == maxCount + 1) // An extra row was read, we're not at the end { isEnd = false; messages.RemoveAt(maxCount); } var filteredMessages = FilterExpired(messages); var nextPosition = filteredMessages[filteredMessages.Count - 1].Position + 1; return(new ReadAllPage( fromPosition, nextPosition, isEnd, ReadDirection.Forward, readNext, filteredMessages.ToArray())); } } }
private async Task <ReadStreamPage> ReadStreamInternal( SqlStreamId sqlStreamId, int start, int count, ReadDirection direction, bool prefetch, ReadNextStreamPage readNext, SqlConnection connection, CancellationToken cancellationToken) { // If the count is int.MaxValue, TSql will see it as a negative number. // Users shouldn't be using int.MaxValue in the first place anyway. count = count == int.MaxValue ? count - 1 : count; // To read backwards from end, need to use int MaxValue var streamVersion = start == StreamVersion.End ? int.MaxValue : start; string commandText; Func <List <StreamMessage>, int, int> getNextVersion; if (direction == ReadDirection.Forward) { commandText = prefetch ? _scripts.ReadStreamForwardWithData : _scripts.ReadStreamForward; getNextVersion = (events, lastVersion) => { if (events.Any()) { return(events.Last().StreamVersion + 1); } return(lastVersion + 1); }; } else { commandText = prefetch ? _scripts.ReadStreamBackwardWithData : _scripts.ReadStreamBackward; getNextVersion = (events, lastVersion) => { if (events.Any()) { return(events.Last().StreamVersion - 1); } return(-1); }; } using (var command = new SqlCommand(commandText, connection)) { command.Parameters.AddWithValue("streamId", sqlStreamId.Id); command.Parameters.AddWithValue("count", count + 1); //Read extra row to see if at end or not command.Parameters.AddWithValue("streamVersion", streamVersion); using (var reader = await command.ExecuteReaderAsync(cancellationToken).NotOnCapturedContext()) { await reader.ReadAsync(cancellationToken).NotOnCapturedContext(); if (reader.IsDBNull(0)) { return(new ReadStreamPage( sqlStreamId.IdOriginal, PageReadStatus.StreamNotFound, start, -1, -1, -1, direction, true, readNext)); } var lastStreamVersion = reader.GetInt32(0); var lastStreamPosition = reader.GetInt64(1); await reader.NextResultAsync(cancellationToken).NotOnCapturedContext(); var messages = new List <StreamMessage>(); while (await reader.ReadAsync(cancellationToken).NotOnCapturedContext()) { if (messages.Count == count) { messages.Add(default(StreamMessage)); } else { var streamVersion1 = reader.GetInt32(0); var ordinal = reader.GetInt64(1); var eventId = reader.GetGuid(2); var created = reader.GetDateTime(3); var type = reader.GetString(4); var jsonMetadata = reader.GetString(5); Func <CancellationToken, Task <string> > getJsonData; if (prefetch) { var jsonData = reader.GetString(6); getJsonData = _ => Task.FromResult(jsonData); } else { getJsonData = ct => GetJsonData(sqlStreamId.Id, streamVersion1, ct); } var message = new StreamMessage( sqlStreamId.IdOriginal, eventId, streamVersion1, ordinal, created, type, jsonMetadata, getJsonData); messages.Add(message); } } var isEnd = true; if (messages.Count == count + 1) { isEnd = false; messages.RemoveAt(count); } return(new ReadStreamPage( sqlStreamId.IdOriginal, PageReadStatus.Success, start, getNextVersion(messages, lastStreamVersion), lastStreamVersion, lastStreamPosition, direction, isEnd, readNext, messages.ToArray())); } } }
private async Task <Event> StreamMessageToEvent( StreamMessage streamMessage, CancellationToken cancellationToken) => (Event)JsonConvert.DeserializeObject( await streamMessage.GetJsonData(cancellationToken), _types.TypeFor(streamMessage.Type));
public static Link Feed(StreamMessage message) => new Link( Constants.Relations.Feed, $"streams/{message.StreamId}");
public abstract Task <Task> CustomExcutionMethod(StreamMessage msg, IAsyncStream <StreamMessage> stream);
private bool sendMessage(Friend friend, PendingMessage pending_message, bool add_to_pending_messages = true) { StreamMessage msg = pending_message.streamMessage; bool send_to_server = pending_message.sendToServer; bool send_push_notification = pending_message.sendPushNotification; // TODO this function has to be improved and node's wallet address has to be added if ((friend.publicKey != null && msg.encryptionType == StreamMessageEncryptionCode.rsa) || (msg.encryptionType != StreamMessageEncryptionCode.rsa && friend.aesKey != null && friend.chachaKey != null)) { if (msg.encryptionType == StreamMessageEncryptionCode.none) { // upgrade encryption type msg.encryptionType = StreamMessageEncryptionCode.spixi1; } if (!msg.encrypt(friend.publicKey, friend.aesKey, friend.chachaKey)) { Logging.warn("Could not encrypt message for {0}!", Base58Check.Base58CheckEncoding.EncodePlain(msg.recipient)); return(false); } } else if (msg.encryptionType != StreamMessageEncryptionCode.none) { if (friend.publicKey == null) { byte[] pub_k = FriendList.findContactPubkey(friend.walletAddress); friend.publicKey = pub_k; } Logging.warn("Could not send message to {0}, due to missing encryption keys!", Base58Check.Base58CheckEncoding.EncodePlain(msg.recipient)); return(false); } bool sent = false; string hostname = friend.searchForRelay(); // TODO cuckoo filter should be used instead, need to check the performance when PL is big if (friend.online) { if (hostname != "" && hostname != null) { StreamClientManager.connectTo(hostname, null); // TODO replace null with node address sent = StreamClientManager.sendToClient(hostname, ProtocolMessageCode.s2data, msg.getBytes(), msg.id); if (sent && pending_message.removeAfterSending) { removeMessage(friend, pending_message.streamMessage.id); } } } if (friend.forcePush || !friend.online || !sent) { if (send_to_server) { send_to_server = Config.enablePushNotifications; if (friend.bot) { send_to_server = false; send_push_notification = false; } } if (send_to_server) { if (OfflinePushMessages.sendPushMessage(msg, send_push_notification)) { pending_message.sendToServer = false; if (add_to_pending_messages) { pending_message.save(storagePath); } PendingMessageHeader tmp_msg_header = getPendingMessageHeader(friend, pending_message.streamMessage.id); if (tmp_msg_header != null) { tmp_msg_header.sendToServer = false; } if (pending_message.removeAfterSending) { removeMessage(friend, pending_message.streamMessage.id); } return(true); } } return(false); } return(true); /* string pub_k = FriendList.findContactPubkey(msg.recipientAddress); * if (pub_k.Length < 1) * { * Console.WriteLine("Contact {0} not found, adding to offline queue!", msg.recipientAddress); * addOfflineMessage(msg); * return; * } * * * // Create a new IXIAN transaction * // byte[] checksum = Crypto.sha256(encrypted_message); * Transaction transaction = new Transaction(0, msg.recipientAddress, Node.walletStorage.address); * // transaction.data = Encoding.UTF8.GetString(checksum); * msg.transactionID = transaction.id; * //ProtocolMessage.broadcastProtocolMessage(ProtocolMessageCode.newTransaction, transaction.getBytes()); * * // Add message to the queue * messages.Add(msg); * * // Request a new keypair from the S2 Node * if(hostname == null) * ProtocolMessage.broadcastProtocolMessage(ProtocolMessageCode.s2generateKeys, Encoding.UTF8.GetBytes(msg.getID())); * else * { * NetworkClientManager.sendData(ProtocolMessageCode.s2generateKeys, Encoding.UTF8.GetBytes(msg.getID()), hostname); * }*/ }
public Task Recovery(StreamMessage msg) { batchTracker.CompleteOneOperatorRecovery(msg.barrierOrCommitInfo); return(Task.CompletedTask); }
protected override void PurgeExpiredMessage(StreamMessage streamMessage) { _taskQueue.Enqueue(ct => DeleteEventInternal(streamMessage.StreamId, streamMessage.MessageId, ct)); }
private async Task StreamMessageReceived(IAllStreamSubscription subscription, StreamMessage message, CancellationToken cancellationToken) { if (message.IsInSystemStream()) { _logger.LogInformation( "Event {messageType} is in a System stream therefore not being sent to observers", message.Type); return; } _logger.LogDebug("Event {eventType} received with ID {messageId}, sending to {observerLength} observers", message.Type, message.MessageId, _eventObservers.Length); var eventSourceEvent = await message.ToEvent(cancellationToken).ConfigureAwait(false); await Task.WhenAll(_eventObservers.Select(observer => observer.EventReceived(eventSourceEvent, cancellationToken))).ConfigureAwait(false); await _setGlobalCheckpoint(subscription.LastPosition, cancellationToken).ConfigureAwait(false); }
public void GenerateSuspensionOnlyOnceWhenMissedDeletion() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); IStateManager provider = new StateManager(_settings.Object, connector.Object); var firstSnapshot = TestHelper.GetFixtureFromResource("rugbydata_snapshot_2"); var secondSnapshot = TestHelper.GetFixtureFromResource("rugbydata_snapshot_withRemovedMarkets_5"); var update = new Fixture { Id = firstSnapshot.Id, //invalid sequence Sequence = firstSnapshot.Sequence + 2, MatchStatus = firstSnapshot.MatchStatus }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns(firstSnapshot.Id); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); // it needs to set up as many snapshots as there will be taken resource.SetupSequence(x => x.GetSnapshot()) .Returns(FixtureJsonHelper.ToJson(firstSnapshot)) .Returns(FixtureJsonHelper.ToJson(secondSnapshot)) .Returns(FixtureJsonHelper.ToJson(secondSnapshot)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); // STEP 4: send the update containing a wrong sequence number listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); update.Sequence += 10; message.Content = update; // should cause a snapshot as we missed a sequence listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); connector.Verify(x => x.ProcessStreamUpdate(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never); connector.Verify(x => x.Suspend(It.IsAny<string>()), Times.Exactly(2)); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Exactly(3)); resource.Verify(x => x.GetSnapshot(), Times.Exactly(3), "The streamlistener is supposed to send second"); var marketsRemoved = firstSnapshot.Markets.Where(m => !secondSnapshot.Markets.Exists(m2 => m.Id == m2.Id)).ToList(); marketsRemoved.Exists(m => m.Id == "_3z0qZjBERuS8kLYiqhuESaDZDM").Should().BeTrue(); connector.Verify( x => x.ProcessSnapshot( It.Is<Fixture>( f => f.Sequence == secondSnapshot.Sequence && marketsRemoved.Any(removedMarket => f.Markets.Exists(m => m.Id == removedMarket.Id && m.IsSuspended)) ), It.IsAny<bool>()), Times.Once); }
void StreamServerUpdate() { streamTimer.Reset(); streamTimer.Start(); uint rpcsExecuted = 0; for (int i = 0; i < servers.Count; i++) { servers [i].StreamServer.Update(); } // Run streaming requests if (streamRequests.Count > 0) { foreach (var entry in streamRequests) { var streamClient = entry.Key; var id = streamClient.Guid; var requests = entry.Value; if (requests.Count == 0) { continue; } if (!rpcClients.ContainsKey(id)) { continue; } CallContext.Set(rpcClients [id]); var streamMessage = new StreamMessage(); foreach (var request in requests) { // Run the RPC Response response; try { response = Service.Services.Instance.HandleRequest(request.Procedure, request.Arguments); } catch (RPCException e) { response = new Response(); response.HasError = true; response.Error = e.ToString(); } catch (YieldException e) { // FIXME: handle yields correctly response = new Response(); response.HasError = true; response.Error = e.ToString(); } rpcsExecuted++; // Don't send an update if it is the previous one // FIXME: does the following comparison work?!? The objects have not been serialized if (response.ReturnValue == streamResultCache [request.Identifier]) { continue; } // Add the update to the response message streamResultCache [request.Identifier] = response.ReturnValue; response.Time = GetUniversalTime(); var streamResponse = request.Response; streamResponse.Response = response; streamMessage.Responses.Add(streamResponse); } if (streamMessage.Responses.Count > 0) { streamClient.Stream.Write(streamMessage); } } } streamTimer.Stop(); StreamRPCs = rpcsExecuted; StreamRPCsExecuted += rpcsExecuted; TimePerStreamUpdate = (float)streamTimer.ElapsedSeconds(); }
public void ShouldTakeASnapshotOnUpdateIfItIsInAnErrorState() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.MarketFiltersDirectory).Returns("."); var provider = new StateManager(_settings.Object, connector.Object); Fixture fixture = new Fixture { Id = "ABCD", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; Fixture update = new Fixture { Id = "ABCD", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABCD"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(r => r.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty); // if we return an emptry string, the StreamListener is supposed to raise an exception resource.Setup(x => x.GetSnapshot()).Returns(String.Empty); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); // STEP 3: check the result resource.Verify(x => x.GetSnapshot(), Times.Exactly(2), "The StreamListener was supposed to acquire 2 snasphots"); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never); // here we are in an error state... // STEP 4: resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 5: verify the results connector.Verify(x => x.ProcessStreamUpdate(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never, "The StreamListener was not supposed to process any updates"); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Once); }
protected abstract void PurgeExpiredMessage(StreamMessage streamMessage);
public void MarkMarkedAsForcedSuspended() { Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.DeltaRuleEnabled).Returns(true); var provider = new StateManager(_settings.Object, connector.Object); provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendAllMarketsStrategy, SuspensionReason.SUSPENSION); //var suspended = false; //Action<IMarketStateCollection> suspension_strategy = x => {suspended = true;}; //suspension.RegisterAction(suspension_strategy, SuspensionReason.FIXTURE_DELETED); // Please note Sequence = 1 Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 }; Market mkt = new Market { Id = "MKT" }; fixture.Markets.Add(mkt); // ...and Sequence = 3 Fixture update = new Fixture { Id = "ABCDE", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.BaseVariables } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABCDE"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); //Update snapshot sequence fixture.Sequence = 2; resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 3: let create at lea listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); var fixtureState = provider.CreateNewMarketRuleManager("ABCDE").CurrentState; fixtureState.Markets.All(x => fixtureState[x].IsForcedSuspended).Should().BeFalse(); }
private void Kc_NewMessageArrived(StreamMessage message) { var nonde = message.After.AsNode(); var id = nonde.Id; }
public void StreamListenerEvents() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.MarketFiltersDirectory).Returns("."); var provider = new StateManager(_settings.Object, connector.Object); var suspensionManager = new SuspensionManager(provider, connector.Object); var fixtureSnapshot = new Fixture { Id = "ABC", Epoch = 0, MatchStatus = "30", Sequence = 1 }; var settledSnapshot = new Fixture { Id = "ABC", Epoch = 3, MatchStatus = "50", Sequence = 5 }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(r => r.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty); resource.Setup(r => r.StopStreaming()).Raises(r => r.StreamDisconnected += (e, o) => { }, EventArgs.Empty); //sequence of 3 snapshots middle one should raise an exception resource.SetupSequence(r => r.GetSnapshot()) .Returns(FixtureJsonHelper.ToJson(fixtureSnapshot)) .Returns(String.Empty) .Returns(FixtureJsonHelper.ToJson(settledSnapshot)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.MonitorEvents(); listener.Start(); listener.ShouldRaise("OnConnected"); listener.ShouldRaise("OnBeginSnapshotProcessing"); listener.ShouldRaise("OnFinishedSnapshotProcessing"); //stream event var update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.MatchOver).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; var message = new StreamMessage { Content = update }; listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); listener.ShouldRaise("OnBeginStreamUpdateProcessing"); listener.ShouldRaise("OnFinishedStreamUpdateProcessing"); //as a result of match status change it will get a second snapshot which is String.Empty listener.ShouldRaise("OnError") .WithArgs<StreamListenerEventArgs>(e => e.Exception != null); listener.ShouldRaise("OnSuspend"); //when recovered the IsErrored should clear listener.IsErrored.Should().BeFalse(); listener.ShouldRaise("OnFlagsChanged") .WithArgs<StreamListenerEventArgs>(e => ((StreamListener)e.Listener).IsErrored == false); //simulate stream disconnection listener.ResourceOnStreamDisconnected(null, null); listener.ShouldRaise("OnDisconnected"); listener.Stop(); listener.ShouldRaise("OnStop"); resource.Verify(x => x.GetSnapshot(), Times.Exactly(3), "The StreamListener was supposed to acquire 3 snasphots"); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Exactly(2)); }
public PublishRequest(StreamMessage streamMessage) : base(messageType.PublishRequest) { this.streamMessage = streamMessage; }
public void PrematchSuspensionShouldSuspendAsNormalWhenEnabledTest() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.MarketFiltersDirectory).Returns("."); //default _settings.Setup(x => x.DisablePrematchSuspensionOnDisconnection).Returns(false); //suspension should occur if time we are within 15mins _settings.Setup(x => x.PreMatchSuspensionBeforeStartTimeInMins).Returns(15); state.Setup(x => x.GetFixtureState(It.Is<string>(id => id == "TestAbc"))) .Returns(new FixtureState() { Id = "TestAbc", MatchStatus = MatchStatus.Prematch }); var startTime = DateTime.UtcNow.AddMinutes(27); var provider = new StateManager(_settings.Object, connector.Object); Fixture fixture = new Fixture { Id = "TestAbc", Sequence = 1, MatchStatus = ((int)MatchStatus.Prematch).ToString(), Epoch = 1, StartTime = startTime }; Fixture update = new Fixture { Id = "TestAbc", Sequence = 2, MatchStatus = ((int)MatchStatus.Prematch).ToString(), Epoch = 1, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus }, StartTime = startTime }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(r => r.Id).Returns("TestAbc"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.Prematch); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); // just to be sure that we are streaming listener.IsStreaming.Should().BeTrue(); listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); listener.ResourceOnStreamDisconnected(this, EventArgs.Empty); // STEP 3: Check the disconnection listener.IsStreaming.Should().BeFalse(); // suspend is called when the stream listener processes snapshots // so we need to make sure that is only called once connector.Verify(x => x.Suspend(It.Is<string>(y => y == "TestAbc")), Times.Once); }
//[Test] public virtual void TestSendReceiveForeignStreamMessage( //[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)] MsgDeliveryMode deliveryMode, string testTopicRef) { using (IConnection connection = CreateConnection()) { connection.Start(); using (ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge)) { IDestination destination = GetClearDestination(session, DestinationType.Topic, testTopicRef); using (IMessageConsumer consumer = session.CreateConsumer(destination)) using (IMessageProducer producer = session.CreateProducer(destination)) { try { producer.DeliveryMode = deliveryMode; StreamMessage request = new StreamMessage(); request.Properties[propertyName] = propertyValue; request.WriteBoolean(a); request.WriteByte(b); request.WriteChar(c); request.WriteInt16(d); request.WriteInt32(e); request.WriteInt64(f); request.WriteString(g); request.WriteBoolean(h); request.WriteByte(i); request.WriteInt16(j); request.WriteInt32(k); request.WriteInt64(l); request.WriteSingle(m); request.WriteDouble(n); producer.Send(request); IStreamMessage message = consumer.Receive(receiveTimeout) as IStreamMessage; Assert.IsNotNull(message, "No message returned!"); Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties."); Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match"); // Check the body Assert.AreEqual(a, message.ReadBoolean(), "Stream Boolean Value: a"); Assert.AreEqual(b, message.ReadByte(), "Stream Byte Value: b"); Assert.AreEqual(c, message.ReadChar(), "Stream Char Value: c"); Assert.AreEqual(d, message.ReadInt16(), "Stream Int16 Value: d"); Assert.AreEqual(e, message.ReadInt32(), "Stream Int32 Value: e"); Assert.AreEqual(f, message.ReadInt64(), "Stream Int64 Value: f"); Assert.AreEqual(g, message.ReadString(), "Stream String Value: g"); Assert.AreEqual(h, message.ReadBoolean(), "Stream Boolean Value: h"); Assert.AreEqual(i, message.ReadByte(), "Stream Byte Value: i"); Assert.AreEqual(j, message.ReadInt16(), "Stream Int16 Value: j"); Assert.AreEqual(k, message.ReadInt32(), "Stream Int32 Value: k"); Assert.AreEqual(l, message.ReadInt64(), "Stream Int64 Value: l"); Assert.AreEqual(m, message.ReadSingle(), "Stream Single Value: m"); Assert.AreEqual(n, message.ReadDouble(), "Stream Double Value: n"); // use generic API to access entries Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName); // use type safe APIs Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName), "map entry: " + propertyName); } catch (NotSupportedException) { } } } } }
public void ShouldGetSnasphotOnInvalidSequence() { // STEP 1: prepare the stub data Mock<IResourceFacade> resource = new Mock<IResourceFacade>(); Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>(); Mock<IEventState> state = new Mock<IEventState>(); _settings.Setup(x => x.MarketFiltersDirectory).Returns("."); var provider = new StateManager(_settings.Object, connector.Object); Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() }; Fixture update = new Fixture { Id = "ABC", Sequence = 2, MatchStatus = ((int)MatchStatus.Paused).ToString(), Epoch = 2, LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus } }; StreamMessage message = new StreamMessage { Content = update }; resource.Setup(x => x.Id).Returns("ABC"); resource.Setup(x => x.Content).Returns(new Summary()); resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning); resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty); resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 2: start the listener StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object); listener.Start(); listener.IsStreaming.Should().BeTrue(); //Snapshot need to have sequence at least equal to the current sequence otherwise it will error on sequence validation fixture.Sequence = 2; resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture)); // STEP 4: send the update containing a the epoch change listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message))); // STEP 5: check that ProcessStreamUpdate is called only once (for suspension)! connector.Verify(x => x.Suspend(It.Is<string>(y => y == "ABC"))); connector.Verify(x => x.ProcessSnapshot(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Exactly(2)); resource.Verify(x => x.GetSnapshot(), Times.Exactly(2), "The streamlistener was supposed to acquire a new snapshot"); }
public void Return(StreamMessage <TKey, TPayload> item) { item.Count = 0; item.iter = 0; this.batchQueue.Enqueue(item); }
private void SendStreamUpdate(Fixture streamUpdate) { var listener = _supervisor.GetType() .InvokeMember("GetStreamListener" , BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, _supervisor, new object[] { streamUpdate.Id }) as StreamListener; var message = new StreamMessage { Content = streamUpdate }; listener.ResourceOnStreamEvent(null, new StreamEventArgs(JsonConvert.SerializeObject(message))); }
// Called when receiving S2 data from clients public static void receiveData(byte[] bytes, RemoteEndpoint endpoint) { // TODO Verify signature for all relevant messages string endpoint_wallet_string = Base58Check.Base58CheckEncoding.EncodePlain(endpoint.presence.wallet); Logging.info(string.Format("Receiving S2 data from {0}", endpoint_wallet_string)); StreamMessage message = new StreamMessage(bytes); // Don't allow clients to send error stream messages, as it's reserved for S2 nodes only if (message.type == StreamMessageCode.error) { Logging.warn(string.Format("Discarding error message type from {0}", endpoint_wallet_string)); return; } // Discard messages not sent to this node if (!IxianHandler.getWalletStorage().isMyAddress(message.recipient)) { Logging.warn(string.Format("Discarding message that wasn't sent to this node from {0}", endpoint_wallet_string)); return; } if (message.encryptionType != StreamMessageEncryptionCode.none && !message.decrypt(IxianHandler.getWalletStorage().getPrimaryPrivateKey(), null, null)) { Logging.error("Could not decrypt message from {0}", Base58Check.Base58CheckEncoding.EncodePlain(message.sender)); return; } SpixiMessage spixi_msg = new SpixiMessage(message.data); int channel = 0; if (spixi_msg != null) { channel = spixi_msg.channel; } if (message.requireRcvConfirmation) { switch (spixi_msg.type) { case SpixiMessageCode.msgReceived: case SpixiMessageCode.msgRead: case SpixiMessageCode.requestFileData: case SpixiMessageCode.fileData: case SpixiMessageCode.appData: case SpixiMessageCode.msgTyping: // do not send received confirmation break; case SpixiMessageCode.chat: sendReceivedConfirmation(message.sender, message.id, channel, endpoint); break; default: sendReceivedConfirmation(message.sender, message.id, -1, endpoint); break; } } switch (spixi_msg.type) { case SpixiMessageCode.requestAdd: // Friend request if (!new Address(spixi_msg.data).address.SequenceEqual(message.sender) || !message.verifySignature(spixi_msg.data)) { Logging.error("Unable to verify signature for message type: {0}, id: {1}, from: {2}.", message.type, Crypto.hashToString(message.id), Base58Check.Base58CheckEncoding.EncodePlain(message.sender)); } else { sendAcceptAdd(endpoint.presence.wallet, endpoint.presence.pubkey); sendAvatar(endpoint.presence.wallet, null); } break; case SpixiMessageCode.getPubKey: if (Node.users.hasUser(spixi_msg.data)) { StreamMessage sm = new StreamMessage(); sm.type = StreamMessageCode.info; sm.sender = IxianHandler.getWalletStorage().getPrimaryAddress(); sm.recipient = message.sender; sm.data = new SpixiMessage(SpixiMessageCode.pubKey, Node.users.getUser(spixi_msg.data).publicKey).getBytes(); sm.encryptionType = StreamMessageEncryptionCode.none; sendMessage(endpoint.presence.wallet, sm); } break; case SpixiMessageCode.getNick: sendNickname(endpoint.presence.wallet, spixi_msg.data); break; case SpixiMessageCode.getAvatar: sendAvatar(endpoint.presence.wallet, spixi_msg.data); break; case SpixiMessageCode.nick: Node.users.setPubKey(endpoint.presence.wallet, endpoint.serverPubKey, false); Node.users.setNick(endpoint.presence.wallet, message.getBytes()); break; case SpixiMessageCode.avatar: Node.users.setPubKey(endpoint.presence.wallet, endpoint.serverPubKey, false); if (message.data.Length < 500000) { if (message.data == null) { Node.users.setAvatar(endpoint.presence.wallet, null); } else { Node.users.setAvatar(endpoint.presence.wallet, message.getBytes()); } } break; case SpixiMessageCode.chat: onChat(bytes, message, channel, endpoint); break; case SpixiMessageCode.botGetMessages: Messages.sendMessages(endpoint.presence.wallet, channel, spixi_msg.data); break; case SpixiMessageCode.msgReceived: { // don't send confirmation back, so just return return; } case SpixiMessageCode.msgRead: { // don't send confirmation back, so just return return; } case SpixiMessageCode.botAction: onBotAction(spixi_msg.data, endpoint); break; case SpixiMessageCode.msgDelete: onMsgDelete(spixi_msg.data, channel, endpoint); break; case SpixiMessageCode.msgReaction: onMsgReaction(message, spixi_msg.data, channel, endpoint); break; case SpixiMessageCode.leave: onLeave(message.sender); break; default: Logging.warn("Received message type that isn't handled {0}", spixi_msg.type); break; } // TODO: commented for development purposes ONLY! /* * // Extract the transaction * Transaction transaction = new Transaction(message.transaction); * * // Validate transaction sender * if(transaction.from.SequenceEqual(message.sender) == false) * { * Logging.error(string.Format("Relayed message transaction mismatch for {0}", endpoint_wallet_string)); * sendError(message.sender); * return; * } * * // Validate transaction amount and fee * if(transaction.amount < CoreConfig.relayPriceInitial || transaction.fee < CoreConfig.transactionPrice) * { * Logging.error(string.Format("Relayed message transaction amount too low for {0}", endpoint_wallet_string)); * sendError(message.sender); * return; * } * * // Validate transaction receiver * if (transaction.toList.Keys.First().SequenceEqual(IxianHandler.getWalletStorage().address) == false) * { * Logging.error("Relayed message transaction receiver is not this S2 node"); * sendError(message.sender); * return; * } * * // Update the recipient dictionary * if (dataRelays.ContainsKey(message.recipient)) * { * dataRelays[message.recipient]++; * if(dataRelays[message.recipient] > Config.relayDataMessageQuota) * { * Logging.error(string.Format("Exceeded amount of unpaid data relay messages for {0}", endpoint_wallet_string)); * sendError(message.sender); * return; * } * } * else * { * dataRelays.Add(message.recipient, 1); * } * * * // Store the transaction * StreamTransaction streamTransaction = new StreamTransaction(); * streamTransaction.messageID = message.getID(); * streamTransaction.transaction = transaction; * lock (transactions) * { * transactions.Add(streamTransaction); * } * * // For testing purposes, allow the S2 node to receive relay data itself * if (message.recipient.SequenceEqual(IxianHandler.getWalletStorage().getWalletAddress())) * { * string test = Encoding.UTF8.GetString(message.data); * Logging.info(test); * * return; * } * * Logging.info("NET: Forwarding S2 data"); * NetworkStreamServer.forwardMessage(message.recipient, DLT.Network.ProtocolMessageCode.s2data, bytes); */ }
public static void onBotAction(byte[] action_data, RemoteEndpoint endpoint, int channel = 0) { SpixiBotAction sba = new SpixiBotAction(action_data); switch (sba.action) { case SpixiBotActionCode.getChannels: sendChannels(endpoint); break; case SpixiBotActionCode.getInfo: Node.users.setPubKey(endpoint.presence.wallet, endpoint.serverPubKey, false); sendInfo(endpoint.presence.wallet); break; case SpixiBotActionCode.getUsers: sendUsers(endpoint); break; case SpixiBotActionCode.getUser: sendUser(endpoint.presence.wallet, Node.users.getUser(sba.data)); break; case SpixiBotActionCode.payment: StreamTransaction stream_tx = new StreamTransaction(sba.data); if (!stream_tx.transaction.toList.Keys.First().SequenceEqual(IxianHandler.getWalletStorage().getPrimaryAddress())) { Logging.warn("Received transaction txid " + stream_tx.transaction.id + " from " + Base58Check.Base58CheckEncoding.EncodePlain(endpoint.presence.wallet) + " that's not for this node."); return; } StreamMessage sm = pendingMessages.Find(x => x.id.SequenceEqual(stream_tx.messageID)); if (sm == null) { // TODO TODO TODO send get message request to the client Logging.warn("Received transaction txid " + stream_tx.transaction.id + " from " + Base58Check.Base58CheckEncoding.EncodePlain(endpoint.presence.wallet) + " but have no message for this transaction."); return; } IxiNumber price = getMessagePrice(sm.sender, sm.data.Length); if (stream_tx.transaction.amount < price) { Logging.warn("Received transaction txid " + stream_tx.transaction.id + " from " + Base58Check.Base58CheckEncoding.EncodePlain(endpoint.presence.wallet) + " that has lower than expected amount."); return; } CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, stream_tx.transaction.getBytes(), null); CoreProtocolMessage.broadcastGetTransaction(stream_tx.transaction.id, 0, null, false); PendingTransactions.addPendingLocalTransaction(stream_tx.transaction, stream_tx.messageID); break; case SpixiBotActionCode.enableNotifications: bool send_notifications = false; if (sba.data[0] == 1) { send_notifications = true; } Node.users.getUser(endpoint.presence.wallet).sendNotification = send_notifications; Node.users.writeContactsToFile(); break; } }
protected override Task <ReadStreamPage> ReadStreamBackwardsInternal( string streamId, int fromVersionInclusive, int count, bool prefetch, ReadNextStreamPage readNext, CancellationToken cancellationToken) { GuardAgainstDisposed(); cancellationToken.ThrowIfCancellationRequested(); using (_lock.UseReadLock()) { InMemoryStream stream; if (!_streams.TryGetValue(streamId, out stream)) { var notFound = new ReadStreamPage(streamId, PageReadStatus.StreamNotFound, fromVersionInclusive, -1, -1, -1, ReadDirection.Backward, true, s_readNextNotFound); return(Task.FromResult(notFound)); } var messages = new List <StreamMessage>(); var i = fromVersionInclusive == StreamVersion.End ? stream.Messages.Count - 1 : fromVersionInclusive; while (i < stream.Messages.Count && i >= 0 && count > 0) { var inMemorymessage = stream.Messages[i]; StreamMessage message; if (prefetch) { message = new StreamMessage( streamId, inMemorymessage.MessageId, inMemorymessage.StreamVersion, inMemorymessage.Position, inMemorymessage.Created, inMemorymessage.Type, inMemorymessage.JsonMetadata, inMemorymessage.JsonData); } else { message = new StreamMessage( streamId, inMemorymessage.MessageId, inMemorymessage.StreamVersion, inMemorymessage.Position, inMemorymessage.Created, inMemorymessage.Type, inMemorymessage.JsonMetadata, ct => Task.Run(() => ReadMessageData(streamId, inMemorymessage.MessageId), ct)); } messages.Add(message); i--; count--; } var lastStreamVersion = stream.Messages.Count > 0 ? stream.Messages[stream.Messages.Count - 1].StreamVersion : StreamVersion.End; var nextStreamVersion = messages.Count > 0 ? messages[messages.Count - 1].StreamVersion - 1 : StreamVersion.End; var endOfStream = nextStreamVersion < 0; var page = new ReadStreamPage( streamId, PageReadStatus.Success, fromVersionInclusive, nextStreamVersion, lastStreamVersion, stream.CurrentPosition, ReadDirection.Backward, endOfStream, readNext, messages.ToArray()); return(Task.FromResult(page)); } }