public void MemoryStream_1024_BufferSize_512() { const int streamLength = 1024; const int bufferSize = 512; TestProbe owner = CreateTestProbe(name: "owner"); MemoryStream stream = CreateMemoryStream(streamLength); IActorRef readStream = ActorOf( ReadStream.Create("memory-stream-1024-buffer-size-512", owner, stream, bufferSize) ); Within(TimeSpan.FromSeconds(1), () => { // Exactly 2 packets for (int iteration = 0; iteration < streamLength / bufferSize; iteration++) { owner.ExpectMsg <ReadStream.StreamData>(streamData => { Assert.Equal(bufferSize, streamData.Data.Count); }); } owner.ExpectMsg <ReadStream.StreamData>(streamData => { Assert.Equal(0, streamData.Data.Count); Assert.True(streamData.IsEndOfStream); }); }); }
/// <summary> /// Create a new <see cref="LogParser"/> actor. /// </summary> /// <param name="correlationId"> /// The message correlation Id that will be sent with the stream data. /// </param> /// <param name="owner"> /// The actor that owns the <see cref="LogParser"/> actor (this actor will receive the stream data). /// </param> /// <param name="stream"> /// The <see cref="Stream"/> to read from. /// </param> /// <param name="bufferSize"> /// The buffer size to use when reading from the stream. /// </param> public LogParser(string correlationId, IActorRef owner, Stream stream, int bufferSize) { if (String.IsNullOrWhiteSpace(correlationId)) { throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(correlationId)}.", nameof(correlationId)); } if (owner == null) { throw new ArgumentNullException(nameof(owner)); } if (stream == null) { throw new ArgumentNullException(nameof(stream)); } _readStreamProps = ReadStream.Create(correlationId, Self, stream, bufferSize); ByteString buffer = ByteString.Empty; bool isEndOfStream = false; // Parse as many log entries as we can find in the buffer. void LogPump() { DockerLogEntry logEntry; while (buffer.Count > 0) { (logEntry, buffer) = DockerLogEntry.ReadFrom(buffer, correlationId); if (logEntry == null) { break; } owner.Tell(logEntry); } } // We've reached the end of the log; like tears in rain, time to die. void EndOfStream() { if (isEndOfStream) { return; } isEndOfStream = true; owner.Tell( new EndOfLog(correlationId) ); Context.Stop(Self); } Receive <ReadStream.StreamData>(streamData => { buffer += streamData.Data; LogPump(); if (streamData.IsEndOfStream) { EndOfStream(); } }); Receive <ReadStream.StreamError>(error => { owner.Tell(error); }); Receive <Terminated>(terminated => { if (terminated.ActorRef == _readStream) { EndOfStream(); } else { Unhandled(terminated); } }); }