Exemple #1
0
  /**
   * Sends a request message to an actor, awaits a response value (but no longer than the given
   * timeout) and returns it. This method can be called by any code, even non-actor code. If the
   * actor responds with an error message, a {@link RuntimeException} will be thrown by this method.
   * <br>
   * The message's {@code id} and {@code from} properties may be left unset.
   *
   * <p>This method should be used as in the following example (assuming a {@code String} return
   * value:
   *
   * <pre>{@code
   * String res = call(actor, new MyRequest());
   * }</pre>
   *
   * In the example, {@code MyRequest} extends {@link RequestMessage}. Note how the result of the
   * {@link #from() from} method is passed to the request's constructor, but the message ID isn't.
   *
   * @param <V> the return value's type
   * @param actor the actor to which the request is sent
   * @param timeout the maximum duration to wait for a response
   * @param unit the time unit of the timeout
   * @return the value sent by the actor as a response
   * @throws RuntimeException if the actor responds with an error message, its contained exception
   *     will be thrown, possibly wrapped by a {@link RuntimeException}.
   * @throws TimeoutException if the timeout expires before a response is received from the actor.
   * @throws InterruptedException
   */
  public static <V> V call(final ActorRef actor, RequestMessage<V> m, long timeout, TimeUnit unit)
      throws TimeoutException, InterruptedException, SuspendExecution {
    assert !actor.equals(LocalActor.self()) : "Can't \"call\" self - deadlock guaranteed";

    if (m.getFrom() == null) m.setFrom(from());

    final Actor currentActor;
    if (m.getFrom() instanceof TempActor) currentActor = ((TempActor<?>) m.getFrom()).actor.get();
    else currentActor = Actor.currentActor();

    assert currentActor != null;

    final Object watch = currentActor.watch(actor);

    if (m.getId() == null) m.setId(watch);

    final Object id = m.getId();

    final SelectiveReceiveHelper<Object> helper =
        new SelectiveReceiveHelper<Object>(currentActor) {
          @Override
          protected void handleLifecycleMessage(LifecycleMessage m) {
            if (m instanceof ExitMessage) {
              final ExitMessage exit = (ExitMessage) m;
              if (Objects.equals(exit.getActor(), actor) && exit.getWatch() == watch)
                throw Exceptions.rethrow(exit.getCause());
            }
            super.handleLifecycleMessage(m);
          }
        };
    try {
      actor.sendSync(m);
      final ResponseMessage response =
          (ResponseMessage)
              helper.receive(
                  timeout,
                  unit,
                  new MessageProcessor<Object, Object>() {
                    @Override
                    public Object process(Object m) throws SuspendExecution, InterruptedException {
                      return (m instanceof ResponseMessage
                              && id.equals(((ResponseMessage) m).getId()))
                          ? m
                          : null;
                    }
                  });
      currentActor.unwatch(
          actor,
          watch); // no need to unwatch in case of receiver death, so not doen in finally block

      if (response instanceof ErrorResponseMessage)
        throw Exceptions.rethrow(((ErrorResponseMessage) response).getError());
      return ((ValueResponseMessage<V>) response).getValue();
    } finally {
      if (m.getFrom() instanceof TempActor) ((TempActor) m.getFrom()).done();
    }
  }
 @SuppressWarnings("unchecked")
 private Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>>
     autoCreateActor(FullHttpRequest req) {
   registerActorClasses();
   final String uri = req.getUri();
   for (final Class<?> c : actorClasses) {
     if (WebActorHandler.handlesWithHttp(uri, c) || WebActorHandler.handlesWithWebSocket(uri, c))
       return new Pair<
           ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>>(
           Actor.newActor(
                   new ActorSpec(
                       c, actorParams != null ? actorParams.get(c) : EMPTY_OBJECT_ARRAY))
               .spawn(),
           (Class<? extends ActorImpl<? extends WebMessage>>) c);
   }
   return null;
 }