Last active
November 3, 2017 09:35
-
-
Save rikbosch/508661d423ac4228c1ac5a4a4c7f28f8 to your computer and use it in GitHub Desktop.
OrleansCommunicationListener 2.0.0-beta1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal class OrleansSiloHostCommunicationListener : ICommunicationListener | |
{ | |
private readonly ISiloHost _host; | |
public OrleansSiloHostCommunicationListener(StatelessService service, Action<ISiloHostBuilder> app) | |
{ | |
var builder = new SiloHostBuilder(); | |
//configure | |
app(builder); | |
//add SF | |
builder.AddServiceFabric(service); | |
_host = builder.Build(); | |
} | |
public async Task<string> OpenAsync(CancellationToken cancellationToken) | |
{ | |
await _host.StartAsync(cancellationToken); | |
// mimic default orleans service fabric communicationlistener | |
var nodeConfig = _host.Services.GetRequiredService<NodeConfiguration>(); | |
return JsonConvert.SerializeObject(new FabricSiloInfo(nodeConfig)); | |
} | |
public Task CloseAsync(CancellationToken cancellationToken) | |
{ | |
return _host.StopAsync(cancellationToken); | |
} | |
public void Abort() | |
{ | |
_host.Services.GetRequiredService<Silo>().Stop(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class SerivceFabricSiloHostBuilderExtensions | |
{ | |
/// <summary> | |
/// Add servicefabric support to silohost builder | |
/// Use last of chain | |
/// </summary> | |
/// <param name="builder"></param> | |
/// <param name="service"></param> | |
/// <returns></returns> | |
public static ISiloHostBuilder AddServiceFabric(this ISiloHostBuilder builder, StatelessService service) | |
{ | |
//SF specific | |
builder.ConfigureServices(x => | |
{ | |
x.AddServiceFabricSupport(service); | |
x.AddSingleton(service.Context); | |
x.Decorate<ClusterConfiguration>((config, provider) => | |
{ | |
AdaptForServiceFabric(config, provider.GetRequiredService<StatelessServiceContext>()); | |
return config; | |
}); | |
x.Configure<SiloIdentityOptions>(options => | |
{ | |
options.SiloName = GetDefaultSiloName(service); | |
}); | |
}); | |
return builder; | |
} | |
private static string GetDefaultSiloName(StatelessService service) | |
{ | |
return Regex.Replace(service.Context.ServiceName.PathAndQuery.Trim('/'), "[^a-zA-Z0-9_]", "_") + "_" + | |
service.Context.ReplicaOrInstanceId.ToString("X"); | |
} | |
/// <summary> | |
/// The name used to identify the silo-to-silo communication endpoint. | |
/// </summary> | |
public const string SiloEndpointName = "OrleansSiloEndpoint"; | |
/// <summary> | |
/// The name used to identify the client-to-silo communication endpoint. | |
/// </summary> | |
public const string GatewayEndpointName = "OrleansProxyEndpoint"; | |
static void AdaptForServiceFabric(ClusterConfiguration config, StatelessServiceContext context) | |
{ | |
var activation = context.CodePackageActivationContext; | |
var endpoints = activation.GetEndpoints(); | |
var siloEndpoint = GetEndpoint(endpoints, SiloEndpointName); | |
var gatewayEndpoint = GetEndpoint(endpoints, GatewayEndpointName); | |
if (string.IsNullOrWhiteSpace(config.Defaults.HostNameOrIPAddress)) | |
{ | |
config.Defaults.HostNameOrIPAddress = context.NodeContext.IPAddressOrFQDN; | |
} | |
config.Defaults.Port = siloEndpoint.Port; | |
config.Defaults.ProxyGatewayEndpoint = new IPEndPoint(config.Defaults.Endpoint.Address, gatewayEndpoint.Port); | |
if (config.Defaults.Generation == 0) | |
{ | |
config.Defaults.Generation = SiloAddress.AllocateNewGeneration(); | |
} | |
} | |
static EndpointResourceDescription GetEndpoint( | |
KeyedCollection<string, EndpointResourceDescription> endpoints, | |
string endpointName) | |
{ | |
if (!endpoints.Contains(endpointName)) | |
{ | |
throw new KeyNotFoundException( | |
$"Endpoint \"{endpointName}\" not found in service manifest. Ensure the service has a TCP endpoint with that name."); | |
} | |
return endpoints[endpointName]; | |
} | |
} | |
public static class ServiceCollectionExtensions | |
{ | |
public static IServiceCollection Decorate<TService>(this IServiceCollection services, Func<TService, IServiceProvider, TService> decorator) | |
{ | |
var descriptors = services.GetDescriptors<TService>(); | |
foreach (var descriptor in descriptors) | |
{ | |
services.Replace(descriptor.Decorate(decorator)); | |
} | |
return services; | |
} | |
public static IServiceCollection Decorate<TService>(this IServiceCollection services, Func<TService, TService> decorator) | |
{ | |
var descriptors = services.GetDescriptors<TService>(); | |
foreach (var descriptor in descriptors) | |
{ | |
services.Replace(descriptor.Decorate(decorator)); | |
} | |
return services; | |
} | |
private static List<ServiceDescriptor> GetDescriptors<TService>(this IServiceCollection services) | |
{ | |
var descriptors = new List<ServiceDescriptor>(); | |
foreach (var service in services) | |
{ | |
if (service.ServiceType == typeof(TService)) | |
{ | |
descriptors.Add(service); | |
} | |
} | |
if (descriptors.Count == 0) | |
{ | |
throw new InvalidOperationException($"Could not find any registered services for type '{typeof(TService).FullName}'."); | |
} | |
return descriptors; | |
} | |
private static ServiceDescriptor Decorate<TService>(this ServiceDescriptor descriptor, Func<TService, IServiceProvider, TService> decorator) | |
{ | |
return descriptor.WithFactory(provider => decorator((TService)descriptor.GetInstance(provider), provider)); | |
} | |
private static ServiceDescriptor Decorate<TService>(this ServiceDescriptor descriptor, Func<TService, TService> decorator) | |
{ | |
return descriptor.WithFactory(provider => decorator((TService)descriptor.GetInstance(provider))); | |
} | |
private static ServiceDescriptor WithFactory(this ServiceDescriptor descriptor, Func<IServiceProvider, object> factory) | |
{ | |
return ServiceDescriptor.Describe(descriptor.ServiceType, factory, descriptor.Lifetime); | |
} | |
private static object GetInstance(this ServiceDescriptor descriptor, IServiceProvider provider) | |
{ | |
if (descriptor.ImplementationInstance != null) | |
{ | |
return descriptor.ImplementationInstance; | |
} | |
if (descriptor.ImplementationType != null) | |
{ | |
return provider.GetServiceOrCreateInstance(descriptor.ImplementationType); | |
} | |
return descriptor.ImplementationFactory(provider); | |
} | |
private static object GetServiceOrCreateInstance(this IServiceProvider provider, Type type) | |
{ | |
return ActivatorUtilities.GetServiceOrCreateInstance(provider, type); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment