2016-09-20 4 views
2

私のツールでは、ほとんどの処理にRX javaを使用しています。基本的に私が働いているツールのアイデアは、次のとおりです。複雑な処理フローで排出量をグループ化またはキャッシュする方法は?

  • は、いくつかの特定のルールを使用して断片に分割し、いくつかのソースからのペイロード(例えばHTMLファイル)を取得します。
  • 各フラグメントは、非同期HTTPコール(なされるべき1つまたは複数のこのようなコールであることができる)
  • 各フラグメントデータを使用し、その後全く同じHTTPコール(エンドポイント)
  • を使用する可能性を介してフェッチされるいくつかの追加データを必要とするかもしれませんhttpエンドポイントから返されたフラグメントで何かを行う
  • 処理されたすべてのフラグメントをペイロードに結合して処理済みのペイロードと呼びましょう 基本的に、私がすでに実装したフローは基本的には基本的にアイディア。 、私はいくつかのを改善する方法を考えている今

    Observable.just("SOME_PAYLOAD_AS_STRING") 
         .flatMap(payload -> splitToFragmentObservables(payload)) //Getting observables of fragments 
         .concatMapEager(//concat all processed fragments 
           fragment -> getServiceCallsObservable(fragment) //get service calls for all fragments 
              .flatMap(this::doServiceCall) // do service call 
              .reduce(new HashMap<>(), (all, result) -> { //reduce results into map 
               all.addAll(result); 
               return all; 
              }) 
             .map(all -> newFragmentWithData(fragment, all)) //apply somehow the all service results to my fragment 
         ) 
         .reduce(new StringBuilder(), StringBuilder::append) //reduce all fragments back to string 
         .map(StringBuilder::toString); 
    

    :処理の擬似コードは次のようになりますので、図は、読み取り可能かどう

Processing flow

わかりません処理、特にHTTPコールを処理します。ダイアグラムで気づいたように、各フラグメントはまったく同じコール(A、BまたはC)を実行でき、これは不必要なオーバーヘッドです。

私は、各フラグメントで同じサービスコールを行うことを避ける方法を探しています。それを改善する最善の方法は何ですか?同じ電話をグループ化し、電話をかけて、最終結果を行うときに何とかそれを使用しますか?代わりにキャッシュするか?

答えて

1

Observableによって生成された結果をキャッシュし、すべてのサブスクライバに同じ結果を与える方法があります。

  1. 使用cacheオペレータ:

    次の2つの選択肢があります。しかし、キャッシュの無効化を実装する必要があります。

  2. replaypublish演算子を使用して、より洗練されたソリューションを使用します。しかし@JakeWhartonは既にあなたに代わってthe solutionというこのような問題に対処しています。 Hereは、この単純なライブラリの説明です。

エクストラ: Hereは、Observableと同じ値を出力する問題のもう1つの解決策です。

希望、私は問題を理解し、適切な答えを与えました。

0

チャールズプロキシ(または同様のもの)を使用して、実際に何が行われているかを確認します。

キャッシング付きの優れたHttpライブラリを使用している場合は、コードが既に完璧である可能性があります。途中で最適化しないでください!

エンドポイントが持つキャッシング・ルール(および変更可能かどうか)によっては、同じエンドポイントへの連続コールでキャッシュ結果を使用できる場合があります。これらのエンドポイントを制御できる場合は、lenientキャッシングヘッダーを設定します。

getServiceCallsObservableにキャッシュを追加すると、おそらくもっと面倒な解決策になります。また、getServiceCallsObservableが別のワーカースレッドから呼び出されるため、スレッドセーフである必要があります。 (少なくとも、いくつかの方法の実装とスケジューリングの詳細に応じて、追加のスケジューリングを追加する必要があります)

0

ヒントをお願いします。実際には、私はグーバのキャッシュを使用して探していた私はまた、cacheオペレータを使用してエレガントなソリューションを発見した。

.flatMap(this::doServiceCall) 

観察可能なサービス結果へのマッピングである

単にflatMapオペレータ私は与えられたキー

.flatMap(service -> cache.get(service.getUrl(),() -> doServiceCall(service.getUrl()).cache())) 

に値が入手できたとき、私はそう実行のコールバックを持つメソッドを取得しグアバキャッシュを使用するように変更単にサービスコールからキャッシュされた観測可能なものをキャッシングするだけです。キャッシュは処理中の新しいペイロードごとに再初期化されています。要求のためだけのキャッシュ・リビングです。

関連する問題