Open Kermel opened 8 months ago
Hmm after some more experiments I found out... that I cannot find out where the problem is. :/
I managed to properly use this functionality by registering my listeners like this:
builder.Services.AddSingleton<ProcessingDispatcher>();
builder.Services.AddSingleton<IProcessingDispatcher>(sp => sp.GetRequiredService<ProcessingDispatcher>());
builder.Services.AddSingleton<IListener<QueueTaskCompleted>>(sp => sp.GetRequiredService<ProcessingDispatcher>());
builder.Services.AddSingleton<IListener<DequeuedTaskFailed>>(sp => sp.GetRequiredService<ProcessingDispatcher>());
and with subscription code:
var eventReg = builder.ApplicationServices.ConfigureEvents();
eventReg.Register<QueueTaskCompleted>().Subscribe<IListener<QueueTaskCompleted>>();
eventReg.Register<DequeuedTaskFailed>().Subscribe<IListener<DequeuedTaskFailed>>();
Then I have it's implementation with explicit interface implementations:
internal class ProcessingDispatcher : IProcessingDispatcher, IListener<QueueTaskCompleted>, IListener<DequeuedTaskFailed>
{
...
Task IListener<QueueTaskCompleted>.HandleAsync(QueueTaskCompleted broadcasted) =>
Task.CompletedTask;
Task IListener<DequeuedTaskFailed>.HandleAsync(DequeuedTaskFailed broadcasted) =>
Task.CompletedTask;
}
I hope that will help!
Affected Coravel Feature Events boradcasting and Events handling
Describe the bug I have experimented with Events broadcasting and created a listener class to handle both the queue events:
and it doesn't do anything. In the background, I have found exceptions thrown by the Dispatcher talking about the ambiguous definition of the "HandleAsync" methods. This is because the code always goes throught the "else" path in the Dispatcher.Broadcast method. The reason is, that this piece of code:) says it is IListener (i.e. the most generic variant)
if (obj is IListener<TEvent> listener)
is never true, because the typeof(IListenerExpected behaviour Event handling works even for listeners capable of handling multiple events.
Suggested fix Actually, I didn't figure out how to exactly fix this as the dynamic casting to a generic type (with runtime-unknown generic type) is a problem. This might help: Dispatcher.cs line 62 containing the
if (obj is IListener<TEvent> listener)
is never true but this:if(obj.GetType().IsAssignableTo(typeof(IListener<TEvent>))
is OK and true as expected(also, the items in the listeners collection have correct types because that's how they get there during subscription so the type check is not needed, just type casting...)
Maybe making the HandleAsync method generic with a generic parameter of the TEvent type? Then the whole if-else block might be dropped and the reflection invocation of the generic method could be used instead. Something like this:
Then you might easily add the listener interfaces to my normal classes and be ready for handling many events and incorporating to the business logic
OR:
after verifying the type
if(obj.GetType().IsAssignableTo(typeof(IListener<TEvent>)))
cast theobj
todynamic
and then call the HandleTask method of which we know it exists and is correct...