def throw_bpmn_error(self, error_code: str, error_message: str = None, variables: Dict[str, Any] = None, files: Dict = None): if not self.FETCH_RESPONSE: logger.warn( 'No task to complete. Maybe you did not fetch and lock a workitem before?' ) else: with self._shared_resources.api_client as api_client: api_instance = openapi_client.ExternalTaskApi(api_client) variables = CamundaResources.convert_dict_to_openapi_variables( variables) openapi_files = CamundaResources.convert_file_dict_to_openapi_variables( files) variables.update(openapi_files) bpmn_error = openapi_client.ExternalTaskBpmnError( worker_id=self.WORKER_ID, error_message=error_message, error_code=error_code, variables=variables) try: logger.debug(f"Sending BPMN error for task:\n{bpmn_error}") api_instance.handle_external_task_bpmn_error( self.FETCH_RESPONSE.id, external_task_bpmn_error=bpmn_error) self.drop_fetch_response() except ApiException as e: raise ApiException( f"Exception when calling ExternalTaskApi->handle_external_task_bpmn_error: {e}\n" )
def complete_task(self, result_set: Dict[str, Any] = None, files: Dict = None): """ Completes the task that was fetched before with `fetch workload`. *Requires `fetch workload` to run before this one, logs warning instead.* Additional variables can be provided as dictionary in _result_set_ . Files can be provided as dictionary of filename and patch. Examples: | _# fetch and immediately complete_ | | | *fetch workload* | _my_topic_ | | | *complete task* | | | | | _# fetch and complete with return values_ | | | *fetch workload* | _decide_on_dish_ | | ${new_variables} | *Create Dictionary* | _my_dish=salad_ | | | *complete task* | _result_set=${new_variables}_ | | | | _# fetch and complete with return values and files_ | | | *fetch workload* | _decide_on_haircut_ | | ${return_values} | *Create Dictionary* | _style=short hair_ | | ${files} | *Create Dictionary* | _should_look_like=~/favorites/beckham.jpg_ | | | *complete task* | _${return_values}_ | _${files}_ | """ if not self.FETCH_RESPONSE: logger.warn( 'No task to complete. Maybe you did not fetch and lock a workitem before?' ) else: with self._shared_resources.api_client as api_client: api_instance = openapi_client.ExternalTaskApi(api_client) variables = CamundaResources.convert_dict_to_openapi_variables( result_set) openapi_files = CamundaResources.convert_file_dict_to_openapi_variables( files) variables.update(openapi_files) complete_task_dto = openapi_client.CompleteExternalTaskDto( worker_id=self.WORKER_ID, variables=variables) try: logger.debug( f"Sending to Camunda for completing Task:\n{complete_task_dto}" ) api_instance.complete_external_task_resource( self.FETCH_RESPONSE.id, complete_external_task_dto=complete_task_dto) self.drop_fetch_response() except ApiException as e: raise ApiException( f"Exception when calling ExternalTaskApi->complete_external_task_resource: {e}\n" )
def get_amount_of_workloads(self, topic: str, **kwargs) -> int: """ Retrieves count of tasks. By default expects a topic name, but all parameters from the original endpoint may be provided: https://docs.camunda.org/manual/latest/reference/rest/external-task/get-query-count/ """ with self._shared_resources.api_client as api_client: api_instance = openapi_client.ExternalTaskApi(api_client) try: response: CountResultDto = api_instance.get_external_tasks_count( topic_name=topic, **kwargs) except ApiException as e: raise ApiException( f'Failed to count workload for topic "{topic}":\n{e}') logger.info(f'Amount of workloads for "{topic}":\t{response.count}') return response.count
def unlock(self): """ Unlocks recent task. """ if not self.FETCH_RESPONSE: logger.warn( 'No task to unlock. Maybe you did not fetch and lock a workitem before?' ) else: with self._shared_resources.api_client as api_client: api_instance = openapi_client.ExternalTaskApi(api_client) try: api_instance.unlock(self.FETCH_RESPONSE.id) self.drop_fetch_response() except ApiException as e: logger.error( f"Exception when calling ExternalTaskApi->unlock: {e}\n" )
def notify_failure(self, **kwargs): """ Raises a failure to Camunda. When retry counter is less than 1, an incident is created by Camunda. You can specify number of retries with the *retries* argument. If current fetched process instance already has *retries* parameter set, the *retries* argument of this keyword is ignored. Instead, the retries counter will be decreased by 1. CamundaLibrary takes care of providing the worker_id and task_id. *retry_timeout* is equal to *lock_duration* for external tasks. Check for camunda client documentation for all parameters of the request body: https://noordsestern.gitlab.io/camunda-client-for-python/7-15-0/docs/ExternalTaskApi.html#handle_failure Example: | *notify failure* | | | | *notify failure* | retries=3 | error_message=Task failed due to... | """ current_process_instance = self.FETCH_RESPONSE if not current_process_instance: logger.warn( 'No task to notify failure for. Maybe you did not fetch and lock a workitem before?' ) else: with self._shared_resources.api_client as api_client: api_instance = openapi_client.ExternalTaskApi(api_client) if 'retry_timeout' not in kwargs or None is kwargs[ 'retry_timeout'] or not kwargs['retry_timeout']: kwargs['retry_timeout'] = self.DEFAULT_LOCK_DURATION if None is not current_process_instance.retries: kwargs['retries'] = current_process_instance.retries - 1 external_task_failure_dto = ExternalTaskFailureDto( worker_id=self.WORKER_ID, **kwargs) try: api_instance.handle_failure( id=current_process_instance.id, external_task_failure_dto=external_task_failure_dto) self.drop_fetch_response() except ApiException as e: raise ApiException( "Exception when calling ExternalTaskApi->handle_failure: %s\n" % e)
def fetch_workload(self, topic: str, async_response_timeout=None, use_priority=None, **kwargs) -> Dict: """ Locks and fetches workloads from camunda on a given topic. Returns a list of variable dictionary. Each dictionary representing 1 workload from a process instance. If a process instance was fetched, the process instance is cached and can be retrieved by keyword `Get recent process instance` The only mandatory parameter for this keyword is *topic* which is the name of the topic to fetch workload from. More parameters can be added from the Camunda documentation: https://docs.camunda.org/manual/7.14/reference/rest/external-task/fetch/ If not provided, this keyword will use a lock_duration of 60000 ms (10 minutes) and set {{deserialize_value=True}} Examples: | ${input_variables} | *Create Dictionary* | _name=Robot_ | | | *start process* | _my_demo_ | _${input_variables}_ | | ${variables} | *fetch and lock workloads* | _first_task_in_demo_ | | | *Dictionary Should Contain Key* | _${variables}_ | _name_ | | | *Should Be Equal As String* | _Robot_ | _${variables}[name]_ | Example deserializing only some variables: | ${input_variables} | *Create Dictionary* | _name=Robot_ | _profession=Framework_ | | | *start process* | _my_demo_ | _${input_variables}_ | | ${variables_of_interest} | *Create List* | _profession_ | | ${variables} | *Fetch Workload* | _first_task_in_demo_ | _variables=${variables_of_interest}_ | | | *Dictionary Should Not Contain Key* | _${variables}_ | _name_ | | | *Dictionary Should Contain Key* | _${variables}_ | _profession_ | | | *Should Be Equal As String* | _Framework_ | _${variables}[profession]_ | """ api_response = [] with self._shared_resources.api_client as api_client: # Create an instance of the API class api_instance = openapi_client.ExternalTaskApi(api_client) if 'lock_duration' not in kwargs: kwargs['lock_duration'] = 60000 if 'deserialize_values' not in kwargs: kwargs['deserialize_values'] = True topic_dto = FetchExternalTaskTopicDto(topic_name=topic, **kwargs) fetch_external_tasks_dto = FetchExternalTasksDto( worker_id=self.WORKER_ID, max_tasks=1, async_response_timeout=async_response_timeout, use_priority=use_priority, topics=[topic_dto]) try: api_response = api_instance.fetch_and_lock( fetch_external_tasks_dto=fetch_external_tasks_dto) logger.info(api_response) except ApiException as e: logger.error( "Exception when calling ExternalTaskApi->fetch_and_lock: %s\n" % e) work_items: List[LockedExternalTaskDto] = api_response if work_items: logger.debug( f'Received {len(work_items)} work_items from camunda engine for topic:\t{topic}' ) else: logger.debug( f'Received no work items from camunda engine for topic:\t{topic}' ) if not work_items: return {} self.FETCH_RESPONSE = work_items[0] variables: Dict[str, VariableValueDto] = self.FETCH_RESPONSE.variables return CamundaResources.convert_openapi_variables_to_dict(variables)