use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class Controller method reconcile.
@Override
public synchronized UpdateControl<$DataType$> reconcile($DataType$ resource, Context context) {
if (!acceptedPayload(resource)) {
LOGGER.debug("Event has been rejected by the filter expression");
return UpdateControl.noUpdate();
}
String trigger = "$Trigger$";
IdentityProvider.set(new TrustedIdentityProvider("System<messaging>"));
final $Type$ model = new $Type$();
return io.automatiko.engine.services.uow.UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
try {
String correlation = resource.getMetadata().getName();
if (correlation != null) {
LOGGER.debug("Correlation ({}) is set, attempting to find if there is matching instance already active", correlation);
Optional<? extends ProcessInstance> possiblyFound = (Optional<? extends ProcessInstance>) process.instances().findById(correlation);
if (possiblyFound.isPresent()) {
ProcessInstance pInstance = (ProcessInstance) possiblyFound.get();
LOGGER.debug("Found process instance {} matching correlation {}, signaling instead of starting new instance", pInstance.id(), correlation);
pInstance.send(Sig.of("Message-updated", resource));
$DataType$ updated = ($DataType$) ((Model) pInstance.variables()).toMap().get("resource");
if (updated == null || Boolean.TRUE.equals(((WorkflowProcessInstanceImpl) ((AbstractProcessInstance<?>) pInstance).processInstance()).getVariable("skipResourceUpdate"))) {
LOGGER.debug("Signalled and returned updated {} no need to updated custom resource", updated);
return UpdateControl.noUpdate();
}
LOGGER.debug("Signalled and returned updated {} that requires update of the custom resource", updated);
return UpdateControl.updateResourceAndStatus(updated);
}
}
if (canStartInstance()) {
LOGGER.debug("Received message without reference id and no correlation is set/matched, staring new process instance with trigger '{}'", trigger);
ProcessInstance<?> pi = process.createInstance(correlation, model);
pi.start(trigger, null, resource);
$DataType$ updated = ($DataType$) ((Model) pi.variables()).toMap().get("resource");
if (updated == null || Boolean.TRUE.equals(((WorkflowProcessInstanceImpl) ((AbstractProcessInstance<?>) pi).processInstance()).getVariable("skipResourceUpdate"))) {
LOGGER.debug("New instance started and not need to update custom resource");
return UpdateControl.noUpdate();
}
LOGGER.debug("New instance started and with the need to update custom resource");
return UpdateControl.updateResourceAndStatus(updated);
} else {
LOGGER.warn("Received message without reference id and no correlation is set/matched, for trigger not capable of starting new instance '{}'", trigger);
}
} catch (Throwable t) {
LOGGER.error("Encountered problems while creating/updating instance", t);
}
return UpdateControl.noUpdate();
});
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class CassandraProcessInstances method create.
@Override
public void create(String id, ProcessInstance instance) {
String resolvedId = resolveId(id, instance);
if (isActive(instance)) {
LOGGER.debug("create() called for instance {}", resolvedId);
byte[] data = codec.encode(marshaller.marhsallProcessInstance(instance));
if (data == null) {
return;
}
Collection<String> tags = new LinkedHashSet<>(instance.tags().values());
tags.add(resolvedId);
if (instance.businessKey() != null) {
tags.add(instance.businessKey());
}
Insert insert = insertInto(config.keyspace().orElse("automatiko"), tableName).value(INSTANCE_ID_FIELD, literal(resolvedId)).value(VERSION_FIELD, literal(((AbstractProcessInstance<?>) instance).getVersionTracker())).value(STATUS_FIELD, literal(((AbstractProcessInstance<?>) instance).status())).value(CONTENT_FIELD, bindMarker()).value(TAGS_FIELD, bindMarker()).ifNotExists();
try {
ResultSet rs = cqlSession.execute(cqlSession.prepare(insert.build()).bind(ByteBuffer.wrap(data), tags));
if (!rs.wasApplied()) {
throw new ProcessInstanceDuplicatedException(id);
}
} catch (QueryExecutionException e) {
throw new ProcessInstanceDuplicatedException(id);
} finally {
cachedInstances.remove(resolvedId);
cachedInstances.remove(id);
disconnect(instance);
}
} else if (isPending(instance)) {
if (cachedInstances.putIfAbsent(resolvedId, instance) != null) {
throw new ProcessInstanceDuplicatedException(id);
}
} else {
cachedInstances.remove(resolvedId);
cachedInstances.remove(id);
}
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class DatabaseProcessInstances method disconnect.
protected void disconnect(ProcessInstance<ProcessInstanceEntity> instance) {
((AbstractProcessInstance<?>) instance).internalRemoveProcessInstance(() -> {
try {
ProcessInstanceEntity entity = (ProcessInstanceEntity) JpaOperations.INSTANCE.findById(type, resolveId(instance.id(), instance));
byte[] reloaded = codec.decode(entity.content);
WorkflowProcessInstance wpi = marshaller.unmarshallWorkflowProcessInstance(reloaded, process);
entity.toMap().forEach((k, v) -> {
if (v != null) {
v.toString();
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((ProcessInstanceImpl) wpi).getContextInstance(VariableScope.VARIABLE_SCOPE);
variableScopeInstance.internalSetVariable(k, v);
}
});
return wpi;
} catch (RuntimeException e) {
LOGGER.error("Unexpected exception thrown when reloading process instance {}", instance.id(), e);
return null;
}
});
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class DynamoDBProcessInstances method update.
@Override
public void update(String id, ProcessInstance instance) {
String resolvedId = resolveId(id, instance);
if (isActive(instance)) {
LOGGER.debug("update() called for instance {}", resolvedId);
byte[] data = codec.encode(marshaller.marhsallProcessInstance(instance));
if (data == null) {
return;
}
HashMap<String, AttributeValue> itemKey = new HashMap<String, AttributeValue>();
itemKey.put(INSTANCE_ID_FIELD, AttributeValue.builder().s(resolvedId).build());
Map<String, AttributeValueUpdate> updatedValues = new HashMap<String, AttributeValueUpdate>();
updatedValues.put(CONTENT_FIELD, AttributeValueUpdate.builder().value(AttributeValue.builder().b(SdkBytes.fromByteArray(data)).build()).action(AttributeAction.PUT).build());
updatedValues.put(VERSION_FIELD, AttributeValueUpdate.builder().value(AttributeValue.builder().n(String.valueOf(((AbstractProcessInstance<?>) instance).getVersionTracker() + 1)).build()).action(AttributeAction.PUT).build());
updatedValues.put(STATUS_FIELD, AttributeValueUpdate.builder().value(AttributeValue.builder().n(String.valueOf(((AbstractProcessInstance<?>) instance).status())).build()).action(AttributeAction.PUT).build());
Collection<String> tags = new ArrayList(instance.tags().values());
tags.add(resolvedId);
if (instance.businessKey() != null) {
tags.add(instance.businessKey());
}
updatedValues.put(TAGS_FIELD, AttributeValueUpdate.builder().value(AttributeValue.builder().ss(tags).build()).action(AttributeAction.PUT).build());
UpdateItemRequest request = UpdateItemRequest.builder().tableName(tableName).key(itemKey).attributeUpdates(updatedValues).conditionExpression(VERSION_FIELD + " = " + ((AbstractProcessInstance<?>) instance).getVersionTracker()).build();
try {
dynamodb.updateItem(request);
} catch (ConditionalCheckFailedException e) {
throw new ConflictingVersionException("Process instance with id '" + instance.id() + "' has older version than the stored one");
} finally {
disconnect(instance);
}
}
cachedInstances.remove(resolvedId);
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class DynamoDBProcessInstances method create.
@Override
public void create(String id, ProcessInstance instance) {
String resolvedId = resolveId(id, instance);
if (isActive(instance)) {
LOGGER.debug("create() called for instance {}", resolvedId);
byte[] data = codec.encode(marshaller.marhsallProcessInstance(instance));
if (data == null) {
return;
}
Map<String, AttributeValue> itemValues = new HashMap<String, AttributeValue>();
itemValues.put(INSTANCE_ID_FIELD, AttributeValue.builder().s(resolvedId).build());
itemValues.put(VERSION_FIELD, AttributeValue.builder().n(String.valueOf(((AbstractProcessInstance<?>) instance).getVersionTracker())).build());
itemValues.put(STATUS_FIELD, AttributeValue.builder().n(String.valueOf(((AbstractProcessInstance<?>) instance).status())).build());
itemValues.put(CONTENT_FIELD, AttributeValue.builder().b(SdkBytes.fromByteArray(data)).build());
Collection<String> tags = new ArrayList(instance.tags().values());
tags.add(resolvedId);
if (instance.businessKey() != null) {
tags.add(instance.businessKey());
}
itemValues.put(TAGS_FIELD, AttributeValue.builder().ss(tags).build());
PutItemRequest request = PutItemRequest.builder().tableName(tableName).conditionExpression("attribute_not_exists(" + INSTANCE_ID_FIELD + ")").item(itemValues).build();
try {
dynamodb.putItem(request);
} catch (ConditionalCheckFailedException e) {
throw new ProcessInstanceDuplicatedException(id);
} finally {
cachedInstances.remove(resolvedId);
cachedInstances.remove(id);
disconnect(instance);
}
} else if (isPending(instance)) {
if (cachedInstances.putIfAbsent(resolvedId, instance) != null) {
throw new ProcessInstanceDuplicatedException(id);
}
} else {
cachedInstances.remove(resolvedId);
cachedInstances.remove(id);
}
}
Aggregations