Farfetch/kafkaflow

[Feature Request]: Inheritance support in Typed Handler Middleware

gschuager opened this issue · 1 comments

Is your request related to a problem you have?

Let's say that we have an inheritance chain as follows:

interface ITaskEvent { }

record TaskStarted : ITaskEvent { }

record TaskStopped : ITaskEvent { }

I'd like to be able to write an implementation of IMessageHandler<ITaskEvent> (not IMessageHandler<TaskStarted> and IMessageHandler<TaskStopped>) to be used with the Typed Handler middleware.

This is currently not supported and since the involved classes are marked as internal, it cannot be customized without duplicating the entire middleware and its related configuration classes.

Describe the solution you'd like

HandlerTypeMapping.GetHandlersTypes can be adjusted to use Type.IsAssignableFrom to match handlers for base types.

Are you able to help bring it to life and contribute with a Pull Request?

Yes

Additional context

No response

There are also issues with using generic Type Resolvers and multiple serializer/deserializer of the same type with different typed handlers. For example, see the following example

This won't work bc the first serializer picks up everything

					.AddDeserializer(f => new KafkaXmlDeserializer(), f => new MarketDocumentTypeResolver<Acknowledgement_MarketDocument>())
						.AddTypedHandlers(handlers => handlers
							.AddHandler<Acknowledgement_MarketDocumentMessageHandler>()
								.WithHandlerLifetime(InstanceLifetime.Scoped)
							.WhenNoHandlerFound(context =>
								Log.Warning("Message not handled > Partition: {0} | Offset: {1} | Context: {2}",
									context.ConsumerContext.Partition,
									context.ConsumerContext.Offset,
									context.ConsumerContext.ToString()))
							)
					.AddDeserializer(f => new KafkaXmlDeserializer(), f => new MarketDocumentTypeResolver<ReserveAllocation_MarketDocument>())
						.AddTypedHandlers(handlers => handlers
							.AddHandler<ReserveAllocation_MarketDocumentMessageHandler>()
								.WithHandlerLifetime(InstanceLifetime.Scoped)
							.WhenNoHandlerFound(context =>
								Log.Warning("Message not handled > Partition: {0} | Offset: {1} | Context: {2}",
									context.ConsumerContext.Partition,
									context.ConsumerContext.Offset,
									context.ConsumerContext.ToString()))
							)

This also won't work bc the typed resolver doesn't match (matches only the first typed handler but not the others that follow)