Skip to content

Migration Guide

This guide is intended to help you migrate from the previous version of the library (0.x) to the latest version. There have been significant changes with the introduction of v1, but they are mostly related to how channels are created and configured. The core concepts and the middleware pipeline remain the same.

Channel Builder

The previous Channels version used a single method to configure the channel and the listener, all in a single step. This has been replaced with a builder pattern that separates the configuration of the channels from the remaining functionality (listeners, clients, etc.), allowing for more flexibility and better extensibility.

This new builder pattern also means that all channel configurations are now named, even if we only have a default one. All the examples in this guide will use the default configuration for simplicity, but the same principles apply to other named channels.

Channel Configuration with v0.x

Here's an example of how we would configure a channel, along with a TCP listener on port 8080, in the previous version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    /*
    channel and listener options are mixed
    */
    channel.Configure( options =>
    {
        options.BufferEndianness = Endianness.LittleEndian;
        options.Port = 8080;
    } );

    channel.AddInputAdapter<Adapter1>()
        .AddInputHandler<Handler1>();
} );

Channel (default) Configuration with v1

And here's how we can achieve the same with the new version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    /*
    only channel options can be set here
    */
    channel.Configure( options =>
    {
        options.BufferEndianness = Endianness.LittleEndian;
    } );

    channel.AddInputAdapter<Adapter1>()
        .AddInputHandler<Handler1>();
} );

/*
this is how we add a TCP listener with the default channel configuration
*/
services.AddTcpChannelListener( 8080 );

Essentially, the main difference is that the channel builder is only for configuring the channel itself. Adding additional functionality, such as listeners, is done separately.

Client

Although the previous version of the library did not have a true client implementation, it was possible to create a client-side channel by using the IClientChannelFactory. This has disappeared with the new version, and a new client implementation has been introduced. This is a true client and manages the connection to the server, automatically reconnecting if the connection is lost.

The previous version of the client also doesn't work if a listener was running in the same application and a different channel configuration was required, since the pipeline factory was shared (see issue on GitHub). The new version allows to either share a channel configuration or use a different one for each.

Client with v0.x

This is how we would create a client channel in the previous version of the library:

IServiceCollection services = ...;

services.AddClientChannelFactory( channel =>
{
    channel.Configure( options =>
    {
        options.Host = "localhost";
        options.Port = 8080;
    } );

    channel.AddInputAdapter<Adapter1>()
        .AddInputHandler<Handler1>();
} );

// ...

IClientChannelFactory channelFactory = ...;
IChannel channel = await channelFactory.CreateAsync();

Client with v1

And this is how we can create a Channels Client in the new version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    channel.AddInputAdapter<Adapter1>()
        .AddInputHandler<Handler1>();
} );

/*
this registers a default client with the default channel configuration
*/
services.AddChannelsClient( "tcp://localhost:8080" );

// ...

IChannelsClientFactory clientFactory = ...;

// this creates the default client
IChannelsClient client = clientFactory.Create();

Again, we can see that the channel configuration is separated from the rest of the functionality. This allows for more flexibility and we can have a server and a client running in the same application, each with its own configuration.

Note

Please note that channel name and client name are two different things. The channel name identifies the channel configuration, while the client name is used to identify a client instance.

Idle Detection

The idle detection mechanism has seen a few changes throughout the different versions of the library. In earlier versions, the idle detection was enabled internally by default, while more recent versions introduced an idling channel service that needed to be explicitly registered. The latest version of the library has dropped the channel service in favor of an internal mechanism that is simpler and more efficient; it is also enabled by default (again).

Idle Detection with v0.x

This is how we would configure the idle detection in the previous version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    // ...

    // adds the idle channel service with the default 60 seconds timeout
    channel.AddIdleChannelService();
} );

Idle Detection with v1

With the latest version of the library, the idle detection mechanism is enabled by default and we can configure it directly in the channel options:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    channel.Configure( options =>
    {
        /*
        60 seconds is the default setting.
        To disable the idle detection, set the value to `TimeSpan.Zero`
        */
        options.IdleTimeout = TimeSpan.FromSeconds( 60 );
    } );

    // ...
} );

Metrics

Prometheus metrics are still available as an extension, but are no longer set from the channel builder. Like the other functionalities, such as listeners and clients, the metrics are now registered separately. Everything else remains the same.

Metrics with v0.x

This is how we would add the metrics collector in the previous version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    // ...

    channel.UsePrometheusMetrics();
} );

Metrics with v1

And this is how we can add the metrics collector in the new version of the library:

IServiceCollection services = ...;

services.AddChannels( channel =>
{
    // ...
} );

services.AddChannelMetrics();