Giter Club home page Giter Club logo

camunda-external-task-client-python3's Introduction

Community ExtensionLifecycle: Stable

camunda-external-task-client-python3

camunda-external-task-client-python3

This repository contains Camunda External Task Client written in Python3.

Implement your BPMN Service Task in Python3.

Python >= 3.7 is required

Installing

Add following line to requirements.txt of your Python project.

git+https://github.com/trustfactors/camunda-external-task-client-python3.git/#egg=camunda-external-task-client-python3

Or use pip to install as shown below:

pip install camunda-external-task-client-python3

Running Camunda with Docker

To run the examples provided in examples folder, you need to have Camunda running locally or somewhere.

To run Camunda locally with Postgres DB as backend, you can use docker-compose.yml file.

$> docker-compose -f docker-compose.yml up

Auth Basic Examples

To run the examples with Auth Basic provided in examples/examples_auth_basic folder, you need to have Camunda with AuthBasic, running locally or somewhere.

To run Camunda with AuthBasic locally with Postgres DB as backend, you can use docker-compose-auth.yml file.

$> docker-compose -f docker-compose-auth.yml up

Usage

  1. Make sure to have Camunda running.
  2. Create a simple process model with an External Service Task and define the topic as 'topicName'.
  3. Deploy the process to the Camunda BPM engine.
  4. In your Python code:
import time
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker

# configuration for the Client
default_config = {
    "maxTasks": 1,
    "lockDuration": 10000,
    "asyncResponseTimeout": 5000,
    "retries": 3,
    "retryTimeout": 5000,
    "sleepSeconds": 30
}

def handle_task(task: ExternalTask) -> TaskResult:
    """
    This task handler you need to implement with your business logic.
    After completion of business logic call either task.complete() or task.failure() or task.bpmn_error() 
    to report status of task to Camunda
    """
    # add your business logic here
    # ...
    
    # mark task either complete/failure/bpmnError based on outcome of your business logic
    failure, bpmn_error = random_true(), random_true() # this code simulate random failure
    if failure:
        # this marks task as failed in Camunda
        return task.failure(error_message="task failed",  error_details="failed task details", 
                            max_retries=3, retry_timeout=5000)
    elif bpmn_error:
        return task.bpmn_error(error_code="BPMN_ERROR_CODE", error_message="BPMN Error occurred", 
                                variables={"var1": "value1", "success": False})
    
    # pass any output variables you may want to send to Camunda as dictionary to complete()
    return task.complete({"var1": 1, "var2": "value"}) 

def random_true():
    current_milli_time = int(round(time.time() * 1000))
    return current_milli_time % 2 == 0

if __name__ == '__main__':
   ExternalTaskWorker(worker_id="1", config=default_config).subscribe("topicName", handle_task)

About External Tasks

External Tasks are service tasks whose execution differs particularly from the execution of other service tasks (e.g. Human Tasks). The execution works in a way that units of work are polled from the engine before being completed.

camunda-external-task-client-python allows you to create easily such client in Python3.

Features

Camunda provides functionality to start a process instance for a given process definition.

To start a process instance, we can use start_process() from engine_client.py

You can find a usage example here.

client = EngineClient()
resp_json = client.start_process(process_key="PARALLEL_STEPS_EXAMPLE", variables={"intVar": "1", "strVar": "hello"},
                                 tenant_id="6172cdf0-7b32-4460-9da0-ded5107aa977", business_key=str(uuid.uuid1()))

ExternalTaskWorker(worker_id="1").subscribe("topicName", handle_task) starts long polling of the Camunda engine for external tasks.

  • Polling tasks from the engine works by performing a fetch & lock operation of tasks that have subscriptions. It then calls the handler function passed to subscribe() function. i.e. handle_task in above example.
  • Long Polling is done periodically based on the asyncResponseTimeout configuration. Read more about Long Polling.
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker
def handle_task(task: ExternalTask) -> TaskResult:
    # add your business logic here
    
    # Complete the task
    # pass any output variables you may want to send to Camunda as dictionary to complete()
    return task.complete({"var1": 1, "var2": "value"})

