Skip to content

Commit

Permalink
cleaner error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rsvihladremio committed Oct 19, 2023
1 parent 08169da commit d9ba8b0
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 129 deletions.
18 changes: 11 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
<artifactId>fmt-maven-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
Expand Down Expand Up @@ -138,7 +138,11 @@
</build>

<dependencies>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
Expand Down
6 changes: 6 additions & 0 deletions script/build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
set -e

cd "$(dirname "$0")/.."

echo "==> Formatting files"
./mvnw com.coveo:fmt-maven-plugin:format

echo "==> Validation files"
./mvnw validate
echo "==> Building jar"
./mvnw clean package -DskipTests=true
mv $(ls target/dremio-stress-*-jar-with-dependencies.jar) target/dremio-stress.jar
12 changes: 12 additions & 0 deletions script/fmt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
#
# scripts/fmt: formats files

set -e

cd "$(dirname "$0")/.."

[ -z "$DEBUG" ] || set -x

echo "==> Formatting files"
./mvnw com.coveo:fmt-maven-plugin:format
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ DremioApi connect(
String username,
String password,
String host,
FileMaker fileMaker,
Integer timeoutSeconds,
Protocol protocol,
boolean ignoreSSL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ public DremioApi connect(
String username,
String password,
String host,
FileMaker fileMaker,
Integer timeoutSeconds,
Protocol protocol,
boolean ignoreSSL)
throws IOException {
final UsernamePasswordAuth auth = new UsernamePasswordAuth(username, password);
if (protocol.equals(Protocol.HTTP)) {
HttpApiCall apiCall = new HttpApiCall(ignoreSSL);
return new DremioV3Api(apiCall, auth, host, fileMaker, timeoutSeconds);
return new DremioV3Api(apiCall, auth, host, timeoutSeconds);
}
return new DremioArrowFlightJDBCDriver(host);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,45 +53,41 @@ public DremioArrowFlightJDBCDriver(String url) {
*/
@Override
public DremioApiResponse runSQL(String sql, Collection<String> table) throws IOException {
String context = String.join(".", table);
final DremioApiResponse response = new DremioApiResponse();
final String context;
if (table == null) {
context = "";
} else {
context = String.join(".", table);
}
synchronized (currentContextLock) {
if (!currentContext.equals(context)) {
currentContext = context;
logger.info(() -> String.format("changing context %s", context));
try {
logger.info(() -> String.format("changing context %s", context));
if (!connection.createStatement().execute("USE " + context)) {
response.setErrorMessage("failed using USE");
response.setSuccessful(false);
return response;
throw new RuntimeException("failed using USE");
}
if (connection.createStatement().execute(sql)) {
response.setSuccessful(true);
response.setErrorMessage("");
return response;
final boolean success = connection.createStatement().execute(sql);
if (!success) {
throw new RuntimeException("unhandled exception executing sql");
}
response.setSuccessful(false);
response.setErrorMessage("unhandled error executing sql");
return response;
} catch (SQLException e) {
response.setErrorMessage(e.getMessage());
final DremioApiResponse response = new DremioApiResponse();
response.setSuccessful(true);
return response;
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
}
try {
if (connection.createStatement().execute(sql)) {
final DremioApiResponse response = new DremioApiResponse();
response.setSuccessful(true);
response.setErrorMessage("");
} else {
response.setSuccessful(false);
response.setErrorMessage("unhandled exception");
return response;
}
return response;
throw new RuntimeException("unhandled exception");
} catch (SQLException e) {
response.setSuccessful(false);
response.setErrorMessage(e.getMessage());
return response;
throw new RuntimeException(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public class DremioV3Api implements DremioApi {
/** unmodifiable map of base headers used in all requests that are authenticated */
private final Map<String, String> baseHeaders;

private static final Logger logger = Logger.getLogger(DremioV3Api.class.getName());

// base url for the api typically http/https hostname and port. Does not include the ending /
private final String baseUrl;
// the actual http implementation
private final ApiCall apiCall;

private static final Logger logger = Logger.getLogger(DremioV3Api.class.getName());
private final FileMaker fileMaker;
private final int timeoutSeconds;

/**
Expand All @@ -50,15 +50,9 @@ public class DremioV3Api implements DremioApi {
* @throws IOException throws when unable to read the response body or unable to attach a request
* body
*/
public DremioV3Api(
ApiCall apiCall,
UsernamePasswordAuth auth,
String baseUrl,
FileMaker fileMaker,
int timeoutSeconds)
public DremioV3Api(ApiCall apiCall, UsernamePasswordAuth auth, String baseUrl, int timeoutSeconds)
throws IOException {
this.apiCall = apiCall;
this.fileMaker = fileMaker;
this.timeoutSeconds = timeoutSeconds;
Map<String, String> headers = new HashMap<>();
// working with json
Expand Down Expand Up @@ -96,29 +90,26 @@ private JobStatusResponse checkJobStatus(String jobId) throws IOException {
if (jobId == null || jobId.trim().isEmpty()) {
throw new InvalidParameterException("jobId cannot be empty");
}

// v3 job api
URL url = new URL(this.baseUrl + "/api/v3/job/" + jobId);
// setup headers
HttpApiResponse response = apiCall.submitGet(url, this.baseHeaders);
// jobState is the necessary key
if (response == null
|| response.getResponse() == null
|| !response.getResponse().containsKey("jobState")) {
String error = tryParseError(response);
if (error != null) {
JobStatusResponse jobStatusResponse = new JobStatusResponse();
jobStatusResponse.setStatus("UNKNOWN");
jobStatusResponse.setMessage(error);
return jobStatusResponse;
}
return null;
if (response == null) {
throw new RuntimeException("no valid response");
}
if (response.getResponse() == null) {
throw new RuntimeException("no valid response body");
}
if (!response.getResponse().containsKey("jobState")) {
throw new RuntimeException("no jobState key present");
}
Object jobState = response.getResponse().get("jobState");
if (jobState == null) {
JobStatusResponse jobStatus = new JobStatusResponse();
jobStatus.setStatus("UNKNOWN");
return jobStatus;
throw new RuntimeException("no valid jobState key present");
}
logger.info(() -> String.format("job %s job state %s", jobId, response.getResponse()));
// for failed jobs
if ("FAILED".equals(jobState)) {
String error =
Expand Down Expand Up @@ -156,30 +147,26 @@ public DremioApiResponse runSQL(String sql, Collection<String> contexts) throws
}
String json = new ObjectMapper().writeValueAsString(params);
HttpApiResponse response = apiCall.submitPost(url, this.baseHeaders, json);
if (response == null
|| response.getResponse() == null
|| !response.getResponse().containsKey("id")) {
String errorMessage = tryParseError(response);
if (errorMessage == null) {
errorMessage = String.format("id was not contained in the response '%s'", response);
}

DremioApiResponse failed = new DremioApiResponse();
failed.setSuccessful(false);
failed.setErrorMessage(errorMessage);
return failed;
if (response == null) {
throw new RuntimeException("missing response");
}
if (response.getResponse() == null) {
throw new RuntimeException("missing response body");
}
JobStatusResponse status = new JobStatusResponse();
status.setStatus("UNKNOWN");
if (!response.getResponse().containsKey("id")) {
throw new RuntimeException("id");
}

Instant timeout = Instant.now().plus(timeoutSeconds, ChronoUnit.SECONDS);
String jobId = String.valueOf(response.getResponse().get("id"));
while (!Instant.now().isAfter(timeout)) {
String jobId = String.valueOf(response.getResponse().get("id"));
status = this.checkJobStatus(jobId);
JobStatusResponse status = this.checkJobStatus(jobId);
if (status == null) {
continue;
throw new RuntimeException("unexpected job status critical error");
}
final String statusString = status.getStatus();
if ("COMPLETED".equals(statusString)) {
logger.info(() -> statusString);
DremioApiResponse success = new DremioApiResponse();
success.setSuccessful(true);
return success;
Expand All @@ -188,6 +175,7 @@ public DremioApiResponse runSQL(String sql, Collection<String> contexts) throws
|| "INVALID_STATE".equals(statusString)
|| "CANCELLED".equals(statusString)) {
DremioApiResponse failure = new DremioApiResponse();
failure.setSuccessful(false);
failure.setErrorMessage(String.format("Response status is '%s'", status.getMessage()));
return failure;
}
Expand All @@ -197,13 +185,10 @@ public DremioApiResponse runSQL(String sql, Collection<String> contexts) throws
throw new RuntimeException(e);
}
}
// hit the timeout
DremioApiResponse failed = new DremioApiResponse();
failed.setSuccessful(false);
if (status != null) {
failed.setErrorMessage(String.format("Response status is '%s'", status.getStatus()));
} else {
failed.setErrorMessage("unknown error");
}
failed.setErrorMessage("timeout hit");
return failed;
} catch (Exception ex) {
DremioApiResponse failed = new DremioApiResponse();
Expand All @@ -218,13 +203,4 @@ public DremioApiResponse runSQL(String sql, Collection<String> contexts) throws
public String getUrl() {
return this.baseUrl;
}

private String tryParseError(HttpApiResponse response) {
if (response != null
&& response.getResponse() != null
&& response.getResponse().containsKey("errorMessage")) {
return String.valueOf(response.getResponse().get("errorMessage"));
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class QueryConfig {
private String query;
private String queryGroup;
private int frequency;
private Map<String, Object[]> parameters;
private Map<String, List<Object>> parameters;
private List<String> sqlContext;

public String getQuery() {
Expand All @@ -48,11 +48,11 @@ public void setFrequency(int frequency) {
this.frequency = frequency;
}

public Map<String, Object[]> getParameters() {
public Map<String, List<Object>> getParameters() {
return parameters;
}

public void setParameters(Map<String, Object[]> parameters) {
public void setParameters(Map<String, List<Object>> parameters) {
this.parameters = parameters;
}

Expand Down
Loading

0 comments on commit d9ba8b0

Please sign in to comment.