-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add StreamBuffer to temporarily stores elements in a buffer (#29)
- Loading branch information
Showing
14 changed files
with
210 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Streamistry.Observability; | ||
|
||
namespace Streamistry; | ||
|
||
/// <summary> | ||
/// Represents a pipeline element that temporarily stores elements in a buffer as they pass through the stream. | ||
/// The buffer can accumulate a specified number of elements or a batch of elements over time, allowing for more efficient processing or delayed downstream transmission. | ||
/// Once the buffer reaches a certain threshold, such as a maximum size or time limit, its contents are released downstream for further processing. | ||
/// </summary> | ||
/// <typeparam name="T">The type of the elements stored in the buffer.</typeparam> | ||
public class StreamBuffer<T> : ChainablePipe<T>, IProcessablePipe<T> | ||
{ | ||
protected List<T?> Store { get; } = []; | ||
protected int? MaxCapacity { get; } | ||
|
||
public StreamBuffer(IChainablePipe<T> upstream, int? maxCapacity = null) | ||
: base(upstream.GetObservabilityProvider()) | ||
{ | ||
upstream.RegisterDownstream(Emit, Complete); | ||
MaxCapacity = maxCapacity; | ||
} | ||
|
||
[Meter] | ||
public void Emit(T? obj) | ||
{ | ||
Invoke(obj); | ||
if (MaxCapacity.HasValue && Store.Count >= MaxCapacity.Value) | ||
{ | ||
Complete(); | ||
Store.Clear(); | ||
} | ||
} | ||
|
||
[Trace] | ||
protected void Invoke(T? obj) | ||
=> Store.Add(obj); | ||
|
||
public override void Complete() | ||
{ | ||
foreach (var item in Store) | ||
PushDownstream(item); | ||
PushComplete(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Streamistry.Testing; | ||
internal class ConsoleOutput : IDisposable | ||
{ | ||
private readonly StringWriter stringWriter = new(); | ||
private readonly TextWriter originalOutput = Console.Out; | ||
|
||
public ConsoleOutput() | ||
=> Console.SetOut(stringWriter); | ||
|
||
public string GetOuput() | ||
=> stringWriter.ToString(); | ||
|
||
public int CountSubstring(string value) | ||
{ | ||
var text = GetOuput(); | ||
int count = 0, minIndex = text.IndexOf(value, 0); | ||
while (minIndex != -1) | ||
{ | ||
minIndex = text.IndexOf(value, minIndex + value.Length); | ||
count++; | ||
} | ||
return count; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Console.SetOut(originalOutput); | ||
stringWriter.Dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using NUnit.Framework; | ||
using Streamistry.Pipes.Sinks; | ||
using Streamistry.Pipes.Sources; | ||
|
||
namespace Streamistry.Testing; | ||
public class StreamBufferTests | ||
{ | ||
[Test] | ||
public void WithoutBuffer_TwoSinks_Overlaps() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new Mapper<int, int>(pipeline, x => x + 1); | ||
var firstSink = new DebugOutputSink<int>(mapper); | ||
var secondSink = new DebugOutputSink<int>(mapper); | ||
|
||
using var output = new ConsoleOutput(); | ||
|
||
pipeline.Emit(0); | ||
pipeline.Emit(1); | ||
pipeline.Emit(2); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 1\r\n>>> 2\r\n>>> 2\r\n>>> 3\r\n>>> 3\r\n")); | ||
} | ||
|
||
[Test] | ||
public void WithBuffer_TwoSinks_NoOverlap() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new Mapper<int, int>(pipeline, x => x + 1); | ||
var firstSink = new DebugOutputSink<int>(mapper); | ||
var buffer = new StreamBuffer<int>(mapper); | ||
var secondSink = new DebugOutputSink<int>(buffer); | ||
|
||
using var output = new ConsoleOutput(); | ||
|
||
pipeline.Emit(0); | ||
pipeline.Emit(1); | ||
pipeline.Emit(2); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n")); | ||
|
||
pipeline.Complete(); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 1\r\n>>> 2\r\n>>> 3\r\n")); | ||
} | ||
|
||
[Test] | ||
public void WithBufferMaxCapacity_TwoSinks_NoOverlap() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new Mapper<int, int>(pipeline, x => x + 1); | ||
var firstSink = new DebugOutputSink<int>(mapper); | ||
var buffer = new StreamBuffer<int>(mapper, 3); | ||
var secondSink = new DebugOutputSink<int>(buffer); | ||
|
||
using var output = new ConsoleOutput(); | ||
|
||
pipeline.Emit(0); | ||
pipeline.Emit(1); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n")); | ||
pipeline.Emit(2); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 1\r\n>>> 2\r\n>>> 3\r\n")); | ||
pipeline.Emit(3); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 4\r\n")); | ||
pipeline.Complete(); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 4\r\n>>> 4\r\n")); | ||
} | ||
|
||
[Test] | ||
public void WithBufferMaxCapacity_TwoSources_NoOverlapSourcePushCompletion() | ||
{ | ||
var source = new EnumerableSource<int>(Enumerable.Range(0, 4)); | ||
var mapper = new Mapper<int, int>(source, x => x + 1); | ||
var firstSink = new DebugOutputSink<int>(mapper); | ||
var buffer = new StreamBuffer<int>(mapper, 3); | ||
var secondSink = new DebugOutputSink<int>(buffer); | ||
|
||
using var output = new ConsoleOutput(); | ||
source.Start(); | ||
Assert.That(output.GetOuput(), Is.EqualTo(">>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 1\r\n>>> 2\r\n>>> 3\r\n>>> 4\r\n>>> 4\r\n")); | ||
} | ||
} |