ExternalTaskWorker(worker_id="1").subscribe("topicName", handle_task)
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker
def handle_task(task: ExternalTask) -> TaskResult:
    # add your business logic here
    
    # Handle task Failure
    return task.failure(error_message="task failed",  error_details="failed task details", 
                        max_retries=3, retry_timeout=5000)
    # This client/worker uses max_retries if no retries are previously set in the task
    # if retries are previously set then it just decrements that count by one before reporting failure to Camunda
    # when retries are zero, Camunda creates an incident which then manually needs to be looked into on Camunda Cockpit            

ExternalTaskWorker(worker_id="1").subscribe("topicName", handle_task)
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker
def handle_task(task: ExternalTask) -> TaskResult:
    # add your business logic here
    
    # Handle a BPMN Failure
    return task.bpmn_error(error_code="BPMN_ERROR", error_message="BPMN error occurred")

ExternalTaskWorker(worker_id="1" ).subscribe("topicName", handle_task)

Access Process Variables

from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker
def handle_task(task: ExternalTask) -> TaskResult:
    # add your business logic here
    # get the process variable 'score'
    score = task.get_variable("score")
    if int(score) >= 100:
        return task.complete(...)
    else:
        return task.failure(...)        

ExternalTaskWorker().subscribe("topicName", handle_task)

Camunda provides functionality to send a message event to a running process instance.

You can read more about the message events here: https://docs.camunda.org/manual/7.13/reference/bpmn20/events/message-events/

In our to send a message event to a process instance, a new function called correlate_message() is added to engine_client.py

We can correlate the message by:

  • process_instance_id
  • tenant_id
  • business_key
  • process_variables

You can find a usage example here.

client = EngineClient()
resp_json = client.correlate_message("CANCEL_MESSAGE", business_key="b4a6f392-12ab-11eb-80ef-acde48001122")

AuthBasic Usage

To create an EngineClient with AuthBasic simple

client = EngineClient(config={"auth_basic": {"username": "demo", "password": "demo"}})
resp_json = client.start_process(process_key="PARALLEL_STEPS_EXAMPLE", variables={"intVar": "1", "strVar": "hello"},
                                 tenant_id="6172cdf0-7b32-4460-9da0-ded5107aa977", business_key=str(uuid.uuid1()))

To create an ExternalTaskWorker with AuthBasic simple

from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker

config = {"auth_basic": {"username": "demo", "password": "demo"}}

def handle_task(task: ExternalTask) -> TaskResult:
    # add your business logic here
    
    # Complete the task
    # pass any output variables you may want to send to Camunda as dictionary to complete()
    return task.complete({"var1": 1, "var2": "value"})

ExternalTaskWorker(worker_id="1", config=config).subscribe("topicName", handle_task)

License

The source files in this repository are made available under the Apache License Version 2.0.

camunda-external-task-client-python3's People

Contributors

aleneum avatar archetipo avatar behrensger avatar celanthe avatar danbailo avatar hugovk avatar jblawatt avatar jonathanlukas avatar klogges5 avatar mstuebner avatar pjangam avatar tinu-thampi13 avatar yogesh-deserve avatar yogesh-selfscore avatar yogeshrnaik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

camunda-external-task-client-python3's Issues

List variable serialized

I have variables of type 'list in my BPMN. When I use get_variable() method I'm getting a serialized Java object. How can I convert it to a python list ?

exemple :

  • On bpmn : my_var = [ "hello", "world" ]
  • In python external task workder:
    print(task.get_variable('my_var')) => rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAACdwQAAAACdAAHIndvcmxkInQAByJoZWxsbyJ4

print(base64.b64decode(task.get_variable('my_var'))) => b'\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x02w\x04\x00\x00\x00\x02t\x00\x07"world"t\x00\x07"hello"x'

