Search code examples
scalaakkaguicespray

Different Akka Actor instances receive messages


I created dependency injection with Guice in Spray project as described in this tutorial.

My Guice module:

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)

}

I have http service actor, which gets by injections other actors and forwards messages to those actors:

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)

       }

and I need to send periodically messages to one of this injected actors, so my main method looks like:

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"))

Actually I see that I have 2 instances of CollectionsFinderActor - one receives scheduled messages every 1 minute and the second receives messages forwarded by HttpServiceActor

Of course this is not what I expect - I want that the same instance of CollectionsFinderActor will receive both messages.

What I'm doing wrong?


Solution

  • I fixed the problem by adding @Singleton annotation to provideGenesActorRef method

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