Home

Awesome

CoherentSolutions.Extensions.Hosting.ServiceFabric

Build Status nuget package

About the Project

CoherentSolutions.Extensions.Hosting.ServiceFabric is an extension to existing HostBuilder. The idea is to simplify configuration of Reliable Services by removing unnecessary code and improving separation of concerns.

Getting Started

As usual, the easiest way to get started is to code → a new Reliable Service!

NOTE

This section doesn't present and explains all features / aspects of the CoherentSolutions.Extensions.Hosting.ServiceFabric. The complete documentation is available on project wiki.

In this section we will:

  1. Configure one stateful service
  2. Configure three endpoints (by configuring three listeners: ASP.NET Core, Remoting and Generic)
  3. Configure one background job (by configuring a delegate to run on RunAsync lifecycle event).

Initial setup

All programs start from entry point and so do Reliable Services. When using CoherentSolutions.Extensions.Hosting.ServiceFabric application entry point starts with new instance of the HostBuilder class followed by calls to Build() and Run() methods.

private static void Main(string[] args)
{
    new HostBuilder()
        .Build()
        .Run();
}

Reliable Service's configuration is done within configuration action accepted by DefineStatefulService(...) or DefineStatelessService(...) extension methods.

NOTE

You can find more details on defining services wiki page.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(serviceBuilder => { })
        .Build()
        .Run();
}

The first step when configuring a service (no matter stateful or stateless) using CoherentSolutions.Extensions.Hosting.ServiceFabric is to "link" configurable service to one of the ServiceTypes declared in the ServiceManifest.xml.

<ServiceManifest Name="ServicePkg" Version="1.0.0">
  <ServiceTypes>
    <StatefulServiceType ServiceTypeName="ServiceType" HasPersistedState="true" />
  </ServiceTypes>
</ServiceManifest>

The "link" is create using UseServiceType(...) method.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder.UseServiceType("ServiceType");
            })
        .Build()
        .Run();
}

This code is now ready to run. CoherentSolutions.Extensions.Hosting.ServiceFabric will do all the plumbing required to start the service.

Unfortunatelly it's current implementation is empty and does nothing.

Configuring Endpoints

Reliable Services can expose endpoints. This exposure is represented in form of listeners configured on replica startup. The CoherentSolutions.Extensions.Hosting.ServiceFabric provides a simple way to configure: ASP.NET Core, Remoting listeners and Generic listeners.

All listeners are configured using the same flow as was demonstrated for services.

NOTE

You can find more details on defining listeners wiki page.

ASP.NET Core

ASP.NET Core listener configuration starts with a call to .DefineAspNetCoreListener(...) method. This method accepts an action where all listener specific configuration is done.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType("ServiceType")
                    .DefineAspNetCoreListener(listenerBuilder => { });
            })
        .Build()
        .Run();
}

The listener should be linked to one of the endpoint resources defined in the ServiceManifest.xml.

<ServiceManifest Name="ServicePkg" Version="1.0.0">
  <Resources>
    <Endpoints>
      <Endpoint Name="ServiceEndpoint" />
    </Endpoints>
  </Resources>
</ServiceManifest>

The linkage is done using UseEndpoint(...) method.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType("ServiceType")
                    .DefineAspNetCoreListener(
                        listenerBuilder =>
                        {
                            listenerBuilder.UseEndpoint("ServiceEndpoint");
                        });
            })
        .Build()
        .Run();
}

The listener is an infrastructure wrapper around the configuration process of IWebHost. The IWebHost configuration is done in ConfigureWebHost(...) method.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType("ServiceType")
                    .DefineAspNetCoreListener(
                        listenerBuilder =>
                        {
                            listenerBuilder
                                .UseEndpoint("ServiceEndpoint")
                                .ConfigureWebHost(webHostBuilder => { webHostBuilder.UseStartup<Startup>(); });
                        });
            })
        .Build()
        .Run();
}

Remoting

Remoting listener has slightly different configuration curse than ASP.NET Core listener. The configuration starts from the call to DefineRemotingListener(...) and UseEndpoint(...) methods.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType(...)
                    .DefineAspNetCoreListener(...)
                    .DefineRemotingListener(
                        listenerBuilder =>
                        {
                            listenerBuilder
                                .UseEndpoint("ServiceEndpoint2");
                        });
            })
        .Build()
        .Run();
}

The remoting implementation consists from two parts: remoting interface and remoting implementation.

remoting interface defines the API surface...

public interface IApiService : IService
{
    Task<string> GetVersionAsync();
}

... while remoting class implements the API.

public class ApiServiceImpl : IApiService
{
    public Task<string> GetVersionAsync()
    {
        return Task.FromResult("1.0");
    }
}

Remoting implementations is configured using UseImplementation<T>(...) method.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType(...)
                    .DefineAspNetCoreListener(...)
                    .DefineRemotingListener(
                        listenerBuilder =>
                        {
                            listenerBuilder
                                .UseEndpoint("ServiceEndpoint2")
                                .UseImplementation<ApiServiceImpl>();
                        });
            })
        .Build()
        .Run();
}

Generic Implementation

Generic listener allows custom listeners to be configured using the same approach as DefineRemotingListener(...) and DefineAspNetCoreListener(...).

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType(...)
                    .DefineAspNetCoreListener(...)
                    .DefineRemotingListener(...)
                    .DefineGenericListener(...)
                        listenerBuilder =>
                        {
                            listenerBuilder
                                .UseEndpoint("ServiceEndpoint3")
                                .UseCommunicationListener(
                                    (context, name, provider) =>
                                    {
                                        return /* ICommunicationListener */;
                                    })
                        });
            })
        .Build()
        .Run();
}

Configuring a Background Job

In CoherentSolutions.Extensions.Hosting.ServiceFabric background jobs and event handlers are represented in form of Delegates. The Delegate is configured using DefineDefine(...) method.

You can find more details on defining delegates wiki page.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType(...)
                    .DefineAspNetCoreListener(...)
                    .DefineRemotingListener(...)
                    .DefineDelegate(delegateBuilder => { });
            })
        .Build()
        .Run();
}

The action to execute is configured by calling UseDelegate(...) method with accepts any Action<...> or Func<..., Task> compatible delegate.

private static void Main(string[] args)
{
    new HostBuilder()
        .DefineStatefulService(
            serviceBuilder =>
            {
                serviceBuilder
                    .UseServiceType(...)
                    .DefineAspNetCoreListener(...)
                    .DefineRemotingListener(...)
                    .DefineDelegate(
                        delegateBuilder =>
                        {
                            delegateBuilder.UseDelegate(async () => await Database.MigrateDataAsync());
                        })
            })
        .Build()
        .Run();
}

Conclusion

That is it :)

Documentation

For project documentation please refer to project wiki.

What's new?

For information on past releases please refer to version history page.

Contributing

For additional information on how to contribute to this project, please see CONTRIBUTING.md.

Samples

Authors

This project is owned and maintained by Coherent Solutions.

License

This project is licensed under the MIT License - see the LICENSE.md for details.

See Also

Besides this project Coherent Solutions also maintains a few more open source projects and workshops:

Projects

Workshops