Skip to content

Commit c71218f

Browse files
Snow 1853185 - Okta http retry storm - retries implementation for Okta auth (#2064)
1 parent 72acaa8 commit c71218f

17 files changed

+1707
-49
lines changed

TestOnly/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<surefire.version>3.5.1</surefire.version>
2323
<mockito.version>3.5.6</mockito.version>
2424
<netty.version>4.1.118.Final</netty.version>
25+
<apache.httpclient.version>4.5.14</apache.httpclient.version>
2526
<shadeBase>net.snowflake.client.jdbc.internal</shadeBase>
2627
</properties>
2728

@@ -31,6 +32,11 @@
3132
<artifactId>netty-common</artifactId>
3233
<version>${netty.version}</version>
3334
</dependency>
35+
<dependency>
36+
<groupId>org.apache.httpcomponents</groupId>
37+
<artifactId>httpclient</artifactId>
38+
<version>${apache.httpclient.version}</version>
39+
</dependency>
3440
<dependency>
3541
<groupId>io.netty</groupId>
3642
<artifactId>netty-buffer</artifactId>

src/main/java/net/snowflake/client/core/HttpUtil.java

+104-9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import javax.net.ssl.TrustManager;
2929
import net.snowflake.client.jdbc.ErrorCode;
3030
import net.snowflake.client.jdbc.RestRequest;
31+
import net.snowflake.client.jdbc.RetryContextManager;
3132
import net.snowflake.client.jdbc.SnowflakeDriver;
3233
import net.snowflake.client.jdbc.SnowflakeSQLException;
3334
import net.snowflake.client.jdbc.SnowflakeUtil;
@@ -582,7 +583,8 @@ public static boolean isSocksProxyDisabled() {
582583
* @param retryTimeout retry timeout
583584
* @param authTimeout authenticator specific timeout
584585
* @param socketTimeout socket timeout (in ms)
585-
* @param retryCount retry count for the request
586+
* @param retryCount max retry count for the request - if it is set to 0, it will be ignored and
587+
* only retryTimeout will determine when to end the retries
586588
* @param injectSocketTimeout injecting socket timeout
587589
* @param canceling canceling?
588590
* @param ocspAndProxyKey OCSP mode and proxy settings for httpclient
@@ -614,7 +616,8 @@ static String executeRequestWithoutCookies(
614616
true, // guid? (do we need this?)
615617
false, // no retry on HTTP 403
616618
getHttpClient(ocspAndProxyKey),
617-
new ExecTimeTelemetryData());
619+
new ExecTimeTelemetryData(),
620+
null);
618621
}
619622

620623
/**
@@ -624,7 +627,8 @@ static String executeRequestWithoutCookies(
624627
* @param retryTimeout retry timeout
625628
* @param authTimeout authenticator specific timeout
626629
* @param socketTimeout socket timeout (in ms)
627-
* @param retryCount retry count for the request
630+
* @param retryCount max retry count for the request - if it is set to 0, it will be ignored and
631+
* only retryTimeout will determine when to end the retries
628632
* @param ocspAndProxyAndGzipKey OCSP mode and proxy settings for httpclient
629633
* @return response
630634
* @throws SnowflakeSQLException if Snowflake error occurs
@@ -638,6 +642,41 @@ public static String executeGeneralRequest(
638642
int retryCount,
639643
HttpClientSettingsKey ocspAndProxyAndGzipKey)
640644
throws SnowflakeSQLException, IOException {
645+
return executeGeneralRequest(
646+
httpRequest,
647+
retryTimeout,
648+
authTimeout,
649+
socketTimeout,
650+
retryCount,
651+
ocspAndProxyAndGzipKey,
652+
null);
653+
}
654+
655+
/**
656+
* Executes an HTTP request for Snowflake.
657+
*
658+
* @param httpRequest HttpRequestBase
659+
* @param retryTimeout retry timeout
660+
* @param authTimeout authenticator specific timeout
661+
* @param socketTimeout socket timeout (in ms)
662+
* @param retryCount max retry count for the request - if it is set to 0, it will be ignored and
663+
* only retryTimeout will determine when to end the retries
664+
* @param ocspAndProxyAndGzipKey OCSP mode and proxy settings for httpclient
665+
* @param retryContextManager RetryContext used to customize retry handling functionality
666+
* @return response
667+
* @throws SnowflakeSQLException if Snowflake error occurs
668+
* @throws IOException raises if a general IO error occurs
669+
*/
670+
@SnowflakeJdbcInternalApi
671+
public static String executeGeneralRequest(
672+
HttpRequestBase httpRequest,
673+
int retryTimeout,
674+
int authTimeout,
675+
int socketTimeout,
676+
int retryCount,
677+
HttpClientSettingsKey ocspAndProxyAndGzipKey,
678+
RetryContextManager retryContextManager)
679+
throws SnowflakeSQLException, IOException {
641680
logger.debug("Executing general request");
642681
return executeRequest(
643682
httpRequest,
@@ -650,7 +689,8 @@ public static String executeGeneralRequest(
650689
false, // no retry parameter
651690
false, // no retry on HTTP 403
652691
ocspAndProxyAndGzipKey,
653-
new ExecTimeTelemetryData());
692+
new ExecTimeTelemetryData(),
693+
retryContextManager);
654694
}
655695

