Http multithreaded connections with retry and session update
$begingroup$
I have the task to make a multithreaded http method. This method is my entry point (As mine is a library) for a bigger project which is a library. So the flow is like this
ProjectA ---> My Entry point Lib ----> HttpLibrary
The main features of this method are:
- Accept Multiple Requests
- Check for Http Status codes and act appropriately
- If session fails, try updating session once and retry main API call
Here is what I have come up with so far
private JsonHttpResult execJsonHttpMethod(final int requestId, BaseRequest request, int maxRequestCount) throws BaseApiException, NullPointerException {
if (maxRequestCount <= 0) {
maxRequestCount = REQUESTS_ATTEMPTS_COUNT;
}
int timeToWaitBeforeNextRequestIncaseError = 500;
HttpRetryManager httpRetryManager = new HttpRetryManager(maxRequestCount, timeToWaitBeforeNextRequestIncaseError); // Instance created for each thread
int count = 0; // Only for logging purpose - thread safe | thread local variable
JsonHttpResult result = null;
while (httpRetryManager.canRetry()) {
count++;
try {
reloginLock.readLock().lock();
final HttpMethod httpMethod = compileHttpMethod(request);
printRequestLog(request, "execJsonHttpMethod[request]: requestId=" + requestId + ", count=" + count + ", url=" + httpMethod.getURI(), false);
result = mTransportProvider.execJsonHttpMethod(httpMethod);
boolean isResEmpty = errorIfResponseEmpty(result);
if (isResEmpty) {
try {
httpRetryManager.onErrorUpdateCountAndSleep(new HttpStatusException(result.getHttpStatus(), "Unexpected empty response body"));
} catch (HttpStatusException responseEmpty) {
responseEmpty.printStackTrace();
throw responseEmpty;
}
}
boolean isSessionInvalid = errorIfResponseUnAuthorized(result);
if (isSessionInvalid) {
if (updateSessionIncaseApiGot401()) {
try {
//In-case session does not update, logout the user by escalating 401 to 403 ( InvalidSessionException() ---> InvalidUserException())
httpRetryManager.onErrorUpdateCountAndSleep(new InvalidUserException());
continue; //Start next iteration - no need to check for the rest of the conditions
} catch (InvalidUserException exceptionSessEsclatedToInvalidUser) {
exceptionSessEsclatedToInvalidUser.printStackTrace();
throw exceptionSessEsclatedToInvalidUser;
}
} else {
throw new InvalidUserException(); // WILL TRY ONLY ONCE - IF UPDATE FAILS LOGOUT - 403
}
}
//Logout user incase API threw 403 - Pops up the stack, no retry action required
if (errorIfResponseForbidden(result)) {
throw new InvalidUserException();
}
boolean isHttpErrCodeNotOk = errorIfHttpStatusNotOk(result);
if (!isHttpErrCodeNotOk) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED
&& result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
throw new HttpStatusDetailedException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString(), result.httpError);
} else {
throw new HttpStatusException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString());
}
}
}
//Success
HttpUUIDController.getInstance().handleSuccessRequest(request);
break;
} catch (TransportLevelException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, requestId=" + requestId + ", count=" + count + ", ex=" + ex, false);
try {
httpRetryManager.onErrorUpdateCountAndSleep(ex);
} catch (Exception transportException) {
transportException.printStackTrace();
throw transportException;
}
} catch (URIException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, ex=" + ex.getMessage(), false);
throw new InvalidUrlException();
} finally {
printRequestLog(request, "execJsonHttpMethod[result]: finished, requestId=" + requestId + ", count=" + count + ", result=" + result, false);
reloginLock.readLock().unlock();
}
}
simpleLog("Loop has been exited, Iterations: " + count);
return result;
}
These are my helper methods:
private boolean errorIfResponseEmpty(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_OK && result.getHttpResponse() == null) {
printResponseLog(result.getHttpStatus() + " Unexpected empty response body", true);
return true;
}
return false;
}
private boolean errorIfResponseUnAuthorized(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_UNAUTHORIZED) {
printResponseLog(result.getHttpStatus() + " Session Failed", true);
return true;
}
return false;
}
private boolean errorIfHttpStatusNotOk(HttpResult result) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED && result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString() + " " + result.httpError, true);
} else {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString(), true);
}
return false;
}
return true;
}
private boolean errorIfResponseForbidden(HttpResult result) {
return (result.getHttpStatus() == HttpStatus.SC_FORBIDDEN);
}
And finally my HttpRetryManager:
private int leftRetries;
private long timeToWait;
public HttpRetryManager(int retries, long timeToWait) {
this.timeToWait = timeToWait;
leftRetries = retries;
}
public boolean canRetry() {
return leftRetries > 0;
}
public void onErrorUpdateCountAndSleep(BaseApiException ex) throws BaseApiException {
leftRetries--;
if (!canRetry()) {
throw ex;
}
waitUntilNextTry();
}
private long getTimeToWait() {
return timeToWait;
}
private void waitUntilNextTry() {
try {
Thread.sleep(getTimeToWait());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java multithreading error-handling api
$endgroup$
add a comment |
$begingroup$
I have the task to make a multithreaded http method. This method is my entry point (As mine is a library) for a bigger project which is a library. So the flow is like this
ProjectA ---> My Entry point Lib ----> HttpLibrary
The main features of this method are:
- Accept Multiple Requests
- Check for Http Status codes and act appropriately
- If session fails, try updating session once and retry main API call
Here is what I have come up with so far
private JsonHttpResult execJsonHttpMethod(final int requestId, BaseRequest request, int maxRequestCount) throws BaseApiException, NullPointerException {
if (maxRequestCount <= 0) {
maxRequestCount = REQUESTS_ATTEMPTS_COUNT;
}
int timeToWaitBeforeNextRequestIncaseError = 500;
HttpRetryManager httpRetryManager = new HttpRetryManager(maxRequestCount, timeToWaitBeforeNextRequestIncaseError); // Instance created for each thread
int count = 0; // Only for logging purpose - thread safe | thread local variable
JsonHttpResult result = null;
while (httpRetryManager.canRetry()) {
count++;
try {
reloginLock.readLock().lock();
final HttpMethod httpMethod = compileHttpMethod(request);
printRequestLog(request, "execJsonHttpMethod[request]: requestId=" + requestId + ", count=" + count + ", url=" + httpMethod.getURI(), false);
result = mTransportProvider.execJsonHttpMethod(httpMethod);
boolean isResEmpty = errorIfResponseEmpty(result);
if (isResEmpty) {
try {
httpRetryManager.onErrorUpdateCountAndSleep(new HttpStatusException(result.getHttpStatus(), "Unexpected empty response body"));
} catch (HttpStatusException responseEmpty) {
responseEmpty.printStackTrace();
throw responseEmpty;
}
}
boolean isSessionInvalid = errorIfResponseUnAuthorized(result);
if (isSessionInvalid) {
if (updateSessionIncaseApiGot401()) {
try {
//In-case session does not update, logout the user by escalating 401 to 403 ( InvalidSessionException() ---> InvalidUserException())
httpRetryManager.onErrorUpdateCountAndSleep(new InvalidUserException());
continue; //Start next iteration - no need to check for the rest of the conditions
} catch (InvalidUserException exceptionSessEsclatedToInvalidUser) {
exceptionSessEsclatedToInvalidUser.printStackTrace();
throw exceptionSessEsclatedToInvalidUser;
}
} else {
throw new InvalidUserException(); // WILL TRY ONLY ONCE - IF UPDATE FAILS LOGOUT - 403
}
}
//Logout user incase API threw 403 - Pops up the stack, no retry action required
if (errorIfResponseForbidden(result)) {
throw new InvalidUserException();
}
boolean isHttpErrCodeNotOk = errorIfHttpStatusNotOk(result);
if (!isHttpErrCodeNotOk) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED
&& result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
throw new HttpStatusDetailedException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString(), result.httpError);
} else {
throw new HttpStatusException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString());
}
}
}
//Success
HttpUUIDController.getInstance().handleSuccessRequest(request);
break;
} catch (TransportLevelException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, requestId=" + requestId + ", count=" + count + ", ex=" + ex, false);
try {
httpRetryManager.onErrorUpdateCountAndSleep(ex);
} catch (Exception transportException) {
transportException.printStackTrace();
throw transportException;
}
} catch (URIException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, ex=" + ex.getMessage(), false);
throw new InvalidUrlException();
} finally {
printRequestLog(request, "execJsonHttpMethod[result]: finished, requestId=" + requestId + ", count=" + count + ", result=" + result, false);
reloginLock.readLock().unlock();
}
}
simpleLog("Loop has been exited, Iterations: " + count);
return result;
}
These are my helper methods:
private boolean errorIfResponseEmpty(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_OK && result.getHttpResponse() == null) {
printResponseLog(result.getHttpStatus() + " Unexpected empty response body", true);
return true;
}
return false;
}
private boolean errorIfResponseUnAuthorized(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_UNAUTHORIZED) {
printResponseLog(result.getHttpStatus() + " Session Failed", true);
return true;
}
return false;
}
private boolean errorIfHttpStatusNotOk(HttpResult result) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED && result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString() + " " + result.httpError, true);
} else {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString(), true);
}
return false;
}
return true;
}
private boolean errorIfResponseForbidden(HttpResult result) {
return (result.getHttpStatus() == HttpStatus.SC_FORBIDDEN);
}
And finally my HttpRetryManager:
private int leftRetries;
private long timeToWait;
public HttpRetryManager(int retries, long timeToWait) {
this.timeToWait = timeToWait;
leftRetries = retries;
}
public boolean canRetry() {
return leftRetries > 0;
}
public void onErrorUpdateCountAndSleep(BaseApiException ex) throws BaseApiException {
leftRetries--;
if (!canRetry()) {
throw ex;
}
waitUntilNextTry();
}
private long getTimeToWait() {
return timeToWait;
}
private void waitUntilNextTry() {
try {
Thread.sleep(getTimeToWait());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java multithreading error-handling api
$endgroup$
add a comment |
$begingroup$
I have the task to make a multithreaded http method. This method is my entry point (As mine is a library) for a bigger project which is a library. So the flow is like this
ProjectA ---> My Entry point Lib ----> HttpLibrary
The main features of this method are:
- Accept Multiple Requests
- Check for Http Status codes and act appropriately
- If session fails, try updating session once and retry main API call
Here is what I have come up with so far
private JsonHttpResult execJsonHttpMethod(final int requestId, BaseRequest request, int maxRequestCount) throws BaseApiException, NullPointerException {
if (maxRequestCount <= 0) {
maxRequestCount = REQUESTS_ATTEMPTS_COUNT;
}
int timeToWaitBeforeNextRequestIncaseError = 500;
HttpRetryManager httpRetryManager = new HttpRetryManager(maxRequestCount, timeToWaitBeforeNextRequestIncaseError); // Instance created for each thread
int count = 0; // Only for logging purpose - thread safe | thread local variable
JsonHttpResult result = null;
while (httpRetryManager.canRetry()) {
count++;
try {
reloginLock.readLock().lock();
final HttpMethod httpMethod = compileHttpMethod(request);
printRequestLog(request, "execJsonHttpMethod[request]: requestId=" + requestId + ", count=" + count + ", url=" + httpMethod.getURI(), false);
result = mTransportProvider.execJsonHttpMethod(httpMethod);
boolean isResEmpty = errorIfResponseEmpty(result);
if (isResEmpty) {
try {
httpRetryManager.onErrorUpdateCountAndSleep(new HttpStatusException(result.getHttpStatus(), "Unexpected empty response body"));
} catch (HttpStatusException responseEmpty) {
responseEmpty.printStackTrace();
throw responseEmpty;
}
}
boolean isSessionInvalid = errorIfResponseUnAuthorized(result);
if (isSessionInvalid) {
if (updateSessionIncaseApiGot401()) {
try {
//In-case session does not update, logout the user by escalating 401 to 403 ( InvalidSessionException() ---> InvalidUserException())
httpRetryManager.onErrorUpdateCountAndSleep(new InvalidUserException());
continue; //Start next iteration - no need to check for the rest of the conditions
} catch (InvalidUserException exceptionSessEsclatedToInvalidUser) {
exceptionSessEsclatedToInvalidUser.printStackTrace();
throw exceptionSessEsclatedToInvalidUser;
}
} else {
throw new InvalidUserException(); // WILL TRY ONLY ONCE - IF UPDATE FAILS LOGOUT - 403
}
}
//Logout user incase API threw 403 - Pops up the stack, no retry action required
if (errorIfResponseForbidden(result)) {
throw new InvalidUserException();
}
boolean isHttpErrCodeNotOk = errorIfHttpStatusNotOk(result);
if (!isHttpErrCodeNotOk) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED
&& result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
throw new HttpStatusDetailedException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString(), result.httpError);
} else {
throw new HttpStatusException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString());
}
}
}
//Success
HttpUUIDController.getInstance().handleSuccessRequest(request);
break;
} catch (TransportLevelException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, requestId=" + requestId + ", count=" + count + ", ex=" + ex, false);
try {
httpRetryManager.onErrorUpdateCountAndSleep(ex);
} catch (Exception transportException) {
transportException.printStackTrace();
throw transportException;
}
} catch (URIException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, ex=" + ex.getMessage(), false);
throw new InvalidUrlException();
} finally {
printRequestLog(request, "execJsonHttpMethod[result]: finished, requestId=" + requestId + ", count=" + count + ", result=" + result, false);
reloginLock.readLock().unlock();
}
}
simpleLog("Loop has been exited, Iterations: " + count);
return result;
}
These are my helper methods:
private boolean errorIfResponseEmpty(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_OK && result.getHttpResponse() == null) {
printResponseLog(result.getHttpStatus() + " Unexpected empty response body", true);
return true;
}
return false;
}
private boolean errorIfResponseUnAuthorized(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_UNAUTHORIZED) {
printResponseLog(result.getHttpStatus() + " Session Failed", true);
return true;
}
return false;
}
private boolean errorIfHttpStatusNotOk(HttpResult result) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED && result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString() + " " + result.httpError, true);
} else {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString(), true);
}
return false;
}
return true;
}
private boolean errorIfResponseForbidden(HttpResult result) {
return (result.getHttpStatus() == HttpStatus.SC_FORBIDDEN);
}
And finally my HttpRetryManager:
private int leftRetries;
private long timeToWait;
public HttpRetryManager(int retries, long timeToWait) {
this.timeToWait = timeToWait;
leftRetries = retries;
}
public boolean canRetry() {
return leftRetries > 0;
}
public void onErrorUpdateCountAndSleep(BaseApiException ex) throws BaseApiException {
leftRetries--;
if (!canRetry()) {
throw ex;
}
waitUntilNextTry();
}
private long getTimeToWait() {
return timeToWait;
}
private void waitUntilNextTry() {
try {
Thread.sleep(getTimeToWait());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java multithreading error-handling api
$endgroup$
I have the task to make a multithreaded http method. This method is my entry point (As mine is a library) for a bigger project which is a library. So the flow is like this
ProjectA ---> My Entry point Lib ----> HttpLibrary
The main features of this method are:
- Accept Multiple Requests
- Check for Http Status codes and act appropriately
- If session fails, try updating session once and retry main API call
Here is what I have come up with so far
private JsonHttpResult execJsonHttpMethod(final int requestId, BaseRequest request, int maxRequestCount) throws BaseApiException, NullPointerException {
if (maxRequestCount <= 0) {
maxRequestCount = REQUESTS_ATTEMPTS_COUNT;
}
int timeToWaitBeforeNextRequestIncaseError = 500;
HttpRetryManager httpRetryManager = new HttpRetryManager(maxRequestCount, timeToWaitBeforeNextRequestIncaseError); // Instance created for each thread
int count = 0; // Only for logging purpose - thread safe | thread local variable
JsonHttpResult result = null;
while (httpRetryManager.canRetry()) {
count++;
try {
reloginLock.readLock().lock();
final HttpMethod httpMethod = compileHttpMethod(request);
printRequestLog(request, "execJsonHttpMethod[request]: requestId=" + requestId + ", count=" + count + ", url=" + httpMethod.getURI(), false);
result = mTransportProvider.execJsonHttpMethod(httpMethod);
boolean isResEmpty = errorIfResponseEmpty(result);
if (isResEmpty) {
try {
httpRetryManager.onErrorUpdateCountAndSleep(new HttpStatusException(result.getHttpStatus(), "Unexpected empty response body"));
} catch (HttpStatusException responseEmpty) {
responseEmpty.printStackTrace();
throw responseEmpty;
}
}
boolean isSessionInvalid = errorIfResponseUnAuthorized(result);
if (isSessionInvalid) {
if (updateSessionIncaseApiGot401()) {
try {
//In-case session does not update, logout the user by escalating 401 to 403 ( InvalidSessionException() ---> InvalidUserException())
httpRetryManager.onErrorUpdateCountAndSleep(new InvalidUserException());
continue; //Start next iteration - no need to check for the rest of the conditions
} catch (InvalidUserException exceptionSessEsclatedToInvalidUser) {
exceptionSessEsclatedToInvalidUser.printStackTrace();
throw exceptionSessEsclatedToInvalidUser;
}
} else {
throw new InvalidUserException(); // WILL TRY ONLY ONCE - IF UPDATE FAILS LOGOUT - 403
}
}
//Logout user incase API threw 403 - Pops up the stack, no retry action required
if (errorIfResponseForbidden(result)) {
throw new InvalidUserException();
}
boolean isHttpErrCodeNotOk = errorIfHttpStatusNotOk(result);
if (!isHttpErrCodeNotOk) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED
&& result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
throw new HttpStatusDetailedException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString(), result.httpError);
} else {
throw new HttpStatusException(result.getHttpStatus(), "Unexpected HTTP(S) result: " + result.toString());
}
}
}
//Success
HttpUUIDController.getInstance().handleSuccessRequest(request);
break;
} catch (TransportLevelException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, requestId=" + requestId + ", count=" + count + ", ex=" + ex, false);
try {
httpRetryManager.onErrorUpdateCountAndSleep(ex);
} catch (Exception transportException) {
transportException.printStackTrace();
throw transportException;
}
} catch (URIException ex) {
printRequestLog(request, "execJsonHttpMethod[error]: request failed, ex=" + ex.getMessage(), false);
throw new InvalidUrlException();
} finally {
printRequestLog(request, "execJsonHttpMethod[result]: finished, requestId=" + requestId + ", count=" + count + ", result=" + result, false);
reloginLock.readLock().unlock();
}
}
simpleLog("Loop has been exited, Iterations: " + count);
return result;
}
These are my helper methods:
private boolean errorIfResponseEmpty(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_OK && result.getHttpResponse() == null) {
printResponseLog(result.getHttpStatus() + " Unexpected empty response body", true);
return true;
}
return false;
}
private boolean errorIfResponseUnAuthorized(HttpResult result) {
if (result.getHttpStatus() == HttpStatus.SC_UNAUTHORIZED) {
printResponseLog(result.getHttpStatus() + " Session Failed", true);
return true;
}
return false;
}
private boolean errorIfHttpStatusNotOk(HttpResult result) {
if (result.getHttpStatus() != HttpStatus.SC_OK && result.getHttpStatus() != HttpStatus.SC_CREATED && result.getHttpStatus() != HttpStatus.SC_NO_CONTENT) {
if (result.httpError != null) {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString() + " " + result.httpError, true);
} else {
printResponseLog(result.getHttpStatus() + " Unexpected HTTP(S) result: " + result.toString(), true);
}
return false;
}
return true;
}
private boolean errorIfResponseForbidden(HttpResult result) {
return (result.getHttpStatus() == HttpStatus.SC_FORBIDDEN);
}
And finally my HttpRetryManager:
private int leftRetries;
private long timeToWait;
public HttpRetryManager(int retries, long timeToWait) {
this.timeToWait = timeToWait;
leftRetries = retries;
}
public boolean canRetry() {
return leftRetries > 0;
}
public void onErrorUpdateCountAndSleep(BaseApiException ex) throws BaseApiException {
leftRetries--;
if (!canRetry()) {
throw ex;
}
waitUntilNextTry();
}
private long getTimeToWait() {
return timeToWait;
}
private void waitUntilNextTry() {
try {
Thread.sleep(getTimeToWait());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java multithreading error-handling api
java multithreading error-handling api
asked 5 mins ago
User3User3
1191115
1191115
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212256%2fhttp-multithreaded-connections-with-retry-and-session-update%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212256%2fhttp-multithreaded-connections-with-retry-and-session-update%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown