Skip to content

Commit aeb2d4d

Browse files
committed
refactor SocketIO.cs
1 parent c2c7b78 commit aeb2d4d

File tree

10 files changed

+202
-28
lines changed

10 files changed

+202
-28
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Net.Http;
2+
using SocketIOClient.Serializer.Decapsulation;
3+
using SocketIOClient.V2.Protocol.Http;
4+
using SocketIOClient.V2.Serializer.SystemTextJson;
5+
using SocketIOClient.V2.Session;
6+
using SocketIOClient.V2.Session.EngineIOHttpAdapter;
7+
using SocketIOClient.V2.UriConverter;
8+
9+
namespace SocketIOClient.V2;
10+
11+
public class DefaultSessionFactory : ISessionFactory
12+
{
13+
public ISession New(EngineIO eio)
14+
{
15+
var engineIOAdapter = NewEnginIOAdapter(eio);
16+
var httpClient = new SystemHttpClient(new HttpClient());
17+
return new HttpSession(
18+
engineIOAdapter,
19+
new HttpAdapter(httpClient),
20+
new SystemJsonSerializer(new Decapsulator()),
21+
new DefaultUriConverter((int)eio));
22+
}
23+
24+
private static IEngineIOAdapter NewEnginIOAdapter(EngineIO eio)
25+
{
26+
if (eio == EngineIO.V3)
27+
{
28+
return new EngineIO3Adapter();
29+
}
30+
return new EngineIO4Adapter();
31+
}
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using SocketIOClient.V2.Session;
2+
3+
namespace SocketIOClient.V2;
4+
5+
public interface ISessionFactory
6+
{
7+
ISession New(EngineIO eio);
8+
}

src/SocketIOClient/V2/ISocketIO.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
using System;
12
using System.Threading.Tasks;
3+
using SocketIOClient.Core.Messages;
24
using SocketIOClient.Transport.Http;
3-
using SocketIOClient.V2.Http;
5+
using SocketIOClient.V2.Observers;
46
using SocketIOClient.V2.Session;
57

68
namespace SocketIOClient.V2;
79

8-
public interface ISocketIO
10+
public interface ISocketIO : IMyObserver<IMessage>
911
{
1012
IHttpClient HttpClient { get; set; }
11-
ISession Session { get; set; }
13+
ISessionFactory SessionFactory { get; set; }
14+
int PacketId { get; }
1215
Task ConnectAsync();
13-
Task EmitAsync(string eventName);
16+
Task EmitAsync(string eventName, Action<IAckMessage> ack);
1417
}

src/SocketIOClient/V2/Session/HttpSession.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,13 @@ private void NotifyObservers(IMessage message)
9898

9999
public SessionOptions SessionOptions { get; set; }
100100

101-
public async Task SendAsync(IMessage message, CancellationToken cancellationToken)
101+
public async Task SendAsync(object[] data, CancellationToken cancellationToken)
102102
{
103-
if (message is null)
103+
var messages = _serializer.Serialize(data);
104+
foreach (var message in messages)
104105
{
105-
throw new ArgumentNullException(nameof(message));
106+
await _httpAdapter.SendAsync(message, cancellationToken);
106107
}
107-
// TODO: serialize by message.Type
108-
// var protocolMessages = serializer.Serialize()
109-
110-
// _serializer.Serialize()
111-
await _httpAdapter.SendAsync(null, cancellationToken);
112-
throw new NotImplementedException();
113108
}
114109

115110
public async Task ConnectAsync(CancellationToken cancellationToken)

src/SocketIOClient/V2/Session/ISession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ public interface ISession : IMyObserver<ProtocolMessage>, IMyObservable<IMessage
1010
{
1111
int PendingDeliveryCount { get; }
1212
SessionOptions SessionOptions { get; set; }
13-
Task SendAsync(IMessage message, CancellationToken cancellationToken);
13+
Task SendAsync(object[] data, CancellationToken cancellationToken);
1414
Task ConnectAsync(CancellationToken cancellationToken);
1515
}

src/SocketIOClient/V2/SocketIO.cs

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,92 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net.Http;
4+
using System.Threading;
15
using System.Threading.Tasks;
2-
using SocketIOClient.Transport.Http;
6+
using SocketIOClient.Core.Messages;
7+
using SocketIOClient.Serializer.Decapsulation;
8+
using SocketIOClient.V2.Protocol.Http;
9+
using SocketIOClient.V2.Serializer.SystemTextJson;
310
using SocketIOClient.V2.Session;
11+
using SocketIOClient.V2.Session.EngineIOHttpAdapter;
12+
using SocketIOClient.V2.UriConverter;
13+
using IHttpClient = SocketIOClient.Transport.Http.IHttpClient;
414

515
namespace SocketIOClient.V2;
616

717
public class SocketIO : ISocketIO
818
{
919
public IHttpClient HttpClient { get; set; }
10-
public ISession Session { get; set; }
20+
public ISessionFactory SessionFactory { get; set; }
21+
private ISession _session;
22+
public int PacketId { get; private set; }
23+
public bool Connected { get; private set; }
24+
25+
26+
private readonly Dictionary<int, Action<IAckMessage>> _ackHandlers = new();
27+
private readonly Dictionary<int, Func<SocketIOResponse, Task>> _funcHandlers = new();
28+
private readonly SocketIOOptions _options;
29+
30+
31+
public SocketIO(Uri uri, SocketIOOptions options)
32+
{
33+
_options = options;
34+
SessionFactory = new DefaultSessionFactory();
35+
}
36+
37+
public SocketIO(Uri uri) : this(uri, new SocketIOOptions())
38+
{
39+
}
40+
41+
public SocketIO(string uri) : this(new Uri(uri), new SocketIOOptions())
42+
{
43+
}
44+
45+
private IEngineIOAdapter NewEnginIOAdapter()
46+
{
47+
if (_options.EIO == EngineIO.V3)
48+
{
49+
return new EngineIO3Adapter();
50+
}
51+
return new EngineIO4Adapter();
52+
}
1153

1254
public Task ConnectAsync()
1355
{
14-
throw new System.NotImplementedException();
56+
_session = SessionFactory.New(_options.EIO);
57+
// Session.Subscribe(this);
58+
Connected = true;
59+
return Task.CompletedTask;
60+
}
61+
62+
// public Task EmitAsync(string eventName, Action ack)
63+
// {
64+
// throw new NotImplementedException();
65+
// }
66+
67+
private void ThrowIfNotConnected()
68+
{
69+
if (Connected)
70+
{
71+
return;
72+
}
73+
throw new InvalidOperationException("SocketIO is not connected.");
74+
}
75+
76+
public async Task EmitAsync(string eventName, Action<IAckMessage> ack)
77+
{
78+
ThrowIfNotConnected();
79+
PacketId++;
80+
await _session.SendAsync([eventName], CancellationToken.None);
81+
_ackHandlers.Add(PacketId, ack);
1582
}
1683

17-
public Task EmitAsync(string eventName)
84+
public void OnNext(IMessage message)
1885
{
19-
throw new System.NotImplementedException();
86+
if (message.Type == MessageType.Ack)
87+
{
88+
var ackMessage = (IAckMessage)message;
89+
_ackHandlers[ackMessage.Id](ackMessage);
90+
}
2091
}
2192
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace SocketIOClient.V2;
2+
3+
public class SocketIOOptions
4+
{
5+
public EngineIO EIO { get; set; }
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace SocketIOClient.V2;
2+
3+
public class SocketIOResponse
4+
{
5+
6+
}

tests/SocketIOClient.UnitTests/V2/Session/HttpSessionTests.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,6 @@ public HttpSessionTests()
4444
private readonly IEngineIOAdapter _engineIOAdapter;
4545
private readonly ISerializer _serializer;
4646

47-
[Fact]
48-
public async Task SendAsync_GivenANull_ThrowArgumentNullException()
49-
{
50-
await _session.Invoking(async x => await x.SendAsync(null, CancellationToken.None))
51-
.Should()
52-
.ThrowAsync<ArgumentNullException>();
53-
}
54-
5547
[Fact]
5648
public async Task ConnectAsync_HttpAdapterThrowAnyException_SessionThrowConnectionFailedException()
5749
{
@@ -112,7 +104,7 @@ public async Task Integration_HttpAdapterPushedMessages_MessagesWillBeForwardedT
112104
{
113105
var httpClient = Substitute.For<IHttpClient>();
114106
var httpAdapter = new HttpAdapter(httpClient);
115-
var serializer = new SystemJsonSerializer(new Decapsulator(), new JsonSerializerOptions());
107+
var serializer = new SystemJsonSerializer(new Decapsulator());
116108
var uriConverter = new DefaultUriConverter(4);
117109
var session = new HttpSession(_engineIOAdapter, httpAdapter, serializer, uriConverter)
118110
{
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using FluentAssertions;
4+
using NSubstitute;
5+
using SocketIOClient.V2;
6+
using SocketIOClient.V2.Serializer.SystemTextJson;
7+
using SocketIOClient.V2.Session;
8+
using Xunit;
9+
10+
namespace SocketIOClient.UnitTests.V2;
11+
12+
public class SocketIOTests
13+
{
14+
public SocketIOTests()
15+
{
16+
_session = Substitute.For<ISession>();
17+
var sessionFactory = Substitute.For<ISessionFactory>();
18+
sessionFactory.New(Arg.Any<EngineIO>()).Returns(_session);
19+
_io = new SocketIOClient.V2.SocketIO("http://localhost:3000")
20+
{
21+
SessionFactory = sessionFactory,
22+
};
23+
}
24+
25+
private readonly SocketIOClient.V2.SocketIO _io;
26+
private readonly ISession _session;
27+
28+
[Fact]
29+
public async Task EmitAsync_NotConnected_ThrowException()
30+
{
31+
await _io.Invoking(x => x.EmitAsync("event", _ => { }))
32+
.Should()
33+
.ThrowAsync<InvalidOperationException>()
34+
.WithMessage("SocketIO is not connected.");
35+
}
36+
37+
[Fact]
38+
public async Task EmitAsync_AckEvent_PacketIdIncrementBy1()
39+
{
40+
await _io.ConnectAsync();
41+
await _io.EmitAsync("event", _ => { });
42+
43+
_io.PacketId.Should().Be(1);
44+
}
45+
46+
[Fact]
47+
public async Task EmitAsync_AckEventAndGotResponse_HandlerIsCalled()
48+
{
49+
var ackCalled = false;
50+
51+
await _io.ConnectAsync();
52+
await _io.EmitAsync("event", _ => ackCalled = true);
53+
var ackMessage = new SystemJsonAckMessage
54+
{
55+
Id = _io.PacketId,
56+
};
57+
_io.OnNext(ackMessage);
58+
59+
ackCalled.Should().BeTrue();
60+
}
61+
}

0 commit comments

Comments
 (0)