2013-01-03 24 views
8

Khi đọc lên trên các tài liệu play2 Tôi thấy điều này:Cố gắng tận dụng Akka tương lai và chơi hứa hẹn trong ứng dụng Play2 tôi

Do cách chơi công trình 2.0, mã hành động phải được nhanh như có thể (tức là không chặn). Vậy chúng ta nên trả lại kết quả gì nếu chúng ta chưa thể tính toán được? Câu trả lời phải là lời hứa của kết quả !

Wow! Điều này tất nhiên đã khiến tôi quan tâm đến playakkaakka. Tôi hiện đang xây dựng một ứng dụng tự động hoàn tất được tích hợp với elasticsearch, vì vậy điều này sẽ hoàn toàn phù hợp!

Bộ điều khiển:

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)); 
      } 
     })); 
} 

dịch vụ:

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; 
    } 
} 

SearchWord:

@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; 
    } 


} 

Mã này hoạt động rất nhưng tôi phải nói rằng tôi không chắc chắn rằng tôi đã thực hiện điều này một cách chính xác. Tôi thực sự đấu tranh để hiểu tài liệu. Vì vậy, câu hỏi của tôi về cơ bản là:

  1. Tôi đã triển khai tương lai và hứa hẹn chính xác chưa?
  2. Nó sẽ được tốt hơn để tạo ra một diễn viên tùy chỉnh, và trong nam diễn viên đó thực hiện tìm kiếm index , giống như ví dụ trong tài liệu:

=====

return async(
     Akka.asPromise(ask(myActor,"hello", 1000)).map(
      new Function<Object,Result>() { 
      public Result apply(Object response) { 
       return ok(response.toString()); 
      } 
      } 
     ) 
    ); 
  1. Có thể bạn có một số ví dụ tuyệt vời mà tôi chưa tìm thấy?
+0

Câu hỏi duy nhất tôi có là (a) lợi thế của mã không đồng bộ trong trường hợp tự động hoàn thành là gì? (b) bất kỳ hoạt động xử lý đáng kể nào bị chặn trong trường hợp không có mã không đồng bộ? và (c) bạn có biện pháp chống lại các lời hứa được giải quyết theo thứ tự sai? –

Trả lời

2

AFAIK, mã của bạn hoàn toàn ổn.

Tôi có thể sai, nhưng tôi nghĩ rằng tùy chọn thứ hai là đúng tương đương với một đầu tiên, kể từ khi phương pháp Akka.future() là một wrapper quanh phương pháp Akka.promise().

Từ 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())); 
} 
0

Mặc dù bạn đã thực hiện đúng lời hứa và trong tương lai, tôi sẽ không xem xét mã này là "non-blocking" ...

Dường như chặn cuộc gọi là

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

và mặc dù điều này bây giờ được gói trong một lời hứa/trong tương lai, nó vẫn là một cuộc gọi chặn ... Nếu bạn muốn b e thực sự không chặn (với tất cả các lợi ích của nó), bạn sẽ phải làm cho truy cập dữ liệu của bạn (truy vấn) không chặn ...

Oh, và non-blocking phương pháp hành động phải trả lại một Lời hứa của một quả, không phải là một kết quả ...

Đây là cách tôi nên viết mã của bạn:

@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)); 
     } 
    }); 
} 

Hope this helps !

+0

Rất tiếc, chỉ nhận thấy điều này đã được hỏi hơn một năm trước ... nghĩ rằng đó chỉ là 5 ngày tuổi ;-) – stikkos

Các vấn đề liên quan