Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
516 views
in Technique[技术] by (71.8m points)

scala - Akka Streams Covarience for SourceQueueWithComplete

I have an Actor which is created from within a SupervisorActor and this Actor is responsible for pushing the messages that it gets into a stream. Here is the Actor:

class KafkaPublisher[T <: KafkaMessage: ClassTag] extends Actor {

  implicit val system = context.system
  val log = Logging(system, this.getClass.getName)

  override final def receive = {
    case ProducerStreamActivated(_, stream: SourceQueueWithComplete[T]) =>
      log.info(s"Activated stream for Kafka Producer with ActorName >> ${self.path.name} << ActorPath >> ${self.path} <<")
      context.become(active(stream))

    case other =>
      log.warning("KafkaPublisher got some unknown message while producing: " + other)
  }

  def active(stream: SourceQueueWithComplete[T]): Receive = {
    case msg: T =>
      log.info(s"Got Message >> $msg << Pushing it to stream $stream")
      stream.offer(msg)

    case other =>
      log.warning("KafkaPublisher got the unknown message while producing: " + other)
  }
}
object KafkaPublisher {

  def props[T <: KafkaMessage: ClassTag] =
    Props(new KafkaPublisher[T])
}

As it can be seen that this Actor works on a generic message type as the SupervisorActor is responsible for creating concrete instances of this generic Actor.

trait Event
object Event {
  case class ProducerStreamActivated[T <: KafkaMessage](kafkaTopic: String, stream: SourceQueueWithComplete[T]) extends Event
}

trait KafkaMessage
object KafkaMessage {

  case class DefaultMessage(message: String, timestamp: DateTime) extends KafkaMessage {
    def this() = this("DEFAULT-EMPTY-MESSAGE", DateTime.now(DateTimeZone.UTC))
  }

  case class DefaultMessageBundle(messages: Seq[DefaultMessage], timeStamp: DateTime) extends KafkaMessage {
    def this() = this(Seq.empty, DateTime.now(DateTimeZone.UTC))
  }
}

Obviously, I get the following error:

Error:(17, 45) pattern type is incompatible with expected type;
 found   : akka.stream.scaladsl.SourceQueueWithComplete[T]
 required: akka.stream.scaladsl.SourceQueueWithComplete[com.eon.pm.messages.KafkaMessage]
Note: T <: com.my.project.messages.KafkaMessage, but trait SourceQueueWithComplete is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
    case ProducerStreamActivated(_, stream: SourceQueueWithComplete[T]) =>

The SourceQueueWithComplete is not Covariant. How can I mitigate this? Any suggestions?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

like:

class KafkaPublisher extends Actor {

  implicit val system = context.system
  val log = Logging(system, this.getClass.getName)

  override final def receive = {
    case ProducerStreamActivated(_, stream) =>
      log.info(s"Activated stream for Kafka Producer with ActorName >> ${self.path.name} << ActorPath >> ${self.path} <<")
      context.become(active(stream))

    case other =>
      log.warning("KafkaPublisher got some unknown message while producing: " + other)
  }

  def active(stream: SourceQueueWithComplete[KafkaMessage]): Receive = {
    case msg: DefaultMessage =>
      log.info(s"Got Message >> $msg << Pushing it to stream $stream")
      stream.offer(msg)

    case msg: DefaultMessageBundle =>
      log.info(s"Got Message >> $msg << Pushing it to stream $stream")
      stream.offer(msg)

    case other =>
      log.warning("KafkaPublisher got the unknown message while producing: " + other)
  }
}
object KafkaPublisher {

  def props = Props(new KafkaPublisher)
}

trait Event
object Event {
  case class ProducerStreamActivated(kafkaTopic: String, stream: SourceQueueWithComplete[KafkaMessage]) extends Event
}

trait KafkaMessage
object KafkaMessage {

  case class DefaultMessage(message: String, timestamp: DateTime) extends KafkaMessage {
    def this() = this("DEFAULT-EMPTY-MESSAGE", DateTime.now(DateTimeZone.UTC))
  }

  case class DefaultMessageBundle(messages: Seq[DefaultMessage], timeStamp: DateTime) extends KafkaMessage {
    def this() = this(Seq.empty, DateTime.now(DateTimeZone.UTC))
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...