use of com.netflix.conductor.client.exceptions.ConductorClientException in project conductor by Netflix.
the class ClientBase method downloadFromExternalStorage.
/**
* Uses the {@link PayloadStorage} for downloading large payloads to be used by the client.
* Gets the uri of the payload fom the server and then downloads from this location.
*
* @param payloadType the {@link com.netflix.conductor.common.utils.ExternalPayloadStorage.PayloadType} to be downloaded
* @param path the relative of the payload in external storage
* @return the payload object that is stored in external storage
*/
@SuppressWarnings("unchecked")
protected Map<String, Object> downloadFromExternalStorage(ExternalPayloadStorage.PayloadType payloadType, String path) {
Preconditions.checkArgument(StringUtils.isNotBlank(path), "uri cannot be blank");
ExternalStorageLocation externalStorageLocation = payloadStorage.getLocation(ExternalPayloadStorage.Operation.READ, payloadType, path);
try (InputStream inputStream = payloadStorage.download(externalStorageLocation.getUri())) {
return objectMapper.readValue(inputStream, Map.class);
} catch (IOException e) {
String errorMsg = String.format("Unable to download payload from external storage location: %s", path);
logger.error(errorMsg, e);
throw new ConductorClientException(errorMsg, e);
}
}
use of com.netflix.conductor.client.exceptions.ConductorClientException in project conductor by Netflix.
the class PayloadStorage method upload.
/**
* Uploads the payload to the uri specified.
*
* @param uri the location to which the object is to be uploaded
* @param payload an {@link InputStream} containing the json payload which is to be uploaded
* @param payloadSize the size of the json payload in bytes
* @throws ConductorClientException if the upload fails due to an invalid path or an error from external storage
*/
@Override
public void upload(String uri, InputStream payload, long payloadSize) {
HttpURLConnection connection = null;
try {
URL url = new URI(uri).toURL();
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(connection.getOutputStream())) {
long count = IOUtils.copy(payload, bufferedOutputStream);
bufferedOutputStream.flush();
// Check the HTTP response code
int responseCode = connection.getResponseCode();
if (Response.Status.fromStatusCode(responseCode).getFamily() != Response.Status.Family.SUCCESSFUL) {
String errorMsg = String.format("Unable to upload. Response code: %d", responseCode);
logger.error(errorMsg);
throw new ConductorClientException(errorMsg);
}
logger.debug("Uploaded {} bytes to uri: {}, with HTTP response code: {}", count, uri, responseCode);
}
} catch (URISyntaxException | MalformedURLException e) {
String errorMsg = String.format("Invalid path specified: %s", uri);
logger.error(errorMsg, e);
throw new ConductorClientException(errorMsg, e);
} catch (IOException e) {
String errorMsg = String.format("Error uploading to path: %s", uri);
logger.error(errorMsg, e);
throw new ConductorClientException(errorMsg, e);
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (payload != null) {
payload.close();
}
} catch (IOException e) {
logger.warn("Unable to close inputstream when uploading to uri: {}", uri);
}
}
}
use of com.netflix.conductor.client.exceptions.ConductorClientException in project conductor by Netflix.
the class WorkflowClient method startWorkflow.
/**
* Starts a workflow.
* If the size of the workflow input payload is bigger than {@link ConductorClientConfiguration#getWorkflowInputPayloadThresholdKB()},
* it is uploaded to {@link ExternalPayloadStorage}, if enabled, else the workflow is rejected.
*
* @param startWorkflowRequest the {@link StartWorkflowRequest} object to start the workflow
* @return the id of the workflow instance that can be used for tracking
* @throws ConductorClientException if {@link ExternalPayloadStorage} is disabled or if the payload size is greater than {@link ConductorClientConfiguration#getWorkflowInputMaxPayloadThresholdKB()}
*/
public String startWorkflow(StartWorkflowRequest startWorkflowRequest) {
Preconditions.checkNotNull(startWorkflowRequest, "StartWorkflowRequest cannot be null");
Preconditions.checkArgument(StringUtils.isNotBlank(startWorkflowRequest.getName()), "Workflow name cannot be null or empty");
Preconditions.checkArgument(StringUtils.isBlank(startWorkflowRequest.getExternalInputPayloadStoragePath()), "External Storage Path must not be set");
String version = startWorkflowRequest.getVersion() != null ? startWorkflowRequest.getVersion().toString() : "latest";
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
objectMapper.writeValue(byteArrayOutputStream, startWorkflowRequest.getInput());
byte[] workflowInputBytes = byteArrayOutputStream.toByteArray();
long workflowInputSize = workflowInputBytes.length;
MetricsContainer.recordWorkflowInputPayloadSize(startWorkflowRequest.getName(), version, workflowInputSize);
if (workflowInputSize > conductorClientConfiguration.getWorkflowInputPayloadThresholdKB() * 1024) {
if (!conductorClientConfiguration.isExternalPayloadStorageEnabled() || (workflowInputSize > conductorClientConfiguration.getWorkflowInputMaxPayloadThresholdKB() * 1024)) {
String errorMsg = String.format("Input payload larger than the allowed threshold of: %d KB", conductorClientConfiguration.getWorkflowInputPayloadThresholdKB());
throw new ConductorClientException(errorMsg);
} else {
MetricsContainer.incrementExternalPayloadUsedCount(startWorkflowRequest.getName(), ExternalPayloadStorage.Operation.WRITE.name(), ExternalPayloadStorage.PayloadType.WORKFLOW_INPUT.name());
String externalStoragePath = uploadToExternalPayloadStorage(ExternalPayloadStorage.PayloadType.WORKFLOW_INPUT, workflowInputBytes, workflowInputSize);
startWorkflowRequest.setExternalInputPayloadStoragePath(externalStoragePath);
startWorkflowRequest.setInput(null);
}
}
} catch (IOException e) {
String errorMsg = String.format("Unable to start workflow:%s, version:%s", startWorkflowRequest.getName(), version);
logger.error(errorMsg, e);
MetricsContainer.incrementWorkflowStartErrorCount(startWorkflowRequest.getName(), e);
throw new ConductorClientException(errorMsg, e);
}
try {
return postForEntity("workflow", startWorkflowRequest, null, String.class, startWorkflowRequest.getName());
} catch (ConductorClientException e) {
String errorMsg = String.format("Unable to send start workflow request:%s, version:%s", startWorkflowRequest.getName(), version);
logger.error(errorMsg, e);
MetricsContainer.incrementWorkflowStartErrorCount(startWorkflowRequest.getName(), e);
throw e;
}
}
use of com.netflix.conductor.client.exceptions.ConductorClientException in project conductor by Netflix.
the class AbstractHttpEndToEndTest method testUpdateWorkflowDefNameNull.
@Test(expected = ConductorClientException.class)
public void testUpdateWorkflowDefNameNull() {
WorkflowDef workflowDef = new WorkflowDef();
List<WorkflowDef> list = new ArrayList<>();
list.add(workflowDef);
try {
metadataClient.updateWorkflowDefs(list);
} catch (ConductorClientException e) {
assertEquals(3, e.getValidationErrors().size());
assertEquals(400, e.getStatus());
assertEquals("Validation failed, check below errors for detail.", e.getMessage());
assertFalse(e.isRetryable());
List<ValidationError> errors = e.getValidationErrors();
List<String> errorMessages = errors.stream().map(ValidationError::getMessage).collect(Collectors.toList());
assertTrue(errorMessages.contains("WorkflowDef name cannot be null or empty"));
assertTrue(errorMessages.contains("WorkflowTask list cannot be empty"));
assertTrue(errorMessages.contains("ownerEmail cannot be empty"));
throw e;
}
}
use of com.netflix.conductor.client.exceptions.ConductorClientException in project conductor by Netflix.
the class AbstractHttpEndToEndTest method testEmptyCreateWorkflowDef.
@Test(expected = ConductorClientException.class)
public void testEmptyCreateWorkflowDef() {
try {
WorkflowDef workflowDef = new WorkflowDef();
metadataClient.registerWorkflowDef(workflowDef);
} catch (ConductorClientException e) {
assertEquals(400, e.getStatus());
assertEquals("Validation failed, check below errors for detail.", e.getMessage());
assertFalse(e.isRetryable());
List<ValidationError> errors = e.getValidationErrors();
List<String> errorMessages = errors.stream().map(ValidationError::getMessage).collect(Collectors.toList());
assertTrue(errorMessages.contains("WorkflowDef name cannot be null or empty"));
assertTrue(errorMessages.contains("WorkflowTask list cannot be empty"));
throw e;
}
}
Aggregations