2016-11-24 2 views
1

Я создал инъекцию зависимостей с проектом Guice in Spray, как описано в уроке this. МодульРазное Аkkа экземпляры актера получают сообщения

Моего Guice:

class ActorsModule extends AbstractModule with ScalaModule with GuiceAkkaActorRefProvider { 
override def configure() { 
    bind[Actor].annotatedWith(Names.named(GenesActor.name)).to[GenesActor] 
    bind[Actor].annotatedWith(Names.named(SearchSegmentsActor.name)).to[SearchSegmentsActor] 
    bind[Actor].annotatedWith(Names.named(CollectionsFinderActor.name)).to[CollectionsFinderActor] 
    bind[Actor].annotatedWith(Names.named(HttpServiceActor.name)).to[HttpServiceActor] 
} 

@Provides 
@Named(GenesActor.name) 
def provideGenesActorRef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, GenesActor.name) 

@Provides 
@Named(SearchSegmentsActor.name) 
def provideSearchSegmentsActorRef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, SearchSegmentsActor.name) 

@Provides 
@Named(CollectionsFinderActor.name) 
def provideCollectionsFinderActorRef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, CollectionsFinderActor.name) 

} 

У меня есть службы HTTP актер, который получает инъекции других актеров и перенаправляет письма этих актеров:

object HttpServiceActor extends NamedActor { 
    override final val name: String = "HttpServiceActor" 
} 

class HttpServiceActor @Inject()(@Named(SearchSegmentsActor.name) searchSegmentsActor: ActorRef, 
          @Named(CollectionsFinderActor.name) collectionsFinderActor: ActorRef, 
          @Named(GenesActor.name) genesActor: ActorRef) 
           extends Actor with SearchHttpService with ActorLogging { 

       def actorRefFactory = context 

       def receive = runRoute(
         sprayRoute(searchSegmentsActor, collectionsFinderActor, genesActor) ~ 
         staticRoute) 

     } 

и мне нужно отправить периодически сообщения одному из этих инъецированных акторов, поэтому мой основной метод выглядит следующим образом:

val injector = Guice.createInjector(
    new ConfigModule(), 
    new AkkaModule(), 
    new DaoModule(), 
    new ActorsModule() 
) 

implicit val system = injector.getInstance(classOf[ActorSystem]) 

val service = system.actorOf(GuiceAkkaExtension(system).props(HttpServiceActor.name)) 
val collectionsActor = system.actorOf(GuiceAkkaExtension(system).props(CollectionsFinderActor.name)) 
system.scheduler.schedule(0 seconds, 1 minutes, collectionsActor, new RefreshCollections()) 

IO(Http) ! Http.Bind(service, system.settings.config.getString("app.interface"), system.settings.config.getInt("app.port")) 

На самом деле я вижу, что у меня есть 2 экземпляра CollectionsFinderActor - каждый получает запланированные сообщения каждые 1 минуту, а второй получает сообщения, перенаправленные HttpServiceActor

Конечно, это не то, что я ожидаю. Я хочу, чтобы тот же экземпляр CollectionsFinderActor получил как Сообщения.

Что я делаю неправильно?

ответ

0

Я исправил проблему путем добавления @Singleton аннотации к методу provideGenesActorRef

@Provides 
@Named(GenesActor.name) 
def provideGenesActorRef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, GenesActor.name) 
2

Краткая догадка. Если я помню, guice по умолчанию создает новый экземпляр сервиса каждый раз, когда вы его просите. По крайней мере, он не обещает повторно использовать их.

Вам придётся ввести систему актеров и искать референт актера каждый раз, когда вам это нужно. Небольшое улучшение может заключаться в добавлении сервиса, который бы обернул актерскую систему и общался с актерами. Затем вводит эту новую услугу вместо актеров и т.д.

Вот так описывается авторами framework:

+0

Они пишут, что вы должны не создавайте актеров, чтобы позволить Akka воссоздать их –

+0

Вы можете посмотреть Play docs. Они рассказали о том, как интегрировать akka guice и играть, может быть, вы найдете какую-то идею повторно использовать в своем проекте https://www.playframework.com/documentation/2.5.x/ScalaAkka – michaJlS

+0

@PavelBernshtam Я исправил свой ответ. – michaJlS

Смежные вопросы