Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close channel on grpc TRANSIENT_FAILURE #75

Merged
merged 17 commits into from
Jan 12, 2021

Conversation

JonatanMartens
Copy link
Collaborator

@JonatanMartens JonatanMartens commented Nov 3, 2020

Close grpc channel to Zeebe on TRANSIENT_FAILURE status.

Changes

  • Close the grpc channel on TRANSIENT_FAILURE connectivity

API Updates

New Features (required)

None.

Deprecations (required)

None.

Enhancements (optional)

  • Pyzeebe will close the grpc channel if it receives a grpc.ChannelConnectivity.TRANSIENT_FAILURE signal. This fixes an issue where pyzeebe would try to reconnect over and over.

Checklist

  • Unit tests
  • Documentation

References

Fixes #74

@JonatanMartens JonatanMartens added the bug Something isn't working label Nov 3, 2020
@JonatanMartens JonatanMartens linked an issue Nov 3, 2020 that may be closed by this pull request
@JonatanMartens
Copy link
Collaborator Author

It appears the channel should be closed on TRANSIENT_FAILURE, as SHUTDOWN indicates that the channel was closed by the application (not by a network issue)

@JonatanMartens JonatanMartens changed the title Close channel on grpc SHUTDOWN Close channel on grpc TRANSIENT_FAILURE Nov 6, 2020
@kbakk
Copy link
Collaborator

kbakk commented Nov 20, 2020

Doing code review.

When running pylint, I'm getting a quite verbose output, maybe you have an additional .pylintrc (e.g. in $HOME)?

