2013-01-03 9 views
8

Kiedy czyta się o dokumentację PLAY2 Znalazłem to:Próbując wykorzystać Akka przyszłych i zabaw obietnic w mojej aplikacji PLAY2

Ze względu na sposób Zagraj 2.0 dzieła, kod działania muszą być jak najszybciej możliwe (tj. bez blokowania). Co więc powinniśmy zwrócić w wyniku, jeśli nie będziemy w stanie go jeszcze obliczyć? Odpowiedź powinna być obietnicą rezultatu: !

Wow! To oczywiście sprawiło, że zainteresowałem się playakka i akka. Aktualnie buduję aplikację do autouzupełniania, która integruje się z elastycznym wyszukiwaniem, , więc byłoby to idealne dopasowanie!

Kontroler:

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

Usługa:

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


} 

Kod działa bardzo dobrze, ale muszę powiedzieć, że nie jestem pewien, czy poprawnie to zaimplementowałem. Naprawdę staram się zrozumieć dokumentację. Moje pytania są w zasadzie następujące:

  1. Czy poprawnie wdrożyłem Przyszłość i obietnicę?
  2. Byłoby lepiej, aby utworzyć niestandardową aktora, w tym aktor przeprowadzić przeszukiwanie indeksu , jak przykładowo w docs:

=====

return async(
     Akka.asPromise(ask(myActor,"hello", 1000)).map(
      new Function<Object,Result>() { 
      public Result apply(Object response) { 
       return ok(response.toString()); 
      } 
      } 
     ) 
    ); 
  1. Może masz jakiś świetny przykład, którego jeszcze nie znalazłem?
+0

Mam tylko pytania: (a) jaka jest zaleta asynchronicznego kodu w przypadku autouzupełniania? (b) czy jakakolwiek znacząca aktywność procesora zostanie zablokowana w przypadku braku asynchronicznego kodu? i (c) czy podejmujecie środki przeciwko złożeniu obietnic w złej kolejności? –

Odpowiedz

2

AFAIK, Twój kod jest całkowicie OK.

Mogę się mylić, ale myślę, że druga opcja jest ściśle równoważna z pierwszą, ponieważ metoda Akka.future() jest opakowaniem wokół metody Akka.promise().

Z 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

Chociaż zostały prawidłowo wdrożone Promise i przyszłości, nie uważam tego kodu, aby być "non-blocking" ...

Wydaje się, że blokowanie połączeń jest

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

i choć jest to teraz owinięte w/obietnica przyszłości, to jest wciąż blokowania połączeń ... Jeśli chcesz b Naprawdę bez blokowania (z wszystkimi jego zaletami), musisz uniemożliwić blokowanie dostępu do danych (zapytań) ...

Aha, i non-blocking metody działania powinny powrócić obietnica rezultacie nie Rezultat ...

ten sposób powinienem napisać swój kod:

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

nadzieję, że to pomaga !

+0

Ups, tylko zauważyłem, że zostało to zadane ponad rok temu ... myślałem, że to tylko 5 dni ;-) – stikkos