/
LastElement.cs
74 lines (63 loc) · 2.59 KB
/
LastElement.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//-----------------------------------------------------------------------
// <copyright file="LastElement.cs" company="Akka.NET Project">
// Copyright (C) 2009-2023 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2023 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------
using System.Threading.Tasks;
using Akka.Streams.Stage;
using Akka.Streams.Util;
using Akka.Util;
namespace Akka.Streams.Dsl
{
/// <summary>
/// This stage materializes to the last element pushed before upstream completion, if any, thereby recovering from any
/// failure. Pushed elements are just passed along.
/// </summary>
/// <typeparam name="T">input and output type</typeparam>
public class LastElement<T> : GraphStageWithMaterializedValue<FlowShape<T, T>, Task<Option<T>>>
{
#region Logic
private sealed class Logic : GraphStageLogic
{
public Logic(LastElement<T> lastElement, TaskCompletionSource<Option<T>> completion) : base(lastElement.Shape)
{
var currentElement = Option<T>.None;
SetHandler(lastElement.In, onPush: () =>
{
var element = Grab(lastElement.In);
currentElement = Option<T>.Create(element);
Push(lastElement.Out, element);
}, onUpstreamFinish: () =>
{
completion.SetResult(currentElement);
CompleteStage();
}, onUpstreamFailure: _ =>
{
completion.SetResult(currentElement);
CompleteStage();
});
SetHandler(lastElement.Out, onPull: () =>
{
Pull(lastElement.In);
});
}
}
#endregion
public LastElement()
{
In = new Inlet<T>("lastElement.in");
Out = new Outlet<T>("lastElement.out");
Shape = new FlowShape<T, T>(In, Out);
}
public override ILogicAndMaterializedValue<Task<Option<T>>> CreateLogicAndMaterializedValue(Attributes inheritedAttributes)
{
var completion = new TaskCompletionSource<Option<T>>();
var logic = new Logic(this, completion);
return new LogicAndMaterializedValue<Task<Option<T>>>(logic, completion.Task);
}
public override FlowShape<T, T> Shape { get; }
public Inlet<T> In { get; }
public Outlet<T> Out { get; }
}
}