Howto handle multiple topics?

Hi @yogeshrnaik,

first thank you for this useful external task worker for Python.

I'm not a python expert. But I need help to build an example.

What would be the best way, to handle two different topics with two different handle methods?

What I have tried so far (and is working) is:

def handle_task(task: ExternalTask) -> TaskResult:
    if (task.get_topic_name() == "topicName"):
      return handle_topic1(task)
    elif (task.get_topic_name() == "name2"):
      return handle_topic2(task)
    else:
      logging.error("no handler specified")

def handle_topic1(task: ExternalTask) -> TaskResult:
    logging.info("handle topic %s for task id %s", task.get_topic_name(), task.get_task_id())
    return task.complete({"var1": 1, "var2": "value"}) 

def handle_topic2(task: ExternalTask) -> TaskResult:
    logging.info("handle topic %s for task id %s", task.get_topic_name(), task.get_task_id())
    return task.complete({"var5": 1, "var2": "value20"}) 

ExternalTaskWorker(
      worker_id="pythonWorker", config=default_config).subscribe(
        ["topicName", "name2"], handle_task)
 

But I have to put the topic two times in the code: in subscribe and handle_task.

Is there a better way available to register multiple handlers for multiple topics? How would a python expert approach this challenge?

Thank you and kind regards, Ingo

Return of nested structures of variables not more working since 4.1.0

Since Release 4.1.0 we face an issue with returning nested variables.
result until 4.0.0
'docxxx': {'Variable1': 'Test1'}

