Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

New client side API design #900

@davidfowl

Description

@davidfowl

I'm proposing a new client side API design to solve a bunch of issues:

The big changes are:

  • Events registration method calls instead of .NET events. This allows taking a state parameter to avoid closure allocations.
  • Event registration methods also return IDisposable to allow removing the underlying subscription.
  • The other big benefit of methods for event registration are the ability to add overloads. We can support non async overloads of event handlers which means callers aren't forced to return Task.CompletedTask.
  • The Connected event has been removed since StartAsync represents the same thing. If we need to support a model where outside actors need to subscribe to the event we can consider making Start return the same task instead of throwing.
  • The closed event is removed in favor of a cancellation token. It means you can poll for closure as well as use a callback. It also allows passing the connection lifetime to other APIs. It also means you can get notified that the connection has closed after it has closed. One downside of this is that you can't run async logic that we wait on.
public interface IConnection
{
    Task StartAsync(CancellationToken cancellationToken = default);
    Task DisposeAsync(CancellationToken cancellationToken = default);
    Task SendAsync(byte[] data, CancellationToken cancellationToken = default);

    public CancellationToken ClosedToken { get; }

    public IDisposable OnReceived(Func<byte[], object, Task> callback, object state);

    IFeatureCollection Features { get; }
}

public class HubConnection
{
    Task StartAsync(CancellationToken cancellationToken = default);
    Task DisposeAsync(CancellationToken cancellationToken = default);
    Task InvokeAsync(string method, CancellationToken cancellationToken = default, params object[] args);
    Task SendAsync(string method, CancellationToken cancellationToken = default, params object[] args);
    Task<ReadableChannel<object>> StreamAsync(string method, CancellationToken cancellationToken = default, params object[] args);

    public CancellationToken ClosedToken { get; }

    IDisposable On(string methodName, Type[] parameterTypes, Func<object[], object, Task> callback, object state);
}

PS: This doesn't take into account the possibility that we might want to change IConnection to be pipe based in the near future (this means Send and Receive would go away).

/cc @moozzyk

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions