Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 13 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
name: Documentation Snippets
if: type = pull_request OR type = push AND branch =~ /^master|[0-9]+-dev$/ OR type = cron
language: node_js
node_js: 10
node_js: 12

script:
- docker-compose -f .ci/doc/docker-compose.yml run doc-tests node index
Expand All @@ -35,22 +35,27 @@ jobs:
name: Dead link check
if: type = pull_request OR type = push AND branch =~ /^master|[0-9]+-(dev|stable)$/ OR type = cron
language: node_js
node_js: 10

node_js: 12
cache:
directories:
- $HOME/.gem/specs
install:
- gem install typhoeus
- npm ci --silent
before_script:
- npm ci
- npm run doc-prepare
- $(npm bin)/kuzdoc iterate-repos:install --repos_path doc/framework/.repos/
- $(npm bin)/kuzdoc framework:link -d /sdk/csharp/1/ -v 1
script:
- gem install typhoeus
- cd doc/framework/ && HYDRA_MAX_CONCURRENCY=20 ruby .ci/dead-links.rb -p src/sdk/csharp/1/
- cd doc/framework/
- HYDRA_MAX_CONCURRENCY=20 ruby .ci/dead-links.rb -p src/sdk/csharp/1/

- stage: Tests
name: Build documentation
if: type = pull_request OR type = push AND branch =~ /^master|[0-9]+-(dev|stable)$/ OR type = cron
language: node_js
node_js: 10
node_js: 12

script:
- npm run doc-prepare
Expand Down Expand Up @@ -86,7 +91,7 @@ jobs:
name: Deploy next-docs.kuzzle.io
if: type = push AND branch =~ .*-dev
language: node_js
node_js: 10
node_js: 12
env:
- BRANCH=dev
- NODE_ENV=production
Expand Down Expand Up @@ -123,7 +128,7 @@ jobs:
name: Deploy docs.kuzzle.io
if: type = push AND branch =~ /^master|[0-9]+-stable$/
language: node_js
node_js: 10
node_js: 12
env:
- NODE_ENV=production
- S3_BUCKET=docs.kuzzle.io
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;
}


}
}
Loading