pylint pyzeebe                 
************* Module pyzeebe.decorators.zeebe_decorator_base
pyzeebe/decorators/zeebe_decorator_base.py:6:0: R0205: Class 'ZeebeDecoratorBase' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance)
************* Module pyzeebe.exceptions.credentials_exceptions
pyzeebe/exceptions/credentials_exceptions.py:7:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/exceptions/credentials_exceptions.py:12:0: C0301: Line too long (106/100) (line-too-long)
************* Module pyzeebe.exceptions.workflow_exceptions
pyzeebe/exceptions/workflow_exceptions.py:20:0: C0301: Line too long (102/100) (line-too-long)
************* Module pyzeebe.grpc_internals.zeebe_adapter_base
pyzeebe/grpc_internals/zeebe_adapter_base.py:15:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_adapter_base.py:21:0: C0301: Line too long (101/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_adapter_base.py:32:0: C0301: Line too long (112/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_adapter_base.py:70:0: C0301: Line too long (116/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_adapter_base.py:82:0: C0301: Line too long (116/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_adapter_base.py:13:0: R0205: Class 'ZeebeAdapterBase' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance)
pyzeebe/grpc_internals/zeebe_adapter_base.py:13:0: R0902: Too many instance attributes (8/7) (too-many-instance-attributes)
pyzeebe/grpc_internals/zeebe_adapter_base.py:14:4: R0913: Too many arguments (7/5) (too-many-arguments)
pyzeebe/grpc_internals/zeebe_adapter_base.py:35:8: R1705: Unnecessary "else" after "return" (no-else-return)
pyzeebe/grpc_internals/zeebe_adapter_base.py:43:8: R1705: Unnecessary "elif" after "return" (no-else-return)
pyzeebe/grpc_internals/zeebe_adapter_base.py:51:8: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:54:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:60:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:66:16: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:70:16: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:77:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_adapter_base.py:85:8: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_adapter_base.py:96:15: W0212: Access to a protected member _state of a client class (protected-access)
pyzeebe/grpc_internals/zeebe_adapter_base.py:13:0: R0903: Too few public methods (1/2) (too-few-public-methods)
************* Module pyzeebe.grpc_internals.zeebe_workflow_adapter
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:6:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:7:0: C0301: Line too long (103/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:9:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:24:0: C0301: Line too long (103/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:29:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:42:0: C0301: Line too long (107/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:61:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:24:4: R0913: Too many arguments (6/5) (too-many-arguments)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:38:8: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:53:12: R1720: Unnecessary "else" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:54:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:63:12: R1720: Unnecessary "else" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_workflow_adapter.py:64:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
************* Module pyzeebe.grpc_internals.zeebe_job_adapter
pyzeebe/grpc_internals/zeebe_job_adapter.py:6:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_job_adapter.py:18:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_job_adapter.py:23:0: C0301: Line too long (107/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_job_adapter.py:51:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_job_adapter.py:17:4: R0913: Too many arguments (7/5) (too-many-arguments)
pyzeebe/grpc_internals/zeebe_job_adapter.py:26:20: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/grpc_internals/zeebe_job_adapter.py:29:12: R1720: Unnecessary "else" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_job_adapter.py:30:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:53:12: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_job_adapter.py:54:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:56:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:64:12: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_job_adapter.py:65:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:67:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:76:12: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_job_adapter.py:77:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/grpc_internals/zeebe_job_adapter.py:79:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
************* Module pyzeebe.grpc_internals.zeebe_message_adapter
pyzeebe/grpc_internals/zeebe_message_adapter.py:16:0: C0301: Line too long (102/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_message_adapter.py:17:0: C0301: Line too long (112/100) (line-too-long)
pyzeebe/grpc_internals/zeebe_message_adapter.py:12:4: R0913: Too many arguments (6/5) (too-many-arguments)
pyzeebe/grpc_internals/zeebe_message_adapter.py:19:12: R1720: Unnecessary "else" after "raise" (no-else-raise)
pyzeebe/grpc_internals/zeebe_message_adapter.py:20:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
************* Module pyzeebe.task.task
pyzeebe/task/task.py:9:0: C0301: Line too long (110/100) (line-too-long)
pyzeebe/task/task.py:10:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/task/task.py:23:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/task/task.py:9:4: R0913: Too many arguments (9/5) (too-many-arguments)
************* Module pyzeebe.job.job
pyzeebe/job/job.py:9:0: C0301: Line too long (113/100) (line-too-long)
pyzeebe/job/job.py:66:0: C0301: Line too long (130/100) (line-too-long)
pyzeebe/job/job.py:85:0: C0301: Line too long (113/100) (line-too-long)
pyzeebe/job/job.py:87:0: C0301: Line too long (116/100) (line-too-long)
pyzeebe/job/job.py:89:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/job/job.py:7:0: R0205: Class 'Job' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance)
pyzeebe/job/job.py:7:0: R0902: Too many instance attributes (15/7) (too-many-instance-attributes)
pyzeebe/job/job.py:8:4: R0913: Too many arguments (16/5) (too-many-arguments)
************* Module pyzeebe.worker.worker
pyzeebe/worker/worker.py:21:0: C0301: Line too long (106/100) (line-too-long)
pyzeebe/worker/worker.py:30:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/worker/worker.py:33:0: C0301: Line too long (155/100) (line-too-long)
pyzeebe/worker/worker.py:66:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/worker/worker.py:68:0: C0301: Line too long (101/100) (line-too-long)
pyzeebe/worker/worker.py:81:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/worker/worker.py:98:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/worker/worker.py:99:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/worker/worker.py:106:0: C0301: Line too long (115/100) (line-too-long)
pyzeebe/worker/worker.py:116:0: C0301: Line too long (109/100) (line-too-long)
pyzeebe/worker/worker.py:126:0: C0301: Line too long (120/100) (line-too-long)
pyzeebe/worker/worker.py:21:4: R0913: Too many arguments (10/5) (too-many-arguments)
pyzeebe/worker/worker.py:65:8: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:68:16: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:76:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:80:8: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:98:4: R0913: Too many arguments (8/5) (too-many-arguments)
pyzeebe/worker/worker.py:101:8: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/worker.py:115:4: R0913: Too many arguments (9/5) (too-many-arguments)
pyzeebe/worker/worker.py:119:8: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/worker.py:160:15: W0703: Catching too general exception Exception (broad-except)
pyzeebe/worker/worker.py:160:8: C0103: Variable name "e" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/worker.py:161:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:164:12: W0150: return statement in finally block may swallow exception (lost-exception)
pyzeebe/worker/worker.py:170:15: W0703: Catching too general exception Exception (broad-except)
pyzeebe/worker/worker.py:168:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:170:8: C0103: Variable name "e" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/worker.py:171:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/worker.py:174:21: W0212: Access to a protected member _before of a client class (protected-access)
pyzeebe/worker/worker.py:180:26: W0212: Access to a protected member _after of a client class (protected-access)
pyzeebe/worker/worker.py:196:15: W0703: Catching too general exception Exception (broad-except)
pyzeebe/worker/worker.py:196:8: C0103: Variable name "e" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/worker.py:197:12: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
************* Module pyzeebe.worker.task_handler
pyzeebe/worker/task_handler.py:31:0: C0301: Line too long (104/100) (line-too-long)
pyzeebe/worker/task_handler.py:32:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/worker/task_handler.py:40:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/worker/task_handler.py:41:0: C0301: Line too long (116/100) (line-too-long)
pyzeebe/worker/task_handler.py:45:0: C0301: Line too long (119/100) (line-too-long)
pyzeebe/worker/task_handler.py:47:0: C0301: Line too long (117/100) (line-too-long)
pyzeebe/worker/task_handler.py:59:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/worker/task_handler.py:60:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/worker/task_handler.py:61:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/worker/task_handler.py:64:0: C0301: Line too long (120/100) (line-too-long)
pyzeebe/worker/task_handler.py:69:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/worker/task_handler.py:70:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/worker/task_handler.py:76:0: C0301: Line too long (109/100) (line-too-long)
pyzeebe/worker/task_handler.py:15:0: C0103: Argument name "e" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/task_handler.py:16:4: W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation)
pyzeebe/worker/task_handler.py:30:4: R0913: Too many arguments (10/5) (too-many-arguments)
pyzeebe/worker/task_handler.py:55:8: R1720: Unnecessary "elif" after "raise" (no-else-raise)
pyzeebe/worker/task_handler.py:69:4: R0913: Too many arguments (8/5) (too-many-arguments)
pyzeebe/worker/task_handler.py:72:8: E0711: NotImplemented raised - should raise NotImplementedError (notimplemented-raised)
pyzeebe/worker/task_handler.py:72:14: E1102: NotImplemented is not callable (not-callable)
pyzeebe/worker/task_handler.py:75:4: R0913: Too many arguments (9/5) (too-many-arguments)
pyzeebe/worker/task_handler.py:79:8: E0711: NotImplemented raised - should raise NotImplementedError (notimplemented-raised)
pyzeebe/worker/task_handler.py:79:14: E1102: NotImplemented is not callable (not-callable)
pyzeebe/worker/task_handler.py:82:4: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/task_handler.py:89:4: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/task_handler.py:91:8: R1705: Unnecessary "elif" after "return" (no-else-return)
************* Module pyzeebe.worker.task_router
pyzeebe/worker/task_router.py:10:0: C0301: Line too long (105/100) (line-too-long)
pyzeebe/worker/task_router.py:11:0: C0301: Line too long (108/100) (line-too-long)
pyzeebe/worker/task_router.py:18:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/worker/task_router.py:19:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/worker/task_router.py:28:0: C0301: Line too long (109/100) (line-too-long)
pyzeebe/worker/task_router.py:38:0: C0301: Line too long (116/100) (line-too-long)
pyzeebe/worker/task_router.py:39:0: C0301: Line too long (111/100) (line-too-long)
pyzeebe/worker/task_router.py:47:0: C0301: Line too long (103/100) (line-too-long)
pyzeebe/worker/task_router.py:48:0: C0301: Line too long (110/100) (line-too-long)
pyzeebe/worker/task_router.py:49:0: C0301: Line too long (102/100) (line-too-long)
pyzeebe/worker/task_router.py:50:0: C0301: Line too long (104/100) (line-too-long)
pyzeebe/worker/task_router.py:51:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/worker/task_router.py:10:4: R0913: Too many arguments (8/5) (too-many-arguments)
pyzeebe/worker/task_router.py:13:8: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/task_router.py:27:4: R0913: Too many arguments (9/5) (too-many-arguments)
pyzeebe/worker/task_router.py:31:8: C0103: Argument name "fn" doesn't conform to snake_case naming style (invalid-name)
pyzeebe/worker/task_router.py:47:4: R0913: Too many arguments (9/5) (too-many-arguments)
************* Module pyzeebe.client.client
pyzeebe/client/client.py:13:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/client/client.py:18:0: C0301: Line too long (155/100) (line-too-long)
pyzeebe/client/client.py:21:0: C0301: Line too long (113/100) (line-too-long)
pyzeebe/client/client.py:31:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/client/client.py:46:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/client/client.py:49:0: C0301: Line too long (103/100) (line-too-long)
pyzeebe/client/client.py:56:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/client/client.py:58:0: C0301: Line too long (102/100) (line-too-long)
pyzeebe/client/client.py:73:0: C0301: Line too long (103/100) (line-too-long)
pyzeebe/client/client.py:74:0: C0301: Line too long (114/100) (line-too-long)
pyzeebe/client/client.py:76:0: C0301: Line too long (115/100) (line-too-long)
pyzeebe/client/client.py:121:0: C0301: Line too long (144/100) (line-too-long)
pyzeebe/client/client.py:123:0: C0301: Line too long (120/100) (line-too-long)
pyzeebe/client/client.py:124:0: C0301: Line too long (118/100) (line-too-long)
pyzeebe/client/client.py:135:0: C0301: Line too long (101/100) (line-too-long)
pyzeebe/client/client.py:9:0: R0205: Class 'ZeebeClient' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance)
pyzeebe/client/client.py:12:4: R0913: Too many arguments (7/5) (too-many-arguments)
pyzeebe/client/client.py:49:4: R0913: Too many arguments (6/5) (too-many-arguments)
pyzeebe/client/client.py:114:4: R0913: Too many arguments (6/5) (too-many-arguments)
************* Module pyzeebe.credentials.base_credentials
pyzeebe/credentials/base_credentials.py:6:0: R0903: Too few public methods (1/2) (too-few-public-methods)
************* Module pyzeebe.credentials.oauth_credentials
pyzeebe/credentials/oauth_credentials.py:20:0: C0301: Line too long (102/100) (line-too-long)
pyzeebe/credentials/oauth_credentials.py:37:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
************* Module pyzeebe.credentials.camunda_cloud_credentials
pyzeebe/credentials/camunda_cloud_credentials.py:11:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
pyzeebe/credentials/camunda_cloud_credentials.py:1:0: R0801: Similar lines in 2 files
==pyzeebe.worker.task_router:22
==pyzeebe.worker.worker:110
            return fn

        return wrapper

    def _non_dict_task(self, task_type: str, variable_name: str,
                       exception_handler: ExceptionHandler = default_exception_handler, timeout: int = 10000,
                       max_jobs_to_activate: int = 32, before: List[TaskDecorator] = None,
                       after: List[TaskDecorator] = None, variables_to_fetch: List[str] = None): (duplicate-code)
pyzeebe/credentials/camunda_cloud_credentials.py:1:0: R0801: Similar lines in 2 files
==pyzeebe.worker.task_router:9
==pyzeebe.worker.worker:97
    def _dict_task(self, task_type: str, exception_handler: ExceptionHandler = default_exception_handler,
                   timeout: int = 10000, max_jobs_to_activate: int = 32, before: List[TaskDecorator] = None,
                   after: List[TaskDecorator] = None, variables_to_fetch: List[str] = None):
        def wrapper(fn: Callable[..., Dict]):
            nonlocal variables_to_fetch
            if not variables_to_fetch:
                variables_to_fetch = self._get_parameters_from_function(fn)
 (duplicate-code)

------------------------------------------------------------------
Your code has been rated at 6.94/10 (previous run: 6.94/10, +0.00)

Copy link
Collaborator

@kbakk kbakk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to load the branch to reproduce the error described in #74 - it still would keep the thread open.

Spending some time trying different things (which I don't have a good understanding of), I came across that setting:

@ pyzeebe/grpc_internals/zeebe_adapter_base.py:86 @ class ZeebeAdapterBase(object):
         return self._max_connection_retries == -1 or self._current_connection_retries < self._max_connection_retries
 
     def _common_zeebe_grpc_errors(self, rpc_error: grpc.RpcError):
+        try:
+            self._channel.close()
+        except Exception as err:
+            logger.exception(f"Failed to close channel, {type(err).__name__} exception was raised")
         if self.is_error_status(rpc_error, grpc.StatusCode.RESOURCE_EXHAUSTED):
             raise ZeebeBackPressure()
         elif self.is_error_status(rpc_error, grpc.StatusCode.UNAVAILABLE):

would resolve the issue.

I've put the self._channel.close() in a try/except block, not sure if it can throw an exception. In that case, it should be logged at least (could use logging.error|warning as well, but this is an exceptional situation, so exception seems to make sense).

Here's the output with this in place:

❯ python main.py      
[2020-11-20 17:57:27,295] [18550 - MainThread] [DEBUG] asyncio - Using selector: KqueueSelector
[2020-11-20 17:57:27,323] [18550 - MainThread] [INFO] uvicorn.error - Started server process [18550]
[2020-11-20 17:57:27,323] [18550 - MainThread] [INFO] uvicorn.error - Waiting for application startup.
[2020-11-20 17:57:27,323] [18550 - MainThread] [INFO] uvicorn.error - Application startup complete.
[2020-11-20 17:57:27,324] [18550 - MainThread] [INFO] uvicorn.error - Uvicorn running on http://0.0.0.0:5001 (Press CTRL+C to quit)
[2020-11-20 17:57:38,519] [18550 - Thread-2] [DEBUG] pyzeebe.grpc_internals.zeebe_adapter_base - Grpc channel connectivity changed to: ChannelConnectivity.IDLE
[2020-11-20 17:57:38,520] [18550 - Thread-2] [DEBUG] pyzeebe.grpc_internals.zeebe_adapter_base - Connected to localhost:26599
[2020-11-20 17:57:38,521] [18550 - MainThread] [INFO] uvicorn.access - 127.0.0.1:59761 - "GET / HTTP/1.1" 500
[2020-11-20 17:57:38,521] [18550 - MainThread] [ERROR] uvicorn.error - Exception in ASGI application
Traceback (most recent call last):
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 389, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/message_logger.py", line 65, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/message_logger.py", line 61, in __call__
    await self.app(scope, inner_receive, inner_send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/applications.py", line 179, in __call__
    await super().__call__(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 183, in app
    dependant=dependant, values=values, is_coroutine=is_coroutine
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 135, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "/Users/kristofferb/.pyenv/versions/3.7.6/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "main.py", line 14, in read_root
    queued = client.run_workflow("test-workflow", {})
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/client/client.py", line 47, in run_workflow
    version=version)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_workflow_adapter.py", line 22, in create_workflow_instance
    self._create_workflow_errors(rpc_error, bpmn_process_id, version, variables)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_workflow_adapter.py", line 46, in _create_workflow_errors
    self._common_zeebe_grpc_errors(rpc_error)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_adapter_base.py", line 93, in _common_zeebe_grpc_errors
    raise ZeebeGatewayUnavailable()
pyzeebe.exceptions.zeebe_exceptions.ZeebeGatewayUnavailable


^C[2020-11-20 17:57:45,904] [18550 - MainThread] [INFO] uvicorn.error - Shutting down
[2020-11-20 17:57:46,011] [18550 - MainThread] [INFO] uvicorn.error - Waiting for application shutdown.
[2020-11-20 17:57:46,012] [18550 - MainThread] [INFO] uvicorn.error - Application shutdown complete.
[2020-11-20 17:57:46,012] [18550 - MainThread] [INFO] uvicorn.error - Finished server process [18550]

pyzeebe/grpc_internals/zeebe_adapter_base.py Outdated Show resolved Hide resolved
pyzeebe/grpc_internals/zeebe_adapter_base.py Show resolved Hide resolved
@JonatanMartens JonatanMartens self-assigned this Nov 21, 2020
@kbakk
Copy link
Collaborator

kbakk commented Nov 21, 2020

Might a context manager be needed, to be able to ensure that the connection is closed on exception / when client instance is deleted?

https://stackoverflow.com/questions/865115/how-do-i-correctly-clean-up-a-python-object

@JonatanMartens
Copy link
Collaborator Author

Doing code review.

When running pylint, I'm getting a quite verbose output, maybe you have an additional .pylintrc (e.g. in $HOME)?

I guess Pycharm doesn't use pylint even with the plugin installed :/
I'll open a separate pull request which fixes this.

@JonatanMartens
Copy link
Collaborator Author

Could you take another look at this @kbakk?

Copy link
Collaborator

@kbakk kbakk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done, thanks!

When trying to reproduce with the following changes

 @app.get("/")
 def read_root():
-    client = pyzeebe.ZeebeClient(hostname="localhost", port=NON_LISTENING_PORT)
+    client = pyzeebe.ZeebeClient(
+        hostname="localhost", port=NON_LISTENING_PORT, max_connection_retries=0
+    )
     queued = client.run_workflow("test-workflow", {})
 
     return {"queued": queued}

it works as desired:

python main.py
[2021-01-12 11:13:11,030] [67550 - MainThread] [DEBUG] asyncio - Using selector: KqueueSelector
[2021-01-12 11:13:11,071] [67550 - MainThread] [INFO] uvicorn.error - Started server process [67550]
[2021-01-12 11:13:11,071] [67550 - MainThread] [INFO] uvicorn.error - Waiting for application startup.
[2021-01-12 11:13:11,072] [67550 - MainThread] [INFO] uvicorn.error - Application startup complete.
[2021-01-12 11:13:11,072] [67550 - MainThread] [INFO] uvicorn.error - Uvicorn running on http://0.0.0.0:5001 (Press CTRL+C to quit)
[2021-01-12 11:13:18,977] [67550 - Thread-2] [DEBUG] pyzeebe.grpc_internals.zeebe_adapter_base - Grpc channel connectivity changed to: ChannelConnectivity.IDLE
[2021-01-12 11:13:18,977] [67550 - Thread-2] [DEBUG] pyzeebe.grpc_internals.zeebe_adapter_base - Connected to localhost:26599
[2021-01-12 11:13:19,187] [67550 - MainThread] [INFO] uvicorn.access - 127.0.0.1:51637 - "GET / HTTP/1.1" 500
[2021-01-12 11:13:19,188] [67550 - MainThread] [ERROR] uvicorn.error - Exception in ASGI application
Traceback (most recent call last):
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 389, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/message_logger.py", line 65, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/uvicorn/middleware/message_logger.py", line 61, in __call__
    await self.app(scope, inner_receive, inner_send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/applications.py", line 179, in __call__
    await super().__call__(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 183, in app
    dependant=dependant, values=values, is_coroutine=is_coroutine
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 135, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "/Users/kristofferb/Code/temp/pyzeebe-fastapi/.venv/lib/python3.7/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "/Users/kristofferb/.pyenv/versions/3.7.6/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "main.py", line 16, in read_root
    queued = client.run_workflow("test-workflow", {})
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/client/client.py", line 47, in run_workflow
    version=version)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_workflow_adapter.py", line 22, in create_workflow_instance
    self._create_workflow_errors(rpc_error, bpmn_process_id, version, variables)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_workflow_adapter.py", line 46, in _create_workflow_errors
    self._common_zeebe_grpc_errors(rpc_error)
  File "/Users/kristofferb/Code/fork/pyzeebe/pyzeebe/grpc_internals/zeebe_adapter_base.py", line 89, in _common_zeebe_grpc_errors
    raise ZeebeGatewayUnavailable()
pyzeebe.exceptions.zeebe_exceptions.ZeebeGatewayUnavailable

^C[2021-01-12 11:38:43,072] [67550 - MainThread] [INFO] uvicorn.error - Shutting down
[2021-01-12 11:38:43,181] [67550 - MainThread] [INFO] uvicorn.error - Waiting for application shutdown.
[2021-01-12 11:38:43,183] [67550 - MainThread] [INFO] uvicorn.error - Application shutdown complete.
[2021-01-12 11:38:43,184] [67550 - MainThread] [INFO] uvicorn.error - Finished server process [67550]

docs/client_quickstart.rst Outdated Show resolved Hide resolved
pyzeebe/grpc_internals/zeebe_adapter_base.py Show resolved Hide resolved
@JonatanMartens JonatanMartens merged commit ebf059c into development Jan 12, 2021
@JonatanMartens JonatanMartens deleted the bugfix/74-sesssion_reconnect branch January 12, 2021 11:17
@JonatanMartens JonatanMartens mentioned this pull request Feb 16, 2021
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Zeebe client continues to re-connect after thrown exception
2 participants