尝试利用Akka未来并在我的Play2应用程序中玩承诺

时间:2013-01-03 10:01:56

标签: java playframework-2.0 akka actor promise

在阅读play2文档时,我发现了这个:

  

由于Play 2.0的工作方式,动作代码必须尽可能快   可能的(即非阻塞)。那么如果我们应该如何回归呢?   还不能计算吗?回应应该是a的承诺   导致!

哇!这当然让我对playakkaakka感兴趣。 我目前正在构建一个与elasticsearch集成的自动完成应用程序, 所以这将是一个完美的契合!

控制器:

public class AutoComplete extends Controller {

    @BodyParser.Of(value = BodyParser.Json.class)
    public static Result complete(final String term) {

        F.Promise<List<String>> list = Akka.future(new Callable<List<String>>() {
            public List<String> call() throws Exception {
                List<String> list = IndexService.find(term);
                return list;
            }
        });    

        return async(list.map(new F.Function<List<String>, Result>() {
            @Override
            public Result apply(List<String> list) throws Throwable {
                return ok(Json.toJson(list));
            }
        }));
}

服务

public static List<String> find(final String term) {

        IndexQuery < SearchWord > query = SearchWord.find.query();
        query.setQuery("{\n" +
                "    \"bool\": {\n" +
                "        \"should\": [\n" +
                "            {\n" +
                "                \"text\": {\n" +
                "                    \"search_word.ngrams\": {\n" +
                "                        \"operator\": \"and\",\n" +
                "                        \"query\": \""+term+"\"\n" +
                "                    }\n" +
                "                }\n" +
                "            },\n" +
                "            {\n" +
                "                \"text\": {\n" +
                "                    \"search_word.full\": {\n" +
                "                        \"boost\": 1,\n" +
                "                        \"query\": \""+term+"\"\n" +
                "                    }\n" +
                "                }\n" +
                "            }\n" +
                "        ]\n" +
                "    }\n" +
                "}");
        IndexResults<SearchWord> indexResults = SearchWord.find.search(query);

        List<String> list = new ArrayList<String>();
        for(SearchWord word : indexResults.getResults()){
            list.add(word.getWord());
        }

        return list;
    }
}

搜索内容:

@IndexType(name = "search_word")
public class SearchWord extends Index {

    // Find method static for request
    public static Index.Finder<SearchWord> find = new Index.Finder<SearchWord>(SearchWord.class);

    public enum WordType {
        NAME,
        STRONG_SEARCH_WORD,
        WEAK_SEARCH_WORD,
        BANNED
    }

    private String word;
    private WordType wordType;

    public SearchWord() {
    }

    public SearchWord(IndexWord indexWord) {
        super.id = ""+indexWord.getId();
        this.word = StringUtils.lowerCase(indexWord.getWord());
        this.wordType = WordType.valueOf(indexWord.getType());
    }

    public String getId() {
        return super.id;
    }

    public void setId(String id) {
        super.id = id;
    }

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }

    public WordType getWordType() {
        return wordType;
    }

    public void setWordType(WordType wordType) {
        this.wordType = wordType;
    }

    @Override
    public Map toIndex() {
        HashMap map = new HashMap();
        map.put("id", super.id);
        map.put("word", word);
        map.put("word_type", wordType.toString());
        return map;
    }

    @Override
    public Indexable fromIndex(Map map) {
        if (map == null) {
            return this;
        }
        this.word = (String) map.get("word");
        this.wordType = WordType.valueOf((String)map.get("word_type"));
        return this;
    }


}

代码运行良好,但我必须说我不确定我是否正确实现了这一点。我真的很难理解文档。 所以我的问题基本上是:

  1. 我是否正确实施了未来和承诺?
  2. 创建自定义actor会更好吗,并在该actor中执行索引 搜索,就像文档中的示例:
  3. =====

     return async(
            Akka.asPromise(ask(myActor,"hello", 1000)).map(
              new Function<Object,Result>() {
                public Result apply(Object response) {
                  return ok(response.toString());
                }
              }
            )
          );
    
    1. 也许你有一些我还没有找到的好例子?

2 个答案:

答案 0 :(得分:2)

AFAIK,你的代码完全可以。

我可能错了,但我认为第二个选项与第一个选项完全相同,因为Akka.future()方法是Akka.promise()方法的包装。

来自Akka class source code of Play 2.0.4

/**
 * Executes a block of code asynchronously in the application Akka Actor system.
 */
public static <T> Promise<T> future(java.util.concurrent.Callable<T> callable) {
    return asPromise(akka.dispatch.Futures.future(callable, system().dispatcher()));
}

答案 1 :(得分:0)

虽然你已经正确实现了Promise和Future,但我不认为这段代码是“非阻塞的”......

似乎阻止呼叫是

List<String> list = IndexService.find(term);

虽然现在已经包含在一个承诺/未来中,但它仍然是一个封锁电话...... 如果你想要真正的非阻塞(具有所有好处),你必须使你的数据访问(查询)无阻塞......

哦,非阻塞动作方法应该返回结果的承诺,而不是结果......

这就是我应该编写代码的方式:

@BodyParser.Of(value = BodyParser.Json.class)
public static F.Promise<Result> complete(final String term) {    
    scala.concurrent.Future<List<String>> listFuture = IndexService.find(term);

    F.Promise<List<String>> listPromise = F.Promise.wrap(listFuture);

    return listPromise.map(new F.Function<List<String>, Result>() {
       @Override
       public Result apply(List<String> list) throws Throwable {
          return ok(Json.toJson(list));
       }
    });
}

希望这有帮助!