我在项目中使用了一些Kafka Channel层次结构:
我的基本特征是:
function Selector($injector) {
var vm = this;
vm.constant = $injector.get(constantProvider);
}
<selector
constant-provider="SOME_OTHER_CONSTANTS"
form="vm.myForm"
model="vm.myModel>
</selector>
现在我有一个常见的kafka发送频道,如
module.factory('MyConstants', function(CONSTANTS, SOME_OTHER_CONSTANTS) {
return {
name1: CONSTANTS, name2: SOME_OTHER_CONSTANTS
}
});
现在CommanKafkaSendChannel有2个变体,一个是回调,一个是Future:
trait SendChannel[A, B] extends CommunicationChannel {
def send(data:A): B
}
trait CommonKafkaSendChannel[A, B, Return] extends SendChannel[A, Return] {
val channelProps: KafkaSendChannelProperties
val kafkaProducer: Producer[String, B]
override def close(): Unit = kafkaProducer.close()
}
定义:
trait KafkaSendChannelWithFuture[A, B] extends CommonKafkaSendChannel[A, B, Future[RecordMetadata]] {
override def send(data: A): Future[RecordMetadata] = Future {
kafkaProducer.send(new ProducerRecord[String, B](channelProps.topic)).get
}
}
现在根据配置值,我在运行时选择合适的通道类型,如下所示。我正在创建具有正确类型的通道的actor,它将数据发送到kafka:
KafkaSendChannelWithCallback
演员定义:
object KafkaSendChannelWithCallback {
def apply[A, B](oChannelProps: KafkaSendChannelProperties,
oKafkaProducer: Producer[String, B],
oCallback: Callback): KafkaSendChannelWithCallback[A, B] =
new KafkaSendChannelWithCallback[A,B] {
override val channelProps: KafkaSendChannelProperties = oChannelProps
override val kafkaProducer: Producer[String, B] = oKafkaProducer
override val callback: Callback = oCallback
}
}
trait KafkaSendChannelWithCallback[A, B] extends CommonKafkaSendChannel[A, B, Unit] {
val callback: Callback
override def send(data: A): Unit =
kafkaProducer.send(new ProducerRecord[String, B](channelProps.topic), callback)
}
问题是,当我使用 val sendChannel = kafkaChannel.channel(config, actorSystem).fold(
error => {
logger.error("Exception while instantiating the KafkaSendChannel")
throw error
},
success => success
)
actor = actorSystem.actorOf(IngestionActor.props(config, sendChannel), name = ACTOR_NAME)
时,我的代码会正确编译,但是当我使用object IngestionRouterActor {
def props[V](config: Config, sendChannel: SendChannel[V, Unit]): Props =
Props(classOf[IngestionActor[V]], config, sendChannel)
}
时,它会在KafkaSendChannelWithCallback
声明中给出以下错误:
[error] IngestionActor.scala:32:模式类型与预期类型不兼容; [错误]发现:KafkaSendChannelWithFuture [String,V] [error] required:SendChannel [V,Unit]
由于两个通道定义都是从KafkaSendChannelWithFuture
扩展而来的,因此该代码应该编译时没有任何错误。我不确定为什么它不编译。感谢
答案 0 :(得分:1)
Props
的{{1}}需要IngestionActor
。传入SendChannel[V, Unit]
到这个参数是有效的,因为它是KafkaSendChannelWithCallback
。
另一方面,SendChannel[V, Unit]
是KafkaSendChannelWithFuture
。 SendChannel[V, Future[RecordMetadata]]
不 SendChannel[V, Future[RecordMetadata]]
。
一种选择是重新定义SendChannel[V, Unit]
以获取Props
,因为SendChannel[V, Any]
是Any
和Unit
的超类型:
Future
此时,编译器仍然不满意,因为作为泛型类型的def props[V](config: Config, sendChannel: SendChannel[V, Any]): Props = ???
默认情况下是不变的。换句话说,SendChannel
和SendChannel[V, Unit]
都不属于SendChannel[V, Future[RecordMetadata]]
类型。
要更改此设置,请在第二个类型参数上设置SendChannel[V, Any]
协变(通过在SendChannel
前添加+
):
B