Skip to content

Commit

Permalink
Merge branch 'master' into hotfix/DI
Browse files Browse the repository at this point in the history
  • Loading branch information
mayuki authored Dec 5, 2019
2 parents f1124e5 + d41a104 commit bbf56c2
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 41 deletions.
73 changes: 68 additions & 5 deletions sandbox/Sandbox.Hosting/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ static async Task Main(string[] args)
options.Service.GlobalStreamingHubFilters.Add<MyStreamingHubFilterAttribute>();
// options.Service.GlobalStreamingHubFilters.Add(new MyStreamingHubFilterAttribute(logger));

options.Service.GlobalFilters.Add<MyFilterAttribute>(); // Register filter by type.
options.Service.GlobalFilters.Add(new MyFilterUsingFactoryAttribute("Global")); // Register filter with IMagicOnionFilterFactory.
// options.Service.GlobalFilters.Add(new MyFilterAttribute(null));
options.Service.GlobalFilters.Add<MyFilterAttribute>();
options.Service.GlobalFilters.Add<MyFilter2Attribute>();
options.Service.GlobalFilters.Add<MyFilter3Attribute>();
// options.Service.GlobalFilters.Add(new MyFilterAttribute(logger));

// options.ServerPorts = new[]{ new MagicOnionHostingServerPortOptions(){ Port = opti

// options.ServerPorts = new[]{ new MagicOnionHostingServerPortOptions(){ Port = 12345, Host = "0.0.0.0", UseInsecureConnection = true } };
}
options.ChannelOptions.MaxReceiveMessageLength = 1024 * 1024 * 10;
options.ChannelOptions.Add(new ChannelOption("grpc.keepalive_time_ms", 10000));
Expand All @@ -71,7 +72,7 @@ static async Task Main(string[] args)
result = await clientMyService.HelloAsync();
var result2 = await clientManagementService.FooBarAsync();

var clientHub = StreamingHubClient.Connect<IMyHub, IMyHubReceiver>(new Channel("localhost", 12345, creds), null);
var clientHub = StreamingHubClient.Connect<IMyHub, IMyHubReceiver>(new Channel("localhost", 12345, creds), new MyHubReceiver());
var result3 = await clientHub.HelloAsync();

var streamingHubClient = StreamingHubClient.Connect<IMyHub, IMyHubReceiver>(new Channel("localhost", 12345, creds), null);
Expand All @@ -85,6 +86,14 @@ static async Task Main(string[] args)

await hostTask;
}

class MyHubReceiver : IMyHubReceiver
{
public void OnNantoka(string value)
{
Console.WriteLine(value);
}
}
}

public class MyHostedService : IHostedService
Expand Down Expand Up @@ -139,6 +148,7 @@ public override async ValueTask Invoke(StreamingHubContext context, Func<Streami
}
}


