Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:

- stage: Deployments
name: NuGet
if: tag IS present AND branch = master
if: tag IS present AND branch =~ /^(master|[0-9]+-stable)$/
language: csharp
solution: sdk-csharp.sln
sudo: required
Expand Down
80 changes: 62 additions & 18 deletions Kuzzle.Tests/Protocol/WebSocketTest.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,78 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Net.WebSockets;
using KuzzleSdk.Protocol;
using Moq;
using Xunit;

namespace Kuzzle.Tests.Protocol {
public class TestableWebSocket : WebSocket {
internal Mock<IClientWebSocket> MockSocket;
public int StateChangesCount = 0;
public ProtocolState LastStateDispatched = ProtocolState.Closed;
public class MockClientWebSocketAdapter : IClientWebSocket {
public Mock<IClientWebSocket> mockedSocket;
public WebSocketState _state = WebSocketState.Open;

public TestableWebSocket(Uri uri) : base(uri) {
StateChanged += (sender, e) => {
StateChangesCount++;
LastStateDispatched = e;
};
public WebSocketState State {
get { return _state; }
}

internal override dynamic CreateClientSocket() {
MockSocket = new Mock<IClientWebSocket>();
public MockClientWebSocketAdapter () {
mockedSocket = new Mock<IClientWebSocket>();

MockSocket
mockedSocket
.Setup(s => s.ConnectAsync(
It.IsAny<Uri>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
}

public Task ConnectAsync(Uri uri, CancellationToken cancellationToken) {
return mockedSocket.Object.ConnectAsync(uri, cancellationToken);
}

public Task SendAsync(
ArraySegment<byte> buffer,
WebSocketMessageType msgType,
bool endOfMessage,
CancellationToken cancellationToken
) {
return mockedSocket.Object.SendAsync(
buffer,
msgType,
endOfMessage,
cancellationToken);
}

public Task<WebSocketReceiveResult> ReceiveAsync(
ArraySegment<byte> buffer,
CancellationToken cancellationToken
) {
Task.Delay(10000).Wait();
return mockedSocket.Object.ReceiveAsync(buffer, cancellationToken);
}

public void Abort() {
mockedSocket.Object.Abort();
}
}

public class TestableWebSocket : AbstractWebSocket {
public Mock<IClientWebSocket> mockedSocket;
public int StateChangesCount = 0;
public ProtocolState LastStateDispatched = ProtocolState.Closed;

MockSocket.Object.State = System.Net.WebSockets.WebSocketState.Open;
public TestableWebSocket(Uri uri)
: base(typeof(MockClientWebSocketAdapter), uri)
{
StateChanged += (sender, e) => {
StateChangesCount++;
LastStateDispatched = e;
};
}

return MockSocket.Object;
public override async Task ConnectAsync(
CancellationToken cancellationToken
) {
await base.ConnectAsync(cancellationToken);
mockedSocket = ((MockClientWebSocketAdapter)socket).mockedSocket;
}
}

Expand All @@ -55,7 +99,7 @@ public void ConstructorRejectsNullUri() {
}

[Fact]
public async void ConnectAsyncTest() {
public async Task ConnectAsyncTest() {
await _ws.ConnectAsync(CancellationToken.None);

Assert.NotNull(_ws.socket);
Expand All @@ -64,7 +108,7 @@ public async void ConnectAsyncTest() {
await _ws.ConnectAsync(CancellationToken.None);
await _ws.ConnectAsync(CancellationToken.None);

_ws.MockSocket.Verify(
_ws.mockedSocket.Verify(
s => s.ConnectAsync(uri, CancellationToken.None),
Times.Once);

Expand All @@ -74,7 +118,7 @@ public async void ConnectAsyncTest() {
}

[Fact]
public async void DisconnectTest() {
public async Task DisconnectTest() {
await _ws.ConnectAsync(CancellationToken.None);

Assert.Equal(ProtocolState.Open, _ws.State);
Expand All @@ -91,7 +135,7 @@ public async void DisconnectTest() {
Assert.Equal(2, _ws.StateChangesCount);
Assert.Equal(ProtocolState.Closed, _ws.LastStateDispatched);

_ws.MockSocket.Verify(s => s.Abort(), Times.Once);
_ws.mockedSocket.Verify(s => s.Abort(), Times.Once);
}

[Fact]
Expand Down
3 changes: 3 additions & 0 deletions Kuzzle/API/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
using Newtonsoft.Json.Linq;

namespace KuzzleSdk.API.Controllers {
/// <summary>
/// Implement the "admin" controller of the Kuzzle API
/// </summary>
public class AdminController : BaseController {
internal AdminController(IKuzzleApi k) : base(k) { }

Expand Down
39 changes: 27 additions & 12 deletions Kuzzle/API/Controllers/RealtimeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
using static KuzzleSdk.API.Controllers.RealtimeController;

namespace KuzzleSdk.API.Controllers {

internal interface IRealtimeController {
Task<string> SubscribeAndAddToRecoverer(
string index, string collection, JObject filters,
NotificationHandler handler, SubscribeOptions options = null, bool addToRecoverer = true);
}

/// <summary>
/// Implements the "realtime" Kuzzle API controller
/// Implement the "realtime" Kuzzle API controller
/// </summary>
public sealed class RealtimeController : BaseController, IRealtimeController {
/// <summary>
Expand Down Expand Up @@ -112,7 +111,7 @@ internal RealtimeController(IKuzzleApi api) : base(api) {
}

/// <summary>
/// Releases unmanaged resources and performs other cleanup operations
/// Releases unmanaged resources and performs other cleanup operations
/// before the <see cref="T:KuzzleSdk.API.Controllers.RealtimeController"/>
/// is reclaimed by garbage collection.
/// </summary>
Expand All @@ -134,8 +133,8 @@ public async Task<int> CountAsync(string roomId) {
}

/// <summary>
/// Sends a real-time message to Kuzzle. The message will be dispatched to
/// all clients with subscriptions matching the index, the collection and
/// Sends a real-time message to Kuzzle. The message will be dispatched to
/// all clients with subscriptions matching the index, the collection and
/// the message content.
/// </summary>
public async Task PublishAsync(
Expand All @@ -153,8 +152,8 @@ await api.QueryAsync(new JObject {
}

/// <summary>
/// Subscribes by providing a set of filters: messages, document changes
/// and, optionally, user events matching the provided filters will
/// Subscribes by providing a set of filters: messages, document changes
/// and, optionally, user events matching the provided filters will
/// generate real-time notifications, sent to you in real-time by Kuzzle.
/// </summary>
public async Task<string> SubscribeAsync(
Expand Down Expand Up @@ -218,16 +217,32 @@ private async Task<string> SubscribeAndAddToSubscriptionRecoverer(
}

/// <summary>
/// Subscribes by providing a set of filters: messages, document changes
/// and, optionally, user events matching the provided filters will
/// Subscribes by providing a set of filters: messages, document changes
/// and, optionally, user events matching the provided filters will
/// generate real-time notifications, sent to you in real-time by Kuzzle.
/// and add the Subscription to the SubscriptionRecoverer for Offline Mode
/// </summary>
/// <param name="index">Storage index</param>
/// <param name="collection">Storage collection</param>
/// <param name="filters">Realtime filters (Koncorde format)</param>
/// <param name="handler">Callback invoked each time a realtime notification is received</param>
/// <param name="options">Subscription options</param>
/// <param name="addToRecoverer">If set to <c>true</c> add to recoverer.</param>
async Task<string> IRealtimeController.SubscribeAndAddToRecoverer(
string index, string collection, JObject filters,
NotificationHandler handler, SubscribeOptions options, bool addToRecoverer) {
return await SubscribeAndAddToSubscriptionRecoverer(index, collection, filters, handler, options, addToRecoverer);
string index,
string collection,
JObject filters,
NotificationHandler handler,
SubscribeOptions options,
bool addToRecoverer
) {
return await SubscribeAndAddToSubscriptionRecoverer(
index,
collection,
filters,
handler,
options,
addToRecoverer);
}

}
Expand Down
12 changes: 12 additions & 0 deletions Kuzzle/Enums/CollectionController/TypeFilter.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
using System;
namespace KuzzleSdk.Enums.CollectionController {
/// <summary>
/// Controls the kind of collections to be returned by collection:list
/// </summary>
public enum TypeFilter {
/// <summary>
/// Return all collections (stored and real-time)
/// </summary>
All,
/// <summary>
/// Return only stored collections
/// </summary>
Stored,
/// <summary>
/// Return only real-time collections
/// </summary>
Realtime,
}
}
25 changes: 25 additions & 0 deletions Kuzzle/EventHandler/AbstractKuzzleEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,38 @@
using KuzzleSdk.EventHandler.Events;

namespace KuzzleSdk.EventHandler {
/// <summary>
/// Abstract class describing this SDK event handler
/// </summary>
public abstract class AbstractKuzzleEventHandler {
/// <summary>
/// Events occuring on realtime subscriptions
/// </summary>
public abstract event EventHandler<SubscriptionEvent> Subscription;
/// <summary>
/// Events occuring on a successful login
/// </summary>
public abstract event EventHandler<UserLoggedInEvent> UserLoggedIn;
/// <summary>
/// Events occuring on a successful logout
/// </summary>
public abstract event Action UserLoggedOut;
/// <summary>
/// Events occuring whenever the SDK reconnects after a connection loss
/// </summary>
public abstract event Action Reconnected;
/// <summary>
/// Events occuring when queued items during a connection loss have all
/// been replayed
/// </summary>
public abstract event Action QueueRecovered;
/// <summary>
/// Events occuring on an unknown query response received from Kuzzle
/// </summary>
public abstract event EventHandler<Response> UnhandledResponse;
/// <summary>
/// Events occuring when the authentication token has expired
/// </summary>
public abstract event Action TokenExpired;

internal abstract void DispatchSubscription(SubscriptionEvent subscriptionData);
Expand Down
25 changes: 22 additions & 3 deletions Kuzzle/EventHandler/Events/SubscriptionEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@
using KuzzleSdk.Offline.Subscription;

namespace KuzzleSdk.EventHandler.Events {
/// <summary>
/// List of possible subscription actions
/// </summary>
public enum SubscriptionAction {
/// <summary>
/// A subscription was added
/// </summary>
Add,
/// <summary>
/// A subscription was removed
/// </summary>
Remove,
/// <summary>
/// Subscriptions were cleared up
/// </summary>
Clear,
}
public class SubscriptionEvent : EventArgs {

/// <summary>
/// Event triggered on realtime subscriptions
/// </summary>
public class SubscriptionEvent : EventArgs {
/// <summary>
/// Explains what subscription action triggered the SubscriptionEvent event
/// </summary>
public SubscriptionAction Action { get; private set; }

/// <summary>
/// Event triggered on realtime subscriptions
/// </summary>
public SubscriptionEvent(SubscriptionAction action) {
Action = action;
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
using KuzzleSdk.Offline.Subscription;

namespace KuzzleSdk.EventHandler.Events.SubscriptionEvents {
/// <summary>
/// Event triggered on new realtime subscriptions
/// </summary>
public sealed class SubscriptionAddEvent : SubscriptionEvent {

/// <summary>
/// Realtime subscription information
/// </summary>
public Subscription SubscriptionData { get; private set; }

public SubscriptionAddEvent(Subscription subscription) : base(SubscriptionAction.Add) {
/// <summary>
/// Event triggered on new realtime subscriptions
/// </summary>
public SubscriptionAddEvent(Subscription subscription)
: base(SubscriptionAction.Add)
{
SubscriptionData = subscription;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
using System;
namespace KuzzleSdk.EventHandler.Events.SubscriptionEvents {
/// <summary>
/// Event triggered when realtime subscriptions are cleared up
/// </summary>
public sealed class SubscriptionClearEvent : SubscriptionEvent {
/// <summary>
/// Event triggered when realtime subscriptions are cleared up
/// </summary>
public SubscriptionClearEvent() : base(SubscriptionAction.Clear) {
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@
using Newtonsoft.Json.Linq;

namespace KuzzleSdk.EventHandler.Events.SubscriptionEvents {
/// <summary>
/// Event triggered on realtime subscriptions removal
/// </summary>
public sealed class SubscriptionRemoveEvent : SubscriptionEvent {

/// <summary>
/// Predicate returning the removed subscription
/// </summary>
public Predicate<Subscription> Predicate { get; private set; }

public SubscriptionRemoveEvent(Predicate<Subscription> predicate) : base(SubscriptionAction.Remove) {
/// <summary>
/// Event triggered on realtime subscriptions removal
/// </summary>
public SubscriptionRemoveEvent(Predicate<Subscription> predicate)
: base(SubscriptionAction.Remove)
{
Predicate = predicate;
}
}
Expand Down
Loading