Обработка операций блокировки в Play 2.1

Я пытаюсь создать способ обработки блокирующих операций определенным образом в Play. Сначала я описал, за какой моей целью следует то, что мне удалось сделать до сих пор. Не могли бы вы сказать мне, если я на правильном пути - если да, не могли бы вы помочь мне понять, как завершить код? Если это не правильный способ сделать это, не могли бы вы предложить лучшую альтернативу? Большое спасибо за вашу помощь

Цель: Хотелось бы, чтобы все операции блокировки отправлялись одному потоку в отдельный поток для асинхронной обработки. Новые поступающие запросы не должны занимать больше потоков, а вместо этого помещают их в очередь (или что-то подобное) для обработки одним потоком. Для каждого элемента, который обрабатывается дополнительным потоком асинхронно, некоторый текст должен быть собран и возвращен в браузер.

Таким образом, после прочтения документов и ТАКИХ вопросов, кажется, что актеры должны быть использованы. Мне нравится концепция актеров, но я никогда не использовал их раньше, поэтому все еще учусь. Вот что у меня есть:

    package models;

    import java.io.*;
    import play.mvc.*;
    import play.libs.*;
    import play.libs.F.*;
    import akka.actor.*;

    public class ActorTest extends UntypedActor {
        static BufferedReader reader = new BufferedReader(new InputStreamReader(
                System.in));

        @Override
        public void onReceive(Object message) throws Exception {
            if (message instanceof String) {
                getSender().tell(
                        "You sent me " + ((String) message)
                                + " and the consol replied with "
                                + reader.readLine(), getSelf());
            } else
                unhandled(message);
        }

    }

Как видите, операция блокировки - readLine() - просто способ тестирования.

Это как это сделать? Если так, то я предположил, что из контроллера я каким-то образом создаю асинхронный результат или что-то с помощью обещаний. Обработка асинхронных результатов.

Пара вопросов, как мне отправить сообщение актеру и получить ответ? Я имею в виду, могу ли я получить результат от вызова tel()? Как я могу убедиться, что больше потоков не будет занято и что все операции будут помещены в очередь - или это уже обрабатывается субъектом?

Не могли бы вы предоставить пример действия контроллера, который мог бы сделать это?

Ваша помощь очень ценится.

PS К вашему сведению, я действительно новичок во всем этом, поэтому просто для того, чтобы добраться до этой стадии, я нашел эти документы полезными для чтения - страницы актеров Akka, игры и, конечно, некоторые вики-страницы об актерах.

[править] Извините, я сказал, что один поток, но это может быть пул потоков - до тех пор, пока только один назначенный поток / пул потоков используется для блокировки, в отличие от других.

1 ответ

Решение

Вы можете отправить сообщение актеру Akka, используя ask (вместо Tell). Он вернет вам будущее, которое затем вы можете отобразить на Promise<Result>,

Тем не менее, вам не нужно использовать Akka, если вам не нужно. Вы можете просто использовать Futures / Promises для запуска операции блокировки в фоновом режиме.

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

Пример использования Promise в Play 2.2.x

...
import play.libs.F.*;

public static Promise<Result> index() {
  Promise<Integer> promiseOfInt = Promise.promise(
      new Function0<Integer>() {
        public Integer apply() {
          // long-running operation (will run in separate thread)
          return 42;
        }
      });

  return promiseOfInt.map(
      new Function<Integer, Result>() {
        public Result apply(Integer i) {
          // 'i' is the result after Promise is complete
          return ok("Got result: " + i);
        }
      });
}

Если вы используете Akka, вам нужно конвертировать Future вернулся из ask играть Promise следующее:

public static Promise<Result> index() {
    ActorRef myActor = Akka.system().actorFor("user/my-actor");

    return Promise.wrap(ask(myActor, "hello", 1000)).map(
        new Function<Object, Result>() {
            public Result apply(Object response) {
                return ok(response.toString());
            }
        });
}

Пример использования Promise в Play 2.1.x

...
import play.libs.F.*;

public static Result index() {
  Promise<Integer> promiseOfInt = play.libs.Akka.future(
      new Callable<Integer>() {
        public Integer call() {
          // long-running operation (will run in separate thread)
          return 42;
        }
      });
  return async(
      promiseOfInt.map(
        new Function<Integer,Result>() {
          public Result apply(Integer i) {
            // 'i' is the result after Promise is complete
            return ok("Got result: " + i);
          }
        }));
}

Если вы используете Akka, вам нужно конвертировать Future вернулся из ask играть Promise следующее:

public static Result index() {
  ActorRef myActor = Akka.system().actorFor("user/my-actor");

  return async(
    Akka.asPromise(ask(myActor,"hello", 1000)).map(
      new Function<Object,Result>() {
        public Result apply(Object response) {
          return ok(response.toString());
        }
      }
    )
  );
}
Другие вопросы по тегам