public class MyFilterAttribute : MagicOnionFilterAttribute
{
private readonly ILogger _logger;
Expand Down Expand Up @@ -166,6 +176,42 @@ public override async ValueTask Invoke(ServiceContext context, Func<ServiceConte
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class MyFilterUsingFactoryAttribute : Attribute, IMagicOnionFilterFactory<MagicOnionFilterAttribute>
{
public int Order { get; set; }
public string Label { get; set; }

public MyFilterUsingFactoryAttribute(string label)
{
Label = label;
}

MagicOnionFilterAttribute IMagicOnionFilterFactory<MagicOnionFilterAttribute>.CreateInstance(IServiceLocator serviceLocator)
{
return new MyFilterUsingFactory(serviceLocator.GetService<ILoggerFactory>().CreateLogger<MyFilterUsingFactoryAttribute>(), Label);
}
}

internal class MyFilterUsingFactory : MagicOnionFilterAttribute
{
private readonly ILogger _logger;
private readonly string _label;

public MyFilterUsingFactory(ILogger logger, string label)
{
this._logger = logger;
this._label = label;
}

public override async ValueTask Invoke(ServiceContext context, Func<ServiceContext, ValueTask> next)
{
_logger.LogInformation($"MyFilterUsingFactory[{_label}] Begin: {context.CallContext.Method}");
await next(context);
_logger.LogInformation($"MyFilterUsingFactory[{_label}] End: {context.CallContext.Method}");
}
}

public class MyFilter2Attribute : MagicOnionFilterAttribute
{
public override async ValueTask Invoke(ServiceContext context, Func<ServiceContext, ValueTask> next) => await next(context);
Expand All @@ -186,6 +232,7 @@ public class MyService : ServiceBase<IMyService>, IMyService
public MyService(MySingletonService foo, MyScopedService bar)
{
}
[MyFilterUsingFactoryAttribute("PerMethod")]
public async UnaryResult<string> HelloAsync()
{
return "Konnichiwa";
Expand All @@ -206,6 +253,7 @@ public async UnaryResult<int> FooBarAsync()

public interface IMyHubReceiver
{
void OnNantoka(string value);
}

public interface IMyHub : IStreamingHub<IMyHub, IMyHubReceiver>
Expand All @@ -219,6 +267,21 @@ public MyHub(MyScopedService scopedService)
{ }

public MyHub() => Console.WriteLine($"{this.GetType().Name}..ctor");
public Task<string> HelloAsync() => Task.FromResult("Konnichiwa!");

public async Task<string> HelloAsync()
{
var group = await this.Group.AddAsync("Nantoka");
group.CreateBroadcaster<IMyHubReceiver>().OnNantoka("BroadcastAll");
group.CreateBroadcasterTo<IMyHubReceiver>(Context.ContextId).OnNantoka("BroadcastTo(Self)");
group.CreateBroadcasterTo<IMyHubReceiver>(Guid.NewGuid()).OnNantoka("BroadcastTo(Non-self)");
group.CreateBroadcasterTo<IMyHubReceiver>(new[] { Guid.NewGuid(), Guid.NewGuid() }).OnNantoka("BroadcastTo(Non-self, Non-self)");
group.CreateBroadcasterTo<IMyHubReceiver>(new[] { Context.ContextId, Guid.NewGuid() }).OnNantoka("BroadcastTo(Self, Non-self)");
group.CreateBroadcasterExcept<IMyHubReceiver>(Context.ContextId).OnNantoka("BroadcastExcept(Self)");
group.CreateBroadcasterExcept<IMyHubReceiver>(Guid.NewGuid()).OnNantoka("BroadcastExcept(Non-self)");
group.CreateBroadcasterExcept<IMyHubReceiver>(new[] { Guid.NewGuid(), Guid.NewGuid() }).OnNantoka("BroadcastExcept(Non-self, Non-self)");
group.CreateBroadcasterExcept<IMyHubReceiver>(new[] { Context.ContextId, Guid.NewGuid() }).OnNantoka("BroadcastExcept(Self, Non-self)");

return "Konnnichiwa!";
}
}
}
26 changes: 24 additions & 2 deletions src/MagicOnion.OpenTelemetry/MagicOnionCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,18 @@ public void WriteToStream(ServiceContext context, byte[] writeData, Type type)
/// <summary>
/// Global filter. Handle Unary and most outside logging.
/// </summary>
public class OpenTelemetryCollectorFilter : MagicOnionFilterAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class OpenTelemetryCollectorFilterAttribute : Attribute, IMagicOnionFilterFactory<MagicOnionFilterAttribute>
{
public int Order { get; set; }

public MagicOnionFilterAttribute CreateInstance(IServiceLocator serviceLocator)
{
return new OpenTelemetryCollectorFilter(serviceLocator.GetService<ITracer>(), serviceLocator.GetService<ISampler>());
}
}

internal class OpenTelemetryCollectorFilter : MagicOnionFilterAttribute
{
readonly ITracer tracer;
readonly ISampler sampler;
Expand Down Expand Up @@ -334,7 +345,18 @@ public override async ValueTask Invoke(ServiceContext context, Func<ServiceConte
/// <summary>
/// StreamingHub Filter. Handle Streaming Hub logging.
/// </summary>
public class OpenTelemetryHubCollectorFilter : StreamingHubFilterAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class OpenTelemetryHubCollectorFilterAttribute : Attribute, IMagicOnionFilterFactory<StreamingHubFilterAttribute>
{
public int Order { get; set; }

public StreamingHubFilterAttribute CreateInstance(IServiceLocator serviceLocator)
{
return new OpenTelemetryHubCollectorFilter(serviceLocator.GetService<ITracer>(), serviceLocator.GetService<ISampler>());
}
}

internal class OpenTelemetryHubCollectorFilter : StreamingHubFilterAttribute
{
readonly ITracer tracer;
readonly ISampler sampler;
Expand Down
67 changes: 67 additions & 0 deletions src/MagicOnion/Server/Hubs/Group.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,71 @@ public void Remove(Guid id)
storage.TryRemove(id, out _);
}
}

public static class GroupBroadcastExtensions
{
/// <summary>
/// Create a receiver proxy from the group. Can be use to broadcast messages to all clients.
/// </summary>
/// <typeparam name="TReceiver"></typeparam>
/// <param name="group"></param>
/// <returns></returns>
public static TReceiver CreateBroadcaster<TReceiver>(this IGroup group)
{
var type = DynamicBroadcasterBuilder<TReceiver>.BroadcasterType;
return (TReceiver) Activator.CreateInstance(type, group);
}

/// <summary>
/// Create a receiver proxy from the group. Can be use to broadcast messages to all clients excepts one.
/// </summary>
/// <typeparam name="TReceiver"></typeparam>
/// <param name="group"></param>
/// <param name="except"></param>
/// <returns></returns>
public static TReceiver CreateBroadcasterExcept<TReceiver>(this IGroup group, Guid except)
{
var type = DynamicBroadcasterBuilder<TReceiver>.BroadcasterType_ExceptOne;
return (TReceiver) Activator.CreateInstance(type, new object[] {group, except});
}

/// <summary>
/// Create a receiver proxy from the group. Can be use to broadcast messages to all clients excepts some clients.
/// </summary>
/// <typeparam name="TReceiver"></typeparam>
/// <param name="group"></param>
/// <param name="excepts"></param>
/// <returns></returns>
public static TReceiver CreateBroadcasterExcept<TReceiver>(this IGroup group, Guid[] excepts)
{
var type = DynamicBroadcasterBuilder<TReceiver>.BroadcasterType_ExceptMany;
return (TReceiver) Activator.CreateInstance(type, new object[] {group, excepts});
}

/// <summary>
/// Create a receiver proxy from the group. Can be use to broadcast messages to one client.
/// </summary>
/// <typeparam name="TReceiver"></typeparam>
/// <param name="group"></param>
/// <param name="toConnectionId"></param>
/// <returns></returns>
public static TReceiver CreateBroadcasterTo<TReceiver>(this IGroup group, Guid toConnectionId)
{
var type = DynamicBroadcasterBuilder<TReceiver>.BroadcasterType_ToOne;
return (TReceiver) Activator.CreateInstance(type, new object[] { group, toConnectionId });
}

/// <summary>
/// Create a receiver proxy from the group. Can be use to broadcast messages to some clients.
/// </summary>
/// <typeparam name="TReceiver"></typeparam>
/// <param name="group"></param>
/// <param name="toConnectionIds"></param>
/// <returns></returns>
public static TReceiver CreateBroadcasterTo<TReceiver>(this IGroup group, Guid[] toConnectionIds)
{
var type = DynamicBroadcasterBuilder<TReceiver>.BroadcasterType_ToMany;
return (TReceiver) Activator.CreateInstance(type, new object[] { group, toConnectionIds });
}
}
}
6 changes: 2 additions & 4 deletions src/MagicOnion/Server/Hubs/StreamingHubHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ public StreamingHubHandler(Type classType, MethodInfo methodInfo, StreamingHubHa
this.filters = handlerOptions.GlobalStreamingHubFilters
.OfType<IMagicOnionFilterFactory<StreamingHubFilterAttribute>>()
.Concat(classType.GetCustomAttributes<StreamingHubFilterAttribute>(true).Select(x => new StreamingHubFilterDescriptor(x, x.Order)))
.Concat(classType.GetCustomAttributes<FromTypeFilterAttribute>(true))
.Concat(classType.GetCustomAttributes<FromServiceFilterAttribute>(true))
.Concat(classType.GetCustomAttributes(true).OfType<IMagicOnionFilterFactory<StreamingHubFilterAttribute>>())
.Concat(methodInfo.GetCustomAttributes<StreamingHubFilterAttribute>(true).Select(x => new StreamingHubFilterDescriptor(x, x.Order)))
.Concat(methodInfo.GetCustomAttributes<FromTypeFilterAttribute>(true))
.Concat(methodInfo.GetCustomAttributes<FromServiceFilterAttribute>(true))
.Concat(methodInfo.GetCustomAttributes(true).OfType<IMagicOnionFilterFactory<StreamingHubFilterAttribute>>())
.OrderBy(x => x.Order)
.ToArray();

Expand Down
Loading

0 comments on commit bbf56c2

Please sign in to comment.