656696
/**
@@ -660,7 +700,8 @@ public static String executeGeneralRequest(
660700
* @param retryTimeout retry timeout
661701
* @param authTimeout authenticator specific timeout
662702
* @param socketTimeout socket timeout (in ms)
663-
* @param retryCount retry count for the request
703+
* @param retryCount max retry count for the request - if it is set to 0, it will be ignored and
704+
* only retryTimeout will determine when to end the retries
664705
* @param httpClient client object used to communicate with other machine
665706
* @return response
666707
* @throws SnowflakeSQLException if Snowflake error occurs
@@ -688,7 +729,8 @@ public static String executeGeneralRequest(
688729
true, // include request GUID
689730
false, // no retry on HTTP 403
690731
httpClient,
691-
new ExecTimeTelemetryData());
732+
new ExecTimeTelemetryData(),
733+
null);
692734
}
693735

694736
/**
@@ -722,6 +764,54 @@ public static String executeRequest(
722764
HttpClientSettingsKey ocspAndProxyKey,
723765
ExecTimeTelemetryData execTimeData)
724766
throws SnowflakeSQLException, IOException {
767+
return executeRequest(
768+
httpRequest,
769+
retryTimeout,
770+
authTimeout,
771+
socketTimeout,
772+
maxRetries,
773+
injectSocketTimeout,
774+
canceling,
775+
includeRetryParameters,
776+
retryOnHTTP403,
777+
ocspAndProxyKey,
778+
execTimeData,
779+
null);
780+
}
781+
782+
/**
783+
* Executes an HTTP request for Snowflake.
784+
*
785+
* @param httpRequest HttpRequestBase
786+
* @param retryTimeout retry timeout
787+
* @param authTimeout authenticator timeout
788+
* @param socketTimeout socket timeout (in ms)
789+
* @param maxRetries retry count for the request
790+
* @param injectSocketTimeout injecting socket timeout
791+
* @param canceling canceling?
792+
* @param includeRetryParameters whether to include retry parameters in retried requests
793+
* @param retryOnHTTP403 whether to retry on HTTP 403 or not
794+
* @param ocspAndProxyKey OCSP mode and proxy settings for httpclient
795+
* @param execTimeData query execution time telemetry data object
796+
* @param retryContextManager RetryContext used to customize retry handling functionality
797+
* @return response
798+
* @throws SnowflakeSQLException if Snowflake error occurs
799+
* @throws IOException raises if a general IO error occurs
800+
*/
801+
public static String executeRequest(
802+
HttpRequestBase httpRequest,
803+
int retryTimeout,
804+
int authTimeout,
805+
int socketTimeout,
806+
int maxRetries,
807+
int injectSocketTimeout,
808+
AtomicBoolean canceling,
809+
boolean includeRetryParameters,
810+
boolean retryOnHTTP403,
811+
HttpClientSettingsKey ocspAndProxyKey,
812+
ExecTimeTelemetryData execTimeData,
813+
RetryContextManager retryContextManager)
814+
throws SnowflakeSQLException, IOException {
725815
boolean ocspEnabled = !(ocspAndProxyKey.getOcspMode().equals(OCSPMode.DISABLE_OCSP_CHECKS));
726816
logger.debug("Executing request with OCSP enabled: {}", ocspEnabled);
727817
execTimeData.setOCSPStatus(ocspEnabled);
@@ -738,7 +828,8 @@ public static String executeRequest(
738828
true, // include request GUID
739829
retryOnHTTP403,
740830
getHttpClient(ocspAndProxyKey),
741-
execTimeData);
831+
execTimeData,
832+
retryContextManager);
742833
}
743834

744835
/**
@@ -760,6 +851,7 @@ public static String executeRequest(
760851
* @param includeRequestGuid whether to include request_guid
761852
* @param retryOnHTTP403 whether to retry on HTTP 403
762853
* @param httpClient client object used to communicate with other machine
854+
* @param retryContextManager RetryContext used to customize retry handling functionality
763855
* @return response in String
764856
* @throws SnowflakeSQLException if Snowflake error occurs
765857
* @throws IOException raises if a general IO error occurs
@@ -777,7 +869,8 @@ private static String executeRequestInternal(
777869
boolean includeRequestGuid,
778870
boolean retryOnHTTP403,
779871
CloseableHttpClient httpClient,
780-
ExecTimeTelemetryData execTimeData)
872+
ExecTimeTelemetryData execTimeData,
873+
RetryContextManager retryContextManager)
781874
throws SnowflakeSQLException, IOException {
782875
// HttpRequest.toString() contains request URI. Scrub any credentials, if
783876
// present, before logging
@@ -811,7 +904,8 @@ private static String executeRequestInternal(
811904
includeRetryParameters,
812905
includeRequestGuid,
813906
retryOnHTTP403,
814-
execTimeData);
907+
execTimeData,
908+
retryContextManager);
815909
if (logger.isDebugEnabled() && stopwatch != null) {
816910
stopwatch.stop();
817911
}
@@ -825,6 +919,7 @@ private static String executeRequestInternal(
825919
EntityUtils.consume(response.getEntity());
826920
}
827921

922+
// We throw here exception if timeout was reached for login
828923
throw new SnowflakeSQLException(
829924
SqlState.IO_ERROR,
830925
ErrorCode.NETWORK_ERROR.getMessageCode(),

0 commit comments

Comments
 (0)