2016-06-23 12 views
1

Manchmal schlagen Anforderungen fehl, und wenn es nicht aufgrund eines Clientfehlers (z. B. nicht 4xx) ist, möchte ich versuchen, dieselbe Anfrage zu senden.
Alle meine Anfragen haben eine Anfrage ID-Header, und wenn ich eine bestimmte Anfrage erneut senden (wiederholen) muss ich die gleiche ID wie die an erster Stelle senden.Identifizieren von Nachrüstungsanforderungen 2

Das hört sich nach einer einfachen Sache an, aber es erweist sich mit Retrofit 2 als ziemlich schwierig, außer natürlich, dass mir etwas fehlt.

Alle meine Wünsche sind async, und so in den Rückruf, falls ich brauche ich erneut zu versuchen mache das:

public void onResponse(final Call<T> call, final Response<T> response) { 
    if (response.isSuccessful()) { 
     handleResponse(response); 
    } else if (response.code() >= 400 && response.code() < 500) { 
     handleClientError(response); 
    } else { 
     call.clone().enqueue(this); 
    } 
} 

ich auch einen Abfangjäger haben für Header auf alle Anforderungen ergänzt:

new Interceptor() { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     final Request request = chain.request(); 

     final Request.Builder newRequestBuilder = request.newBuilder() 
       .addHeader("Header1-name", "Header1-value") 
       .addHeader("Header2-name", "Header2-value") 
       ... 
       .addHeader("HeaderN-name", "HeaderN-value"); 

     if (request.header("REQUEST-ID") == null) { 
      newRequestBuilder.addHeader("REQUEST-ID", UUID.randomUUID().toString()); 
     } 

     return chain.proceed(newRequestBuilder.build()); 
    } 
}; 

ich dachte, da ich die Call Klonen werde dann die (Retry) Anfrage werden die Header der vorherigen, aber das ist nicht der Fall ist (wahrscheinlich, weil die Call kloniert und nicht die Request).

Mein Problem ist, dass ich keine Möglichkeit habe, die Anfrage zu identifizieren oder in meinem Interceptor.intercept anzurufen, so dass ich keine Karte von Anfrage/Anrufe an ID pflegen kann.
Es gibt auch keine Möglichkeit, den Calls/Requests Informationen hinzuzufügen (da sie nicht von mir generiert werden und für einen solchen Fall fehlen und Setter).

Ich dachte, dass ich vielleicht die Request.tag Methode verwenden kann, aber wieder habe ich keine Kontrolle über die Objektinstanz, die dort zugewiesen ist und die Objekte sind zwischen den Anforderungen unterschiedlich.
Und wenn wir schon zu diesem Thema sind, was ist dieses Tag überhaupt? Ich kann keine Dokumentation darüber finden.

Irgendeine Idee, wie ich das irgendwie abziehen kann? Dank

+0

hey hast du herausgefunden, was dieses Tag-Objekt auf der Anfrage ist –

+0

@AmanSatija Nein, aber ich habe nicht mehr in diese nach der Lösung in meiner Antwort. –

Antwort

0

nahm ich einen anderen Ansatz dazu, stattdessen Netzwerk Abfangjäger und Rückrufe zu verwenden, ich eine Lösung geschrieben, die ein Netzwerk Abfangjäger verwendet:

class BackoffRetryInteceptor implements Interceptor { 
    private static final long RETRY_INITIAL_DELAY = 500; 
    private static final long RETRY_MAX_DELAY = 35000; 

    @Override 
    public Response intercept(final Chain chain) throws IOException { 
     Request request = chain.request(); 

     final Headers.Builder headersBuilder = new Headers.Builder(); 
     addHeaders(headersBuilder); 

     final Headers headers = headersBuilder.build(); 
     long delay = RETRY_INITIAL_DELAY; 
     Response response = null; 
     IOException exception = null; 

     while (delay < RETRY_MAX_DELAY) { 
      exception = null; 
      request = request.newBuilder().headers(headers).build(); 

      try { 
       response = chain.proceed(request); 

       if (response.isSuccessful() || response.code() != 500) { 
        return response; 
       } 
      } catch (IOException e) { 
       exception = e; 
      } 

      try { 
       Thread.sleep(delay); 
       delay *= 2; 
      } catch (InterruptedException e) { 
       delay = RETRY_MAX_DELAY; 
      } 
     } 

     if (exception != null) { 
      throw exception; 
     } 

     return response; 
    } 

    private static void addHeaders(final Headers.Builder headers) { 
     headers.add("Header1-name", "Header1-value") 
       .add("Header2-name", "Header2-value") 
       ... 
       .add("HeaderN-name", "HeaderN-value") 
       .add("Request-Id", UUID.randomUUID().toString()); 
    } 
} 

Dies scheint in meinen Tests gut zu funktionieren.
Das Hauptproblem ist jedoch das Blockieren der Netzwerk-Threads.

Wenn sich jemand eine bessere Lösung ausdenken kann, würde ich es gerne hören.

Verwandte Themen