-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
134 lines (120 loc) · 4.85 KB
/
Program.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Autofac;
using AutofacSerilogIntegration;
using SamplePacketDispatcher.Contracts;
using SamplePacketDispatcher.Dispatcher;
using SamplePacketDispatcher.Handlers;
using SamplePacketDispatcher.Loggers;
using SamplePacketDispatcher.Packets;
using Serilog;
namespace SamplePacketDispatcher
{
class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
Setup();
Run();
}
/// <summary>
/// Set up our dependency injection container and logger
/// </summary>
static void Setup()
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
var builder = new ContainerBuilder();
builder.RegisterLogger();
RegisterComponents(builder);
Container = builder.Build();
}
/// <summary>
/// Register all of the packet-related components
/// </summary>
static void RegisterComponents(ContainerBuilder builder)
{
// Register packet handlers
builder.RegisterType<PacketHandlerOne>().As<IPacketHandler>().SingleInstance();
builder.RegisterType<PacketHandlerTwo>().As<IPacketHandler>().SingleInstance();
builder.RegisterType<PacketHandlerThree>().As<IPacketHandler>().SingleInstance();
// Register dispatcher
builder.RegisterType<PacketDispatcher>().As<IPacketDispatcher>().SingleInstance();
builder.RegisterType<PacketLogger>().As<IPacketLogger>().SingleInstance();
}
/// <summary>
/// Run the main packet processing loop
/// </summary>
static void Run()
{
using (var scope = Container.BeginLifetimeScope())
{
var dispatcher = scope.Resolve<IPacketDispatcher>();
var packerLogger = scope.Resolve<IPacketLogger>();
ProcessPacketsAsync(dispatcher, packerLogger, CancellationToken.None).GetAwaiter().GetResult();
}
}
/// <summary>
/// The main packet processing loop.
/// </summary>
/// <remarks>
/// This method illustrates how the dispatcher can be used. For this illustration
/// we use an async foreach, to simulate a thread which receives and processes packets
/// independent of the rest of the process, and which responds to cancellation tokens
/// by terminating any outstanding dispatches and terminating the waits on any
/// incoming packets.
/// </remarks>
static async Task ProcessPacketsAsync(
IPacketDispatcher dispatcher,
IPacketLogger packetLogger,
CancellationToken cancellationToken)
{
await foreach (var packet in GeneratePacketsAsync(cancellationToken))
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
try
{
await dispatcher.DispatchAsync(packet, cancellationToken);
}
catch (Exception ex)
{
Guid correlationId = Guid.NewGuid();
Log.Error(ex, "CID:{correlationId}: Exception invoking dispatcher for packet with id {id} and type {type}", correlationId, packet?.Id, packet?.GetType().Name);
packetLogger.LogPacket(PacketLogReason.Error, correlationId, packet);
}
}
}
/// <summary>
/// This is a sample packet source, assumed to be asynchronous and producing fully-formed packets.
/// </summary>
static async IAsyncEnumerable<IPacket> GeneratePacketsAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{
var testData = new byte[] { 1, 2, 3 };
var packets = new[] {
new TestPacket { Id = 1, Data = testData },
new TestPacket { Id = 2, Data = testData },
new TestPacket { Id = 3, Data = testData },
new TestPacket { Id = 4, Data = testData },
new TestPacket { Id = 2, Data = testData },
new TestPacket { Id = 5, Data = testData },
new TestPacket { Id = 2, Data = TestPacket.BAD_DATA },
new TestPacket { Id = 3, Data = testData },
new TestPacket { Id = 2, Data = testData },
new TestPacket { Id = 1, Data = testData },
};
foreach (var packet in packets)
{
await Task.Delay(500, cancellationToken);
yield return packet;
}
}
}
}