Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Commit 6ef39f8

Browse files
committed
Added support for a continous feed of connection request updates.
1 parent 967bbfc commit 6ef39f8

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

src/SymphonyOSS.RestApiClient/Api/PodApi/ConnectionApi.cs

+115
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ namespace SymphonyOSS.RestApiClient.Api.PodApi
1919
{
2020
using System;
2121
using System.Collections.Generic;
22+
using System.Diagnostics;
23+
using System.Linq;
24+
using System.Threading;
25+
using System.Threading.Tasks;
26+
using AgentApi;
2227
using Authentication;
28+
using Generated.OpenApi.AgentApi.Model;
2329
using Generated.OpenApi.PodApi.Client;
2430
using Generated.OpenApi.PodApi.Model;
2531

@@ -30,12 +36,37 @@ namespace SymphonyOSS.RestApiClient.Api.PodApi
3036
/// </summary>
3137
public class ConnectionApi
3238
{
39+
private static readonly TraceSource TraceSource = new TraceSource("SymphonyOSS.RestApiClient");
40+
3341
private readonly Generated.OpenApi.PodApi.Api.IConnectionApi _connectionApi;
3442

3543
private readonly IAuthTokens _authTokens;
3644

3745
private readonly IApiExecutor _apiExecutor;
3846

47+
private readonly Dictionary<EventHandler<ConnectionRequestEventArgs>, Task> _tasks =
48+
new Dictionary<EventHandler<ConnectionRequestEventArgs>, Task>();
49+
50+
private Timer connectionPollTimer;
51+
52+
private event EventHandler<ConnectionRequestEventArgs> _onConnectionRequest;
53+
54+
public event EventHandler<ConnectionRequestEventArgs> OnConnectionRequest
55+
{
56+
add
57+
{
58+
_onConnectionRequest += value;
59+
}
60+
remove
61+
{
62+
_onConnectionRequest -= value;
63+
lock (_tasks)
64+
{
65+
_tasks.Remove(value);
66+
}
67+
}
68+
}
69+
3970
/// <summary>
4071
/// Initializes a new instance of the <see cref="UsersApi" /> class.
4172
/// See <see cref="Factories.PodApiFactory"/> for conveniently constructing
@@ -51,6 +82,54 @@ public ConnectionApi(IAuthTokens authTokens, Configuration configuration, IApiEx
5182
_apiExecutor = apiExecutor;
5283
}
5384

85+
/// <summary>
86+
/// Starts listening, notifying event handlers about incoming connection requests. Blocks
87+
/// until <see cref="ConnectionApi.Stop"/> is invoked.
88+
/// </summary>
89+
public void Listen(long timeout)
90+
{
91+
connectionPollTimer = new Timer(
92+
cb =>
93+
{
94+
try
95+
{
96+
var connectionList =
97+
List().Where(connection => connection.Status != UserConnection.StatusEnum.Accepted);
98+
99+
ProcessConnectionList(connectionList);
100+
}
101+
catch (Exception ex)
102+
{
103+
TraceSource.TraceEvent(
104+
TraceEventType.Error, 0,
105+
"Unhandled exception caught when fecthing list of connection request {1}",
106+
ex);
107+
}
108+
}, null, 0, timeout);
109+
}
110+
111+
/// <summary>
112+
/// Requests that <see cref="Listen"/> should stop.
113+
/// </summary>
114+
public void Stop()
115+
{
116+
connectionPollTimer.Dispose();
117+
connectionPollTimer = null;
118+
}
119+
120+
protected void ProcessConnectionList(IEnumerable<UserConnection> connectionList)
121+
{
122+
if (connectionList == null || _onConnectionRequest == null)
123+
{
124+
return;
125+
}
126+
127+
foreach (var eventHandler in _onConnectionRequest.GetInvocationList())
128+
{
129+
NotifyAsync((EventHandler<ConnectionRequestEventArgs>)eventHandler, connectionList);
130+
}
131+
}
132+
54133
/// <summary>
55134
/// Get the status of a connection invitation to another user.
56135
/// </summary>
@@ -120,5 +199,41 @@ private string GetStatusAsString(UserConnection.StatusEnum status)
120199
return status.ToString().ToLower();
121200
}
122201
}
202+
203+
protected async void NotifyAsync(EventHandler<ConnectionRequestEventArgs> connectionEventHandler,
204+
IEnumerable<UserConnection> connectionList)
205+
{
206+
// Notify each handler in a separate task, maintaining the order of connections in the list, and
207+
// get back to reading the connectio list again without waiting for listeners to process connection requests.
208+
Task task;
209+
if (_tasks.TryGetValue(connectionEventHandler, out task))
210+
{
211+
await task;
212+
}
213+
_tasks[connectionEventHandler] = Task.Run(() => Notify(connectionEventHandler, connectionList));
214+
}
215+
216+
private void Notify(EventHandler<ConnectionRequestEventArgs> connectionEventHandler,
217+
IEnumerable<UserConnection> connectionList)
218+
{
219+
foreach (var connection in connectionList)
220+
{
221+
TraceSource.TraceEvent(
222+
TraceEventType.Verbose, 0,
223+
"Notifying listener about connection request for user with ID \"{0}\" and status \"{1}\"",
224+
connection?.UserId, connection?.Status);
225+
try
226+
{
227+
connectionEventHandler.Invoke(this, new ConnectionRequestEventArgs(connection));
228+
}
229+
catch (Exception e)
230+
{
231+
TraceSource.TraceEvent(
232+
TraceEventType.Error, 0,
233+
"Unhandled exception caught when notifying listener about connection request for user with ID \"{0}\": {1}",
234+
connection?.UserId, e);
235+
}
236+
}
237+
}
123238
}
124239
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace SymphonyOSS.RestApiClient.Api.PodApi
2+
{
3+
using System;
4+
using Generated.OpenApi.PodApi.Model;
5+
6+
/// <summary>
7+
/// Event data for connection requests.
8+
/// </summary>
9+
public class ConnectionRequestEventArgs : EventArgs
10+
{
11+
public ConnectionRequestEventArgs(UserConnection connection)
12+
{
13+
Connection = connection;
14+
}
15+
16+
public UserConnection Connection { get; private set; }
17+
}
18+
}

0 commit comments

Comments
 (0)