-
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 distinct routes out of a pipe (#38)
- Loading branch information
Showing
14 changed files
with
237 additions
and
37 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Streamistry.Observability; | ||
|
||
namespace Streamistry; | ||
public class ExceptionRouterMapper<TInput, TOutput> : Mapper<TInput, TOutput>, IDualRoute<TOutput, TInput> | ||
{ | ||
public OutputPort<TInput> Alternate { get; } | ||
public new OutputPort<TOutput> Main { get => base.Main; } | ||
|
||
public ExceptionRouterMapper(IChainablePort<TInput> upstream, Func<TInput?, TOutput?> function) | ||
: base(upstream, function) | ||
{ | ||
Alternate = new(this, "Alternate"); | ||
} | ||
|
||
[Trace] | ||
public override void Emit(TInput? obj) | ||
{ | ||
if (TryInvokeCatch(obj, out var value, out var exception)) | ||
PushDownstream(value); | ||
else | ||
Alternate.PushDownstream(obj); | ||
} | ||
|
||
[Meter] | ||
protected virtual bool TryInvokeCatch(TInput? obj, out TOutput? value, out Exception? ex) | ||
{ | ||
value = default; | ||
ex = null; | ||
try | ||
{ | ||
value = Function.Invoke(obj); | ||
return true; | ||
} | ||
catch (Exception e) | ||
{ | ||
ex = e; | ||
return false; | ||
} | ||
} | ||
} |
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,12 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Streamistry; | ||
public interface IDualRoute<TMain, TAlternate> : IChainablePort<TMain> | ||
{ | ||
OutputPort<TMain> Main { get; } | ||
OutputPort<TAlternate> Alternate { get; } | ||
} |
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,32 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Streamistry; | ||
public class OutputPort<T> : IChainablePort<T> | ||
{ | ||
private Action<T?>? Downstream { get; set; } | ||
|
||
public void RegisterDownstream(Action<T?> downstream) | ||
=> Downstream += downstream; | ||
|
||
public string Name { get; init; } | ||
|
||
public IChainablePipe Pipe { get; init; } | ||
|
||
|
||
public OutputPort(IChainablePipe pipe, string name) | ||
=> (Name, Pipe) = (name, pipe); | ||
|
||
public void PushDownstream(T? obj) | ||
=> Downstream?.Invoke(obj); | ||
} | ||
|
||
public class MainOutputPort<T> : OutputPort<T> | ||
{ | ||
public MainOutputPort(IChainablePipe pipe) | ||
: base(pipe, "Main") | ||
{ } | ||
} |
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,94 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using NUnit.Framework; | ||
using Streamistry; | ||
using Streamistry.Pipes.Sinks; | ||
|
||
namespace Streamistry.Testing; | ||
public class ExceptionRouterMapperTests | ||
{ | ||
[Test] | ||
public void Emit_ValidData_MainOnly() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new ExceptionRouterMapper<int, int>(pipeline, x => 60 / x); | ||
var mainSink = new MemorySink<int>(mapper); | ||
var exceptionSink = new MemorySink<int>(mapper.Alternate); | ||
pipeline.Emit(10); | ||
pipeline.Emit(20); | ||
pipeline.Emit(6); | ||
|
||
Assert.That(mainSink.State.Count, Is.EqualTo(3)); | ||
Assert.That(mainSink.State.First, Is.EqualTo(6)); | ||
Assert.That(mainSink.State.Last, Is.EqualTo(10)); | ||
Assert.That(exceptionSink.State.Count, Is.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void Emit_InvalidData_ExceptionOnly() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new ExceptionRouterMapper<int, int>(pipeline, x => 60 / x); | ||
var mainSink = new MemorySink<int>(mapper); | ||
var exceptionSink = new MemorySink<int>(mapper.Alternate); | ||
pipeline.Emit(0); | ||
|
||
Assert.That(mainSink.State.Count, Is.EqualTo(0)); | ||
Assert.That(exceptionSink.State.Count, Is.EqualTo(1)); | ||
Assert.That(exceptionSink.State.First, Is.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void Emit_MixedDataNoExceptionPath_DontFail() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new ExceptionRouterMapper<int, int>(pipeline, x => 60 / x); | ||
var mainSink = new MemorySink<int>(mapper); | ||
pipeline.Emit(10); | ||
pipeline.Emit(0); | ||
pipeline.Emit(3); | ||
|
||
Assert.That(mainSink.State.Count, Is.EqualTo(2)); | ||
Assert.That(mainSink.State.First, Is.EqualTo(6)); | ||
Assert.That(mainSink.State.Last, Is.EqualTo(20)); | ||
} | ||
|
||
[Test] | ||
public void Emit_MixedDataWithExceptionPath_DontFail() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new ExceptionRouterMapper<int, int>(pipeline, x => 60 / x); | ||
var mainSink = new MemorySink<int>(mapper); | ||
var exceptionSink = new MemorySink<int>(mapper.Alternate); | ||
pipeline.Emit(10); | ||
pipeline.Emit(0); | ||
pipeline.Emit(3); | ||
|
||
Assert.That(mainSink.State.Count, Is.EqualTo(2)); | ||
Assert.That(mainSink.State.First, Is.EqualTo(6)); | ||
Assert.That(mainSink.State.Last, Is.EqualTo(20)); | ||
Assert.That(exceptionSink.State.Count, Is.EqualTo(1)); | ||
Assert.That(exceptionSink.State.First, Is.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void Emit_MixedDataWithExceptionPathAndExplicitMainPath_DontFail() | ||
{ | ||
var pipeline = new Pipeline<int>(); | ||
var mapper = new ExceptionRouterMapper<int, int>(pipeline, x => 60 / x); | ||
var mainSink = new MemorySink<int>(mapper.Main); | ||
var exceptionSink = new MemorySink<int>(mapper.Alternate); | ||
pipeline.Emit(10); | ||
pipeline.Emit(0); | ||
pipeline.Emit(3); | ||
|
||
Assert.That(mainSink.State.Count, Is.EqualTo(2)); | ||
Assert.That(mainSink.State.First, Is.EqualTo(6)); | ||
Assert.That(mainSink.State.Last, Is.EqualTo(20)); | ||
Assert.That(exceptionSink.State.Count, Is.EqualTo(1)); | ||
Assert.That(exceptionSink.State.First, Is.EqualTo(0)); | ||
} | ||
} |