result since 4.1.0:
'doccxxx': Type=Null, Value is empty """

This make the worker unusable for us.
Regards
Jörg

from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.external_task.external_task_worker import ExternalTaskWorker

DOCC_IDENTIFIER = "doccxxx"
TOPIC_TO_SUBSCRIBE = f"external_test_variable"
DEFAULT_CLIENT_CONFIG = {
    "maxTasks": 1,
    "lockDuration": 10000,
    "asyncResponseTimeout": 60000,
    "retries": 3,
    "retryTimeout": 5000,
    "sleepSeconds": 30
}
BASE_URL = "http://localhost:8080/engine-rest"


def handle_task(task: ExternalTask) -> TaskResult:
    _business_key = task.get_business_key()
    _topic_name = task.get_topic_name()

    print(f'Execute worker for [Business key: {_business_key}/Topic: {_topic_name}]')

    _result_dict_input = {'Variable1': 'Test1'}
    _result_dict = {DOCC_IDENTIFIER: _result_dict_input}

    """result until 4.0.0
    'docxxx': {'Variable1': 'Test1'}
    
    result since 4.1.0:
    'doccxxx': Type=Null, Value is empty """
    return task.complete(global_variables=_result_dict)


if __name__ == '__main__':
    print(f'Connect to {BASE_URL} to topic: {TOPIC_TO_SUBSCRIBE}')
    ExternalTaskWorker(worker_id=DOCC_IDENTIFIER, base_url=BASE_URL,
                       config=DEFAULT_CLIENT_CONFIG).subscribe(TOPIC_TO_SUBSCRIBE, handle_task)

Allow subscribing to a specific businessKey

Right now for when a worker is configured, it subscribes from all businessKeys for a list of topics.

I have a use case where there are multiple process instances running with different business keys.

This behavior is supported in the fetchAndLock REST call.

new release

The pip package is behind on some commits, do you have plans to release a new version?

Missing `pydantic` dependency in `4.3.0`

Hi,

Just installed camunda-external-task-client-python3 version 4.3.0 using poetry, script crashes for missing pydantic dependency.

Script runs fine after installing pydantic.

Graceful shutdown?

Just noticed that the worker does not react to signals, neither does it provide any means to "tell" it to shut down/close.

Possibility of ignoring certain logs by setting a log level

Hi,

First of all, thank you for the library, super useful. Would it be possible to be able to set the log level so that we can ignore certain logs? For example, I don't want to get the logs that 0 tasks were found, but I do want to get the log that x tasks were found. Right now I subclassed the task executor and others to implement it myself, but it s a bit dirty

Pip package don't have dependency on requests but use it

Hello.

requests package not installed with this package after installation using pip.

pip show camunda-external-task-client-python3
Name: camunda-external-task-client-python3
Version: 3.0.0
Summary: Camunda External Task Client for Python 3
Home-page: https://github.com/trustfactors/camunda-external-task-client-python3
Author: Deserve Labs
Author-email: [email protected]
License: LICENSE.txt
Location: c:\users\aaksarin\virtualenvs\crm2camunda\lib\site-packages
Requires:
Required-by:

But in engine_client.py there is requests import.

Centralized use of requests

Hi,
it would be very helpful if all API calls which are made via requests would be routed through a central extendable method. With this it would be possible to inject individual authentication or other recurring options into the call. Since these calls are currently being made in many different methods of the EngineClient and the ExternalTaskClient, this is difficult to achieve.

If you think this suggestion is a good idea, I would participate in the implementation or make a pull request. I just want to make sure the idea has a change to become accepted.

Best regards and thanks for your work!
Jens

Execute Taks Assync - by Celery

Hi folks

I have using, it to dev a Generic External Worker my proposition is run a worker that get the activity(task) and send it to Celery to run asynchronous and free the worker tread.
In my case, i sent o celery and it is working very well but, the necessity is use a celery callback to complete the task when it run ok and a callback_error_handle when it fail.
worker-->celery-->callback.

Anyony have idea what do it
My code
my_task.apply_async(args=[call], link=complete_task.s(task=task), link_error=fail_task.s(task=task))
Where my_task is my celery task.
it show the error:
TypeError: 'ExternalTask' object is not iterable

it is my callback function:

  try:
                if isinstance(result.result, BusinessException):
                    
                    logger.error(F"BusinessError:{result.result.error_code}-> {result.result.error_message}")
                    task.bpmn_error(error_code=result.result.error_code, error_message=result.result.error_message)
                else:
                    task.failure(error_message=f"ERROR_ON_EXCECUTE TASK", error_details="result.result", max_retries=1,
                                 retry_timeout=5000)
except (Exception) as e:
                logger.error(f"ERROR_ON_COMPLETE_TASK_ON_BPMENGINE:{e}", extra={'task': task})             

Update of package in pypi

HI there,
we would like to use the Auth Rest as we need Auth in our prod environment, so is there any plan when a new package will show up in pypi (as we are forced to live from that source)?

Is there any release intervall for these community hub repositories?

br Matthias

Worker is not counting Down Retries and tasks is starting with retries = None

Hy community

First of all thanks for this good lib I using that a lot.
But for now I experiencing a error.
I coded a Simple worker, but it is not capable of fail a task, when the task is complete it is OK, but when task fail I cant fail the task on Camunda engine.

my Simple worker


#configuration for the Client
default_config = {
    "maxTasks": 100,
    "lockDuration": 10000,
    "asyncResponseTimeout": 5000,
    "retries": 0,
    "maxRetries": 3,
    "retryTimeout": 5000,
    "sleepSeconds": 30
}

def handle_task(task: ExternalTask) -> TaskResult:
    """
    This task handler is the hub to get task from camunda bpm-engine and switch to a bpcore task
    """

    logger.info(F"starting task: {task}")

    try:
        print (F"=====Task arrived ----------\n {task}\n ------------------------------\n")
        print (F"=====Properties ----------\n {task._context}\n ------------------------------\n")
        
        #here I do my things returning  a result object
        result = call.my.things()


        
        
        if result.status == "SUCCESS":
            print( f"Completing:{result.status}" )
            return task.complete(result.result)
        elif result.status == "FAILURE":

            try:
                print( f"failed ... :{result.result}" )
                x = task.failure(error_message="task failed",error_details="task failed forced",max_retries=1, retry_timeout=10 )
                print( f"\n---My call to failure is done ... :{task._context}----\n" )

            except (Exception) as e:
                print (F"Why my call Failed : ...{e}-------\n")


    except (Exception) as e:
        logger.error(f"ERROR_ON_EXCECUTE TASK: {e}", extra=task)
        

if __name__ == '__main__':

        ExternalTaskWorker( worker_id="2", config=default_config ).subscribe( "network", handle_task )
`

When I run my code
I can check that:
first:
The task arrive with no retries property:

{'activityId': 'run_discovery', 'activityInstanceId': 'run_discovery:4ec0150e-f6d5-11eb-a3c0-0242ac170003', 'errorMessage': None, 'errorDetails': None, 'executionId': '4ec0150d-f6d5-11eb-a3c0-0242ac170003', 'id': '4ec0150f-f6d5-11eb-a3c0-0242ac170003', 'lockExpirationTime': '2021-08-06T16:52:12.657+0000', 'processDefinitionId': 'BPDiscovery:3:cad9c151-f6d4-11eb-a3c0-0242ac170003', 'processDefinitionKey': 'BPDiscovery', 'processDefinitionVersionTag': None, 'processInstanceId': '4ebc1d65-f6d5-11eb-a3c0-0242ac170003', 'retries': None, 'suspended': False, 'workerId': '2', 'topicName': 'network', 'tenantId': None, 'variables': {'options': {'type': 'String', 'value': '-T4 -sV -A -PS', 'valueInfo': {}}, 'target': {'type': 'String', 'value': '192.168.10.36', 'valueInfo': {}}}, 'priority': 0, 'businessKey': None, 'extensionProperties': {}}
Then my code raise a exception and it print
failed and the result
After call task.failure
it prints
{'activityId': 'run_discovery', 'activityInstanceId': 'run_discovery:4ec0150e-f6d5-11eb-a3c0-0242ac170003', 'errorMessage': None, 'errorDetails': None, 'executionId': '4ec0150d-f6d5-11eb-a3c0-0242ac170003', 'id': '4ec0150f-f6d5-11eb-a3c0-0242ac170003', 'lockExpirationTime': '2021-08-06T16:59:43.919+0000', 'processDefinitionId': 'BPDiscovery:3:cad9c151-f6d4-11eb-a3c0-0242ac170003', 'processDefinitionKey': 'BPDiscovery', 'processDefinitionVersionTag': None, 'processInstanceId': '4ebc1d65-f6d5-11eb-a3c0-0242ac170003', 'retries': None, 'suspended': False, 'workerId': '2', 'topicName': 'network', 'tenantId': None, 'variables': {'options': {'type': 'String', 'value': '-T4 -sV -A -PS', 'valueInfo': {}}, 'target': {'type': 'String', 'value': '192.168.10.36', 'valueInfo': {}}}, 'priority': 0, 'businessKey': None, 'extensionProperties': {}}
That is:
the call to task.failure its ok, but not work.

After thart de worker print :

ERROR:root:[WORKER_ID:2][TOPIC:network][TASK_ID:4ec0150f-f6d5-11eb-a3c0-0242ac170003] error when executing task: <class 'AttributeError'> : 'NoneType' object has no attribute 'get_task' Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/camunda/external_task/external_task_worker.py", line 73, in _execute_task self.executor.execute_task(task, action) File "/usr/local/lib/python3.9/site-packages/camunda/external_task/external_task_executor.py", line 21, in execute_task self._handle_task_result(task_result) File "/usr/local/lib/python3.9/site-packages/camunda/external_task/external_task_executor.py", line 25, in _handle_task_result task = task_result.get_task() AttributeError: 'NoneType' object has no attribute 'get_task'

And retry, retry forever !!! and the task was never finished

Change IP Adress of Camunda run

Hey there,

I've been trying to get the task client, as well as Camunda, running in docker containers.
It's mostly working, but I can't figure out, how I can change the URL, which the task client is trying to reach.

I know, that it's possible to configure an engine_base_url when creating a ExternalClient instance, but I can't figure out, how this Client can be included when subscribing to a topic.

Help would be highly appreciated

Remove Basic Auth Password from logging

We are using the basic auth feature and it is very useful, but we see a problem in using it, because its write on startup the whole config with password in log.
Could you please replace the password with XXX or remove the password from logging?

As Is:

2022-02-11 16:09:29,979 - INFO - Connect to http://localhost:8080/engine-rest to topic: docc606
2022-02-11 16:09:33,394 - INFO - [WORKER_ID:docc606] Created External Task client with config: {'maxTasks': 1, 'lockDuration': 10000, 'asyncResponseTimeout': 60000, 'retries': 3, 'retryTimeout': 5000, 'httpTimeoutMillis': 30000, 'timeoutDeltaMillis': 5000, 'includeExtensionProperties': True, 'auth_basic': {'username': 'demo', 'password': 'demo'}, 'sleepSeconds': 30}
2022-02-11 16:09:33,394 - INFO - [WORKER_ID:docc606] Created new External Task Worker with config: {'auth_basic': {'username': 'demo', 'password': 'demo'}, 'maxTasks': 1, 'lockDuration': 10000, 'asyncResponseTimeout': 60000, 'retries': 3, 'retryTimeout': 5000, 'sleepSeconds': 30}

Should be:

2022-02-11 16:09:29,979 - INFO - Connect to http://localhost:8080/engine-rest to topic: docc606
2022-02-11 16:09:33,394 - INFO - [WORKER_ID:docc606] Created External Task client with config: {'maxTasks': 1, 'lockDuration': 10000, 'asyncResponseTimeout': 60000, 'retries': 3, 'retryTimeout': 5000, 'httpTimeoutMillis': 30000, 'timeoutDeltaMillis': 5000, 'includeExtensionProperties': True, 'auth_basic': {'username': 'demo', 'password': 'XXX'}, 'sleepSeconds': 30}
2022-02-11 16:09:33,394 - INFO - [WORKER_ID:docc606] Created new External Task Worker with config: {'auth_basic': {'username': 'demo', 'password': 'XXX'}, 'maxTasks': 1, 'lockDuration': 10000, 'asyncResponseTimeout': 60000, 'retries': 3, 'retryTimeout': 5000, 'sleepSeconds': 30}

Message correlation fails when using a process instance id

When trying to correlate a message to the engine and using the parameter "processInstanceId" in the body, you are not allowed to also use the parameter "withoutTenantId". By default, this parameter always is inside the body and correlating the message fails.

Taks Assync - by Celery

Hi Everyone.
Hi hi @yogeshrnaik. How are you ?
We have discussed about it a same month ago, but now the things changed positively :)
I have developed and tested and used a "camunda worker" and a "Celery Worker" and solved some technical issues about run External tasks asynchronous with celery and camunda.
To do that I using the stack: Python3, this toll and pycamunda + celery + (opensearch or flower or ELK) and obviously camunda.
Now that reasonably mature to run in production I need to share with the camunda community.
The base that code I will present on next Friday (june, 12) on Camunda meetup Brasil to explain the challengers ans solutions etc.
Then I Asking you?
Do you prefer include it as part of this repository as a sub project ? or do you think that is better create a new repository/project on camunda-community-hub specific for it ?
In my opinion is better join it with this repository, because it is more popular and widespread, But it include others technologies like rabbitmq, opensearch and celery that can be out of objectives of this project.

I Waiting for your answer.

Thanks

TyperError __init__ 'worker_id'

Hi,
I wanted to try out the example from camunda with python as an external task client: https://docs.camunda.org/get-started/quick-start/deploy/

I have the two following files:

  • rest-client
    image

  • external-task-worker
    image

But I got the following error when I start "rest-client".

image

When I run the same code in juypter notebook I don't get the same error & I get a result in my terminal ("external-task-worker").
Do you know why?

Thanks for help!

Tasklist

It appears that camunda has a function to retrieve open tasks for a user: taskService.createTaskQuery. However, I cannot figure out how to get this using this library. I searched through the source code and couldn't find anything promising. By the way, thank you for writing this package--very useful!

Prints not appearing when using ExternalTaskWorker

I've implemented a simple external task client in Python and docker-compose. However, none of my print() statements seem to appear in the console.

The code I wrote is rather straightforward:

import os

from camunda.external_task.external_task_worker import ExternalTaskWorker
from camunda.external_task.external_task import ExternalTask, TaskResult
from camunda.client.engine_client import EngineClient

ENDPOINT_KEY = "ENDPOINT"
TOPIC_KEY = "TOPIC"

def task_handler(task: ExternalTask) -> TaskResult:
    return task.complete()

if __name__ == "__main__":
    ENDPOINT = os.getenv(ENDPOINT_KEY)
    BASE_URL = f'http://{ENDPOINT}/engine-rest'
    TOPIC_NAME = os.getenv(TOPIC_KEY)

    print(f'{BASE_URL=}\n{TOPIC_NAME=}')

    client = EngineClient(BASE_URL)
    worker = ExternalTaskWorker(worker_id=0, base_url=BASE_URL)
    worker.subscribe(TOPIC_NAME, task_handler)

I learned that whenever I remove the last two lines (i.e. the ones creating/using worker), the prints show up just fine.
Additionally, whenever I attach myself to the client's docker instance (using docker attach) and then cause a KeyboardInterrupt, the logs do show up. So they are printed at some point, just not at runtime.

Does anyone know how I can use print() in combination with ExternalTaskWorker? (Thanks in advance!)

Note that the code works just fine; whenever I create a task the client is interested in, it completes it.

In case it's relevant, this is the docker-compose I'm using:

version: "3"

services:
  postgres:
    image: postgres:11
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=app
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"

  camunda-workflow:
    image: camunda/camunda-bpm-platform:7.18.0
    container_name: camunda-workflow
    depends_on:
      - postgres
    ports:
      - "8080:8080"

  camunda-ext-client:
    build: .
    container_name: camunda-ext-client
    depends_on:
      - camunda-workflow
    environment:
      - ENDPOINT=camunda-workflow:8080
      - TOPIC=topicName

volumes:
  pgdata:
    driver: local

requests dependency confusion

Hi, maintainers:

i'm attempting to use this awesome package in my project to do some workflow integration.
when i try to pip install -r requirements.txt, it says

The conflict is caused by:
    The user requested requests==2.27.1
    camunda-external-task-client-python3 4.3.0 depends on requests==2.24.0

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict

here is the part of my requirements.txt:

camunda-external-task-client-python3==4.3.0
requests==2.27.1

but i have another package which uses requests package version >= 2.24.0
when i remove ==4.3.0, it works, got an old version 3.0.0,

maybe here are some clue to find out the reason:
the 2.24.0 appears in setup.cfg, but in requirements.txt it is 2.26.0

i'm new to python, i don't know how pypi/pip works.
but i guess it was just a mistyping of manifest .

thx.

Migrate Project to the Camunda Community Hub?

Hello! I hope today finds you well! My name is Rin Oliver, and I'm a Technical Community Builder at Camunda. I'm opening this issue today to ask if you might be interested in migrating this extension over to the Camunda Community Hub?

We'd love to hear your feedback on how we might improve the overall community extension development process for maintainers and contributors moving forward, and learn more about what you'd like to see from this initiative in the future.

If migrating this extension something you'd be interested in, I can send you the instructions for doing so via email, or whatever communication method works best for you. If you are for any reason no longer able to maintain this extension, if it is migrated to the Hub I would be more than happy to add a lifecycle badge to it indicating that the project is in need of a new maintainer.

I'm also more than happy to schedule a call and talk over this in more detail if that would be preferable to you, for whenever best suits your schedule over the next few weeks.

Thank you so much for your time. I look forward to hearing from you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.