conductor-python 1.3.11__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. {conductor_python-1.3.11 → conductor_python-1.5.0}/PKG-INFO +42 -9
  2. {conductor_python-1.3.11 → conductor_python-1.5.0}/README.md +38 -5
  3. {conductor_python-1.3.11 → conductor_python-1.5.0}/pyproject.toml +9 -5
  4. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/__init__.py +2 -1
  5. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/async_task_runner.py +21 -2
  6. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/task_handler.py +71 -13
  7. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/task_runner.py +21 -2
  8. conductor_python-1.5.0/src/conductor/client/configuration/settings/metrics_settings.py +151 -0
  9. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/workflow_resource_api.py +6 -2
  10. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api_client.py +67 -24
  11. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/async_api_client.py +41 -16
  12. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/async_rest.py +4 -1
  13. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/rest.py +36 -25
  14. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_base_client.py +9 -2
  15. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_workflow_client.py +48 -5
  16. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes_clients.py +14 -3
  17. conductor_python-1.5.0/src/conductor/client/telemetry/canonical_metrics_collector.py +242 -0
  18. conductor_python-1.5.0/src/conductor/client/telemetry/legacy_metrics_collector.py +324 -0
  19. conductor_python-1.5.0/src/conductor/client/telemetry/metrics_collector.py +38 -0
  20. conductor_python-1.5.0/src/conductor/client/telemetry/metrics_collector_base.py +504 -0
  21. conductor_python-1.5.0/src/conductor/client/telemetry/metrics_factory.py +62 -0
  22. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/telemetry/model/metric_documentation.py +12 -1
  23. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/telemetry/model/metric_label.py +1 -0
  24. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/telemetry/model/metric_name.py +9 -0
  25. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/worker.py +120 -1
  26. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/executor/workflow_executor.py +22 -6
  27. conductor_python-1.3.11/src/conductor/client/configuration/settings/metrics_settings.py +0 -59
  28. conductor_python-1.3.11/src/conductor/client/telemetry/metrics_collector.py +0 -927
  29. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/__init__.py +0 -0
  30. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/ai/__init__.py +0 -0
  31. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/ai/configuration.py +0 -0
  32. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/ai/integrations.py +0 -0
  33. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/ai/orchestrator.py +0 -0
  34. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/authorization_client.py +0 -0
  35. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/__init__.py +0 -0
  36. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/json_schema_generator.py +0 -0
  37. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/lease_tracker.py +0 -0
  38. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/automator/utils.py +0 -0
  39. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/configuration/__init__.py +0 -0
  40. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/configuration/configuration.py +0 -0
  41. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/configuration/settings/__init__.py +0 -0
  42. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/configuration/settings/authentication_settings.py +0 -0
  43. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/context/__init__.py +0 -0
  44. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/context/task_context.py +0 -0
  45. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/__init__.py +0 -0
  46. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/conductor_event.py +0 -0
  47. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/event_client.py +0 -0
  48. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/event_dispatcher.py +0 -0
  49. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/listener_register.py +0 -0
  50. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/listeners.py +0 -0
  51. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/queue/__init__.py +0 -0
  52. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/queue/kafka_queue_configuration.py +0 -0
  53. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/queue/queue_configuration.py +0 -0
  54. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/queue/queue_worker_configuration.py +0 -0
  55. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/sync_event_dispatcher.py +0 -0
  56. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/sync_listener_register.py +0 -0
  57. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/task_events.py +0 -0
  58. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/task_runner_events.py +0 -0
  59. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/event/workflow_events.py +0 -0
  60. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/exceptions/__init__.py +0 -0
  61. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/exceptions/api_error.py +0 -0
  62. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/exceptions/api_exception_handler.py +0 -0
  63. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/helpers/__init__.py +0 -0
  64. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/helpers/helper.py +0 -0
  65. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/__init__.py +0 -0
  66. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/__init__.py +0 -0
  67. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/application_resource_api.py +0 -0
  68. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/async_task_resource_api.py +0 -0
  69. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/authorization_resource_api.py +0 -0
  70. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/event_resource_api.py +0 -0
  71. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/gateway_auth_resource_api.py +0 -0
  72. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/group_resource_api.py +0 -0
  73. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/integration_resource_api.py +0 -0
  74. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/metadata_resource_api.py +0 -0
  75. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/prompt_resource_api.py +0 -0
  76. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/role_resource_api.py +0 -0
  77. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/scheduler_resource_api.py +0 -0
  78. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/schema_resource_api.py +0 -0
  79. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/secret_resource_api.py +0 -0
  80. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/service_registry_resource_api.py +0 -0
  81. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/task_resource_api.py +0 -0
  82. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/token_resource_api.py +0 -0
  83. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/user_resource_api.py +0 -0
  84. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/api/workflow_bulk_resource_api.py +0 -0
  85. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/__init__.py +0 -0
  86. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/action.py +0 -0
  87. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/auditable.py +0 -0
  88. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/authentication_config.py +0 -0
  89. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/authorization_request.py +0 -0
  90. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/bulk_response.py +0 -0
  91. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/circuit_breaker_transition_response.py +0 -0
  92. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/conductor_application.py +0 -0
  93. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/conductor_user.py +0 -0
  94. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/correlation_ids_search_request.py +0 -0
  95. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/create_or_update_application_request.py +0 -0
  96. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/create_or_update_role_request.py +0 -0
  97. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/event_handler.py +0 -0
  98. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/external_storage_location.py +0 -0
  99. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/generate_token_request.py +0 -0
  100. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/group.py +0 -0
  101. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/health.py +0 -0
  102. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/health_check_status.py +0 -0
  103. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/integration.py +0 -0
  104. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/integration_api.py +0 -0
  105. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/integration_api_update.py +0 -0
  106. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/integration_def.py +0 -0
  107. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/integration_update.py +0 -0
  108. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/permission.py +0 -0
  109. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/poll_data.py +0 -0
  110. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/prompt_template.py +0 -0
  111. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/prompt_test_request.py +0 -0
  112. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/proto_registry_entry.py +0 -0
  113. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/rate_limit.py +0 -0
  114. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/request_param.py +0 -0
  115. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/rerun_workflow_request.py +0 -0
  116. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/response.py +0 -0
  117. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/role.py +0 -0
  118. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/save_schedule_request.py +0 -0
  119. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/schema_def.py +0 -0
  120. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/scrollable_search_result_workflow_summary.py +0 -0
  121. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/search_result_task.py +0 -0
  122. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/search_result_task_summary.py +0 -0
  123. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/search_result_workflow.py +0 -0
  124. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/search_result_workflow_schedule_execution_model.py +0 -0
  125. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/search_result_workflow_summary.py +0 -0
  126. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/service_method.py +0 -0
  127. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/service_registry.py +0 -0
  128. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/signal_response.py +0 -0
  129. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/skip_task_request.py +0 -0
  130. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/start_workflow.py +0 -0
  131. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/start_workflow_request.py +0 -0
  132. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/state_change_event.py +0 -0
  133. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/sub_workflow_params.py +0 -0
  134. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/subject_ref.py +0 -0
  135. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/tag_object.py +0 -0
  136. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/tag_string.py +0 -0
  137. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/target_ref.py +0 -0
  138. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task.py +0 -0
  139. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_def.py +0 -0
  140. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_details.py +0 -0
  141. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_exec_log.py +0 -0
  142. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_result.py +0 -0
  143. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_result_status.py +0 -0
  144. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/task_summary.py +0 -0
  145. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/terminate_workflow.py +0 -0
  146. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/token.py +0 -0
  147. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/update_workflow_variables.py +0 -0
  148. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/upsert_group_request.py +0 -0
  149. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/upsert_user_request.py +0 -0
  150. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow.py +0 -0
  151. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_def.py +0 -0
  152. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_message.py +0 -0
  153. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_run.py +0 -0
  154. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_schedule.py +0 -0
  155. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_schedule_execution_model.py +0 -0
  156. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_state_update.py +0 -0
  157. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_status.py +0 -0
  158. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_summary.py +0 -0
  159. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_tag.py +0 -0
  160. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_task.py +0 -0
  161. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/models/workflow_test_request.py +0 -0
  162. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/http/thread.py +0 -0
  163. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/integration_client.py +0 -0
  164. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/metadata_client.py +0 -0
  165. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/__init__.py +0 -0
  166. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/api/__init__.py +0 -0
  167. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/api/tags_api.py +0 -0
  168. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/__init__.py +0 -0
  169. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/access_key.py +0 -0
  170. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/access_key_status.py +0 -0
  171. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/access_type.py +0 -0
  172. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/created_access_key.py +0 -0
  173. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/granted_permission.py +0 -0
  174. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/metadata_tag.py +0 -0
  175. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/models/ratelimit_tag.py +0 -0
  176. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_authorization_client.py +0 -0
  177. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_integration_client.py +0 -0
  178. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_metadata_client.py +0 -0
  179. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_prompt_client.py +0 -0
  180. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_scheduler_client.py +0 -0
  181. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_schema_client.py +0 -0
  182. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_secret_client.py +0 -0
  183. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_service_registry_client.py +0 -0
  184. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/orkes/orkes_task_client.py +0 -0
  185. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/prompt_client.py +0 -0
  186. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/scheduler_client.py +0 -0
  187. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/schema_client.py +0 -0
  188. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/secret_client.py +0 -0
  189. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/service_registry_client.py +0 -0
  190. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/task_client.py +0 -0
  191. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/telemetry/__init__.py +0 -0
  192. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/telemetry/model/__init__.py +0 -0
  193. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/__init__.py +0 -0
  194. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/exception.py +0 -0
  195. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/worker_config.py +0 -0
  196. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/worker_interface.py +0 -0
  197. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/worker_loader.py +0 -0
  198. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/worker/worker_task.py +0 -0
  199. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/__init__.py +0 -0
  200. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/conductor_workflow.py +0 -0
  201. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/executor/__init__.py +0 -0
  202. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/__init__.py +0 -0
  203. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/do_while_task.py +0 -0
  204. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/dynamic_fork_task.py +0 -0
  205. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/dynamic_task.py +0 -0
  206. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/event_task.py +0 -0
  207. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/fork_task.py +0 -0
  208. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/get_document.py +0 -0
  209. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/http_poll_task.py +0 -0
  210. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/http_task.py +0 -0
  211. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/human_task.py +0 -0
  212. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/inline.py +0 -0
  213. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/javascript_task.py +0 -0
  214. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/join_task.py +0 -0
  215. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/json_jq_task.py +0 -0
  216. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/kafka_publish.py +0 -0
  217. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/kafka_publish_input.py +0 -0
  218. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/__init__.py +0 -0
  219. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/call_mcp_tool.py +0 -0
  220. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/chat_message.py +0 -0
  221. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/generate_audio.py +0 -0
  222. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/generate_image.py +0 -0
  223. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/list_mcp_tools.py +0 -0
  224. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_chat_complete.py +0 -0
  225. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_generate_embeddings.py +0 -0
  226. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_index_documents.py +0 -0
  227. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_index_text.py +0 -0
  228. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_query_embeddings.py +0 -0
  229. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_search_embeddings.py +0 -0
  230. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_search_index.py +0 -0
  231. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_store_embeddings.py +0 -0
  232. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/llm_text_complete.py +0 -0
  233. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/tool_call.py +0 -0
  234. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/tool_spec.py +0 -0
  235. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/utils/__init__.py +0 -0
  236. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/utils/embedding_model.py +0 -0
  237. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/llm_tasks/utils/prompt.py +0 -0
  238. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/pull_workflow_messages_task.py +0 -0
  239. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/set_variable_task.py +0 -0
  240. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/simple_task.py +0 -0
  241. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/start_workflow_task.py +0 -0
  242. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/sub_workflow_task.py +0 -0
  243. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/switch_task.py +0 -0
  244. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/task.py +0 -0
  245. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/task_type.py +0 -0
  246. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/terminate_task.py +0 -0
  247. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/timeout_policy.py +0 -0
  248. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/wait_for_webhook_task.py +0 -0
  249. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow/task/wait_task.py +0 -0
  250. {conductor_python-1.3.11 → conductor_python-1.5.0}/src/conductor/client/workflow_client.py +0 -0
@@ -1,17 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conductor-python
3
- Version: 1.3.11
3
+ Version: 1.5.0
4
4
  Summary: Python SDK for working with https://github.com/conductor-oss/conductor
5
5
  License: Apache-2.0
6
6
  Author: Orkes
7
7
  Author-email: developers@orkes.io
8
- Requires-Python: >=3.9
8
+ Requires-Python: >=3.10
9
9
  Classifier: Development Status :: 5 - Production/Stable
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: Intended Audience :: System Administrators
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
@@ -27,10 +26,11 @@ Requires-Dist: h2 (>=4.1.0)
27
26
  Requires-Dist: httpx[http2] (>=0.26.0)
28
27
  Requires-Dist: prometheus-client (>=0.13.1)
29
28
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
30
- Requires-Dist: requests (>=2.31.0)
29
+ Requires-Dist: requests (>=2.33.0)
31
30
  Requires-Dist: shortuuid (>=1.0.11)
32
31
  Requires-Dist: six (>=1.10)
33
32
  Requires-Dist: typing-extensions (>=4.2.0)
33
+ Requires-Dist: urllib3 (>=2.6.3)
34
34
  Description-Content-Type: text/markdown
35
35
 
36
36
  # Python SDK for Conductor
@@ -141,7 +141,7 @@ Create a `quickstart.py` with the following:
141
141
  ```python
142
142
  from conductor.client.automator.task_handler import TaskHandler
143
143
  from conductor.client.configuration.configuration import Configuration
144
- from conductor.client.orkes_clients import OrkesClients # works with OSS Conductor and Orkes Conductor
144
+ from conductor.client.orkes_clients import ConductorClients # OrkesClients is an alias for the same class
145
145
  from conductor.client.workflow.conductor_workflow import ConductorWorkflow
146
146
  from conductor.client.worker.worker_task import worker_task
147
147
 
@@ -156,7 +156,7 @@ def main():
156
156
  # Configure the SDK (reads CONDUCTOR_SERVER_URL / CONDUCTOR_AUTH_* from env).
157
157
  config = Configuration()
158
158
 
159
- clients = OrkesClients(configuration=config)
159
+ clients = ConductorClients(configuration=config)
160
160
  executor = clients.get_workflow_executor()
161
161
 
162
162
  # Build a workflow with the >> operator.
@@ -188,6 +188,8 @@ Run it:
188
188
  python quickstart.py
189
189
  ```
190
190
 
191
+ > **About `OrkesClients`:** This is the standard client factory for Conductor. The `Orkes` prefix reflects the implementing organization — it works identically with self-hosted OSS Conductor. No Orkes account or paid service is required.
192
+
191
193
  > ### Using Orkes Conductor / Remote Server?
192
194
  > Export your authentication credentials as well:
193
195
  >
@@ -355,7 +357,7 @@ with TaskHandler(configuration=config, metrics_settings=metrics, scan_for_annota
355
357
  curl http://localhost:8000/metrics
356
358
  ```
357
359
 
358
- See [examples/metrics_example.py](examples/metrics_example.py) and [METRICS.md](METRICS.md) for details on all tracked metrics.
360
+ Legacy metrics are emitted by default. Set `WORKER_CANONICAL_METRICS=true` before starting workers to use the canonical metric catalog. See [examples/metrics_example.py](examples/metrics_example.py) and [METRICS.md](METRICS.md) for the full legacy and canonical reference.
359
361
 
360
362
  ### Managing Workflow Executions
361
363
 
@@ -364,10 +366,10 @@ Full lifecycle control — start, execute, pause, resume, terminate, retry, rest
364
366
  ```python
365
367
  from conductor.client.configuration.configuration import Configuration
366
368
  from conductor.client.http.models import StartWorkflowRequest, RerunWorkflowRequest, TaskResult
367
- from conductor.client.orkes_clients import OrkesClients
369
+ from conductor.client.orkes_clients import ConductorClients
368
370
 
369
371
  config = Configuration()
370
- clients = OrkesClients(configuration=config)
372
+ clients = ConductorClients(configuration=config)
371
373
  workflow_client = clients.get_workflow_client()
372
374
  task_client = clients.get_task_client()
373
375
  executor = clients.get_workflow_executor()
@@ -525,6 +527,37 @@ Yes. Conductor ensures workflows complete reliably even in the face of infrastru
525
527
 
526
528
  No. While Conductor excels at asynchronous orchestration, it also supports synchronous workflow execution when immediate results are required.
527
529
 
530
+ **Why did `execute()` return `status: RUNNING` with no output?**
531
+
532
+ `execute()` blocks until the workflow finishes **or** `wait_for_seconds` elapses (default: 10 s),
533
+ whichever comes first. If it times out, you get `status='RUNNING'` — that is correct behavior,
534
+ not a bug.
535
+
536
+ The most common cause: your worker raised an exception. Conductor marks the task FAILED and
537
+ schedules a retry after `retryDelaySeconds` (default: **60 s**). The default 10 s wait expires
538
+ while the retry is pending, so `execute()` returns before the workflow completes.
539
+
540
+ **To fix**: increase `wait_for_seconds` to outlast the retry cycle:
541
+
542
+ ```python
543
+ # default retryDelaySeconds is 60 — wait long enough to cover one retry
544
+ run = executor.execute(name='my_workflow', version=1, workflow_input={...}, wait_for_seconds=70)
545
+ ```
546
+
547
+ **To debug** when a workflow is stuck:
548
+
549
+ ```python
550
+ # Inspect task statuses and failure reasons
551
+ wf = executor.get_workflow(run.workflow_id, include_tasks=True)
552
+ for task in wf.tasks:
553
+ if task.status in ('FAILED', 'FAILED_WITH_TERMINAL_ERROR'):
554
+ print(task.reference_task_name, task.reason_for_incompletion)
555
+ ```
556
+
557
+ You can also open the Conductor UI at `<server>/execution/<workflow_id>` — it shows each task's
558
+ status, retry count, and the worker exception message directly. Worker tracebacks are also logged
559
+ at ERROR level by the SDK in the `TaskHandler` process.
560
+
528
561
  **Do I need to use a Conductor-specific framework?**
529
562
 
530
563
  No. Conductor is language and framework agnostic. Use your preferred language and framework — the [SDKs](https://github.com/conductor-oss/conductor#conductor-sdks) provide native integration for Python, Java, JavaScript, Go, C#, and more.
@@ -106,7 +106,7 @@ Create a `quickstart.py` with the following:
106
106
  ```python
107
107
  from conductor.client.automator.task_handler import TaskHandler
108
108
  from conductor.client.configuration.configuration import Configuration
109
- from conductor.client.orkes_clients import OrkesClients # works with OSS Conductor and Orkes Conductor
109
+ from conductor.client.orkes_clients import ConductorClients # OrkesClients is an alias for the same class
110
110
  from conductor.client.workflow.conductor_workflow import ConductorWorkflow
111
111
  from conductor.client.worker.worker_task import worker_task
112
112
 
@@ -121,7 +121,7 @@ def main():
121
121
  # Configure the SDK (reads CONDUCTOR_SERVER_URL / CONDUCTOR_AUTH_* from env).
122
122
  config = Configuration()
123
123
 
124
- clients = OrkesClients(configuration=config)
124
+ clients = ConductorClients(configuration=config)
125
125
  executor = clients.get_workflow_executor()
126
126
 
127
127
  # Build a workflow with the >> operator.
@@ -153,6 +153,8 @@ Run it:
153
153
  python quickstart.py
154
154
  ```
155
155
 
156
+ > **About `OrkesClients`:** This is the standard client factory for Conductor. The `Orkes` prefix reflects the implementing organization — it works identically with self-hosted OSS Conductor. No Orkes account or paid service is required.
157
+
156
158
  > ### Using Orkes Conductor / Remote Server?
157
159
  > Export your authentication credentials as well:
158
160
  >
@@ -320,7 +322,7 @@ with TaskHandler(configuration=config, metrics_settings=metrics, scan_for_annota
320
322
  curl http://localhost:8000/metrics
321
323
  ```
322
324
 
323
- See [examples/metrics_example.py](examples/metrics_example.py) and [METRICS.md](METRICS.md) for details on all tracked metrics.
325
+ Legacy metrics are emitted by default. Set `WORKER_CANONICAL_METRICS=true` before starting workers to use the canonical metric catalog. See [examples/metrics_example.py](examples/metrics_example.py) and [METRICS.md](METRICS.md) for the full legacy and canonical reference.
324
326
 
325
327
  ### Managing Workflow Executions
326
328
 
@@ -329,10 +331,10 @@ Full lifecycle control — start, execute, pause, resume, terminate, retry, rest
329
331
  ```python
330
332
  from conductor.client.configuration.configuration import Configuration
331
333
  from conductor.client.http.models import StartWorkflowRequest, RerunWorkflowRequest, TaskResult
332
- from conductor.client.orkes_clients import OrkesClients
334
+ from conductor.client.orkes_clients import ConductorClients
333
335
 
334
336
  config = Configuration()
335
- clients = OrkesClients(configuration=config)
337
+ clients = ConductorClients(configuration=config)
336
338
  workflow_client = clients.get_workflow_client()
337
339
  task_client = clients.get_task_client()
338
340
  executor = clients.get_workflow_executor()
@@ -490,6 +492,37 @@ Yes. Conductor ensures workflows complete reliably even in the face of infrastru
490
492
 
491
493
  No. While Conductor excels at asynchronous orchestration, it also supports synchronous workflow execution when immediate results are required.
492
494
 
495
+ **Why did `execute()` return `status: RUNNING` with no output?**
496
+
497
+ `execute()` blocks until the workflow finishes **or** `wait_for_seconds` elapses (default: 10 s),
498
+ whichever comes first. If it times out, you get `status='RUNNING'` — that is correct behavior,
499
+ not a bug.
500
+
501
+ The most common cause: your worker raised an exception. Conductor marks the task FAILED and
502
+ schedules a retry after `retryDelaySeconds` (default: **60 s**). The default 10 s wait expires
503
+ while the retry is pending, so `execute()` returns before the workflow completes.
504
+
505
+ **To fix**: increase `wait_for_seconds` to outlast the retry cycle:
506
+
507
+ ```python
508
+ # default retryDelaySeconds is 60 — wait long enough to cover one retry
509
+ run = executor.execute(name='my_workflow', version=1, workflow_input={...}, wait_for_seconds=70)
510
+ ```
511
+
512
+ **To debug** when a workflow is stuck:
513
+
514
+ ```python
515
+ # Inspect task statuses and failure reasons
516
+ wf = executor.get_workflow(run.workflow_id, include_tasks=True)
517
+ for task in wf.tasks:
518
+ if task.status in ('FAILED', 'FAILED_WITH_TERMINAL_ERROR'):
519
+ print(task.reference_task_name, task.reason_for_incompletion)
520
+ ```
521
+
522
+ You can also open the Conductor UI at `<server>/execution/<workflow_id>` — it shows each task's
523
+ status, retry count, and the worker exception message directly. Worker tracebacks are also logged
524
+ at ERROR level by the SDK in the `TaskHandler` process.
525
+
493
526
  **Do I need to use a Conductor-specific framework?**
494
527
 
495
528
  No. Conductor is language and framework agnostic. Use your preferred language and framework — the [SDKs](https://github.com/conductor-oss/conductor#conductor-sdks) provide native integration for Python, Java, JavaScript, Go, C#, and more.
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "conductor-python"
7
- version = "1.3.11" # Do not change! Placeholder. Real version injected during build (edited)
7
+ version = "1.5.0" # Do not change! Placeholder. Real version injected during build (edited)
8
8
  description = "Python SDK for working with https://github.com/conductor-oss/conductor"
9
9
  authors = ["Orkes <developers@orkes.io>"]
10
10
  license = "Apache-2.0"
@@ -23,11 +23,11 @@ classifiers = [
23
23
  ]
24
24
 
25
25
  [tool.poetry.dependencies]
26
- python = ">=3.9"
26
+ python = ">=3.10"
27
27
  certifi = ">=14.05.14"
28
28
  prometheus-client = ">=0.13.1"
29
29
  six = ">=1.10"
30
- requests = ">=2.31.0"
30
+ requests = ">=2.33.0"
31
31
  typing-extensions = ">=4.2.0"
32
32
  astor = ">=0.8.1"
33
33
  shortuuid = ">=1.0.11"
@@ -36,6 +36,7 @@ deprecated = ">=1.2.14"
36
36
  python-dateutil = "^2.8.2"
37
37
  httpx = {version = ">=0.26.0", extras = ["http2"]}
38
38
  h2 = ">=4.1.0"
39
+ urllib3 = ">=2.6.3"
39
40
 
40
41
  [tool.poetry.group.dev.dependencies]
41
42
  pylint = ">=2.17.5"
@@ -44,10 +45,13 @@ pytest-cov = ">=4.1.0"
44
45
  ruff = "^0.12.0"
45
46
  pre-commit = "^4.2.0"
46
47
  setuptools = "^80.9.0"
47
- pytest = "^8.4.1"
48
+ pytest = "^9.0.3"
49
+ pygments = ">=2.20.0"
50
+ filelock = ">=3.20.3"
51
+ virtualenv = ">=20.36.1"
48
52
 
49
53
  [tool.ruff]
50
- target-version = "py39"
54
+ target-version = "py310"
51
55
  line-length = 100
52
56
  src = ["src"]
53
57
  extend-exclude = [
@@ -3,7 +3,7 @@
3
3
  from conductor.client.configuration.configuration import Configuration
4
4
  from conductor.client.automator.task_handler import TaskHandler
5
5
  from conductor.client.automator.task_runner import TaskRunner
6
- from conductor.client.orkes_clients import OrkesClients
6
+ from conductor.client.orkes_clients import OrkesClients, ConductorClients
7
7
  from conductor.client.workflow.conductor_workflow import ConductorWorkflow
8
8
  from conductor.client.workflow.executor.workflow_executor import WorkflowExecutor
9
9
  from conductor.client.worker.worker_task import worker_task
@@ -18,6 +18,7 @@ __all__ = [
18
18
  "TaskHandler",
19
19
  "TaskRunner",
20
20
  "OrkesClients",
21
+ "ConductorClients",
21
22
  "ConductorWorkflow",
22
23
  "WorkflowExecutor",
23
24
  "worker_task",
@@ -27,7 +27,7 @@ from conductor.client.http.models.schema_def import SchemaDef, SchemaType
27
27
  from conductor.client.http.rest import AuthorizationException, ApiException
28
28
  from conductor.client.orkes.orkes_metadata_client import OrkesMetadataClient
29
29
  from conductor.client.orkes.orkes_schema_client import OrkesSchemaClient
30
- from conductor.client.telemetry.metrics_collector import MetricsCollector
30
+ from conductor.client.telemetry.metrics_factory import create_metrics_collector
31
31
  from conductor.client.worker.worker_interface import WorkerInterface
32
32
  from conductor.client.worker.worker_config import resolve_worker_config, get_worker_config_oneline
33
33
  from conductor.client.worker.exception import NonRetryableException
@@ -88,7 +88,7 @@ class AsyncTaskRunner:
88
88
 
89
89
  self.metrics_collector = None
90
90
  if metrics_settings is not None:
91
- self.metrics_collector = MetricsCollector(
91
+ self.metrics_collector = create_metrics_collector(
92
92
  metrics_settings
93
93
  )
94
94
  # Register metrics collector as event listener
@@ -863,6 +863,7 @@ class AsyncTaskRunner:
863
863
  if attempt > 0:
864
864
  # Exponential backoff: [10s, 20s, 30s] before retry
865
865
  await asyncio.sleep(attempt * 10)
866
+ update_start = time.time()
866
867
  try:
867
868
  if self._use_update_v2:
868
869
  next_task = await self.async_task_client.update_task_v2(body=task_result)
@@ -873,6 +874,10 @@ class AsyncTaskRunner:
873
874
  task_definition_name,
874
875
  next_task.task_id if next_task else None
875
876
  )
877
+ if self.metrics_collector is not None:
878
+ self.metrics_collector.record_task_update_time(
879
+ task_definition_name, time.time() - update_start, status="SUCCESS"
880
+ )
876
881
  return next_task
877
882
  else:
878
883
  await self.async_task_client.update_task(body=task_result)
@@ -882,6 +887,10 @@ class AsyncTaskRunner:
882
887
  task_result.workflow_instance_id,
883
888
  task_definition_name,
884
889
  )
890
+ if self.metrics_collector is not None:
891
+ self.metrics_collector.record_task_update_time(
892
+ task_definition_name, time.time() - update_start, status="SUCCESS"
893
+ )
885
894
  return None
886
895
  except ApiException as e:
887
896
  if e.status in (404, 405) and self._use_update_v2:
@@ -895,12 +904,19 @@ class AsyncTaskRunner:
895
904
  # Retry immediately with v1
896
905
  try:
897
906
  await self.async_task_client.update_task(body=task_result)
907
+ if self.metrics_collector is not None:
908
+ self.metrics_collector.record_task_update_time(
909
+ task_definition_name, time.time() - update_start, status="SUCCESS"
910
+ )
898
911
  return None
899
912
  except Exception as fallback_e:
900
913
  last_exception = fallback_e
901
914
  continue
902
915
  last_exception = e
903
916
  if self.metrics_collector is not None:
917
+ self.metrics_collector.record_task_update_time(
918
+ task_definition_name, time.time() - update_start, status="FAILURE"
919
+ )
904
920
  self.metrics_collector.increment_task_update_error(
905
921
  task_definition_name, type(e)
906
922
  )
@@ -917,6 +933,9 @@ class AsyncTaskRunner:
917
933
  except Exception as e:
918
934
  last_exception = e
919
935
  if self.metrics_collector is not None:
936
+ self.metrics_collector.record_task_update_time(
937
+ task_definition_name, time.time() - update_start, status="FAILURE"
938
+ )
920
939
  self.metrics_collector.increment_task_update_error(
921
940
  task_definition_name, type(e)
922
941
  )
@@ -4,10 +4,11 @@ import importlib
4
4
  import inspect
5
5
  import logging
6
6
  import os
7
+ import pickle
7
8
  import signal
8
9
  import threading
9
10
  import time
10
- from multiprocessing import Process, freeze_support, Queue, set_start_method
11
+ from multiprocessing import Process, freeze_support, Queue, set_start_method, get_start_method
11
12
  from sys import platform
12
13
  from typing import List, Optional, Any, Dict
13
14
 
@@ -18,7 +19,7 @@ from conductor.client.configuration.settings.metrics_settings import MetricsSett
18
19
  from conductor.client.event.task_runner_events import TaskRunnerEvent
19
20
  from conductor.client.event.sync_event_dispatcher import SyncEventDispatcher
20
21
  from conductor.client.event.sync_listener_register import register_task_runner_listener
21
- from conductor.client.telemetry.metrics_collector import MetricsCollector
22
+ from conductor.client.telemetry.metrics_collector_base import MetricsCollectorBase
22
23
  from conductor.client.telemetry.model.metric_documentation import MetricDocumentation
23
24
  from conductor.client.telemetry.model.metric_label import MetricLabel
24
25
  from conductor.client.telemetry.model.metric_name import MetricName
@@ -33,13 +34,37 @@ logger = logging.getLogger(
33
34
  )
34
35
 
35
36
  _decorated_functions = {}
37
+ _VALID_MP_START_METHODS = {"spawn", "fork", "forkserver"}
36
38
  _mp_fork_set = False
37
39
  if not _mp_fork_set:
38
40
  try:
39
- if platform == "win32":
40
- set_start_method("spawn")
41
- else:
42
- set_start_method("fork")
41
+ # Default start method: "spawn" on every platform.
42
+ #
43
+ # fork() is fundamentally unsafe in a process that holds native
44
+ # framework state or non-main threads:
45
+ # - macOS: Apple frameworks (CFNetwork, Security, libdispatch) may
46
+ # SIGSEGV in forked children, producing silently-restarting worker
47
+ # processes with exitcode=-11. CPython switched its own macOS
48
+ # default to spawn in 3.8 for the same reason (bpo-33725).
49
+ # - all POSIX: forking while another thread holds a lock (e.g. the
50
+ # prometheus_client module-level lock, or the TaskHandler monitor
51
+ # thread restarting a worker) leaves that lock permanently held in
52
+ # the child -> silent deadlock.
53
+ # Workers (including the @worker_task decorator path) are pickle-safe,
54
+ # so spawn works everywhere. Deployments that rely on fork's
55
+ # copy-on-write inheritance can opt back in with
56
+ # CONDUCTOR_MP_START_METHOD=fork (re-exposing the hazards above).
57
+ # NOTE: spawn requires the standard `if __name__ == "__main__":` guard
58
+ # in the entrypoint script.
59
+ _default_method = "spawn"
60
+ _method = os.environ.get("CONDUCTOR_MP_START_METHOD", "").strip().lower() or _default_method
61
+ if _method not in _VALID_MP_START_METHODS:
62
+ logger.warning(
63
+ "Ignoring invalid CONDUCTOR_MP_START_METHOD=%r; falling back to %r",
64
+ _method, _default_method,
65
+ )
66
+ _method = _default_method
67
+ set_start_method(_method)
43
68
  _mp_fork_set = True
44
69
  except Exception as e:
45
70
  logger.info("error when setting multiprocessing.set_start_method - maybe the context is set %s", e.args)
@@ -221,11 +246,11 @@ class TaskHandler:
221
246
  self._configuration = configuration
222
247
  self._metrics_settings = metrics_settings
223
248
 
224
- # Set prometheus multiprocess directory BEFORE any worker processes start
225
- # This must be done before prometheus_client is imported in worker processes
249
+ # Set PROMETHEUS_MULTIPROC_DIR BEFORE any worker processes start.
250
+ # MetricsSettings resolves the subdirectory eagerly at construction.
226
251
  if metrics_settings is not None:
227
- os.environ["PROMETHEUS_MULTIPROC_DIR"] = metrics_settings.directory
228
- logger.info(f"Set PROMETHEUS_MULTIPROC_DIR={metrics_settings.directory}")
252
+ os.environ["PROMETHEUS_MULTIPROC_DIR"] = metrics_settings.metrics_directory
253
+ logger.info(f"Set PROMETHEUS_MULTIPROC_DIR={metrics_settings.metrics_directory}")
229
254
 
230
255
  # Store event listeners to pass to each worker process
231
256
  self.event_listeners = event_listeners or []
@@ -330,8 +355,26 @@ class TaskHandler:
330
355
  logger.info("Starting worker processes...")
331
356
  freeze_support()
332
357
  self._monitor_stop_event.clear()
333
- self.__start_task_runner_processes()
334
- self.__start_metrics_provider_process()
358
+ try:
359
+ self.__start_task_runner_processes()
360
+ self.__start_metrics_provider_process()
361
+ except (TypeError, pickle.PicklingError, AttributeError) as e:
362
+ # Under the 'spawn'/'forkserver' start methods, Process arguments
363
+ # are pickled at start(); unpicklable state fails here. Clean up
364
+ # everything already started - otherwise the non-daemon logger
365
+ # subprocess keeps the interpreter alive forever after the
366
+ # exception (observed as a hang after "cannot pickle
367
+ # '_thread.lock' object").
368
+ logger.error(
369
+ "Failed to start worker processes with start method %r: %s. "
370
+ "Workers must be defined at module level (not nested inside "
371
+ "functions), and configuration, metrics_settings and "
372
+ "event_listeners must be picklable. "
373
+ "See https://github.com/conductor-oss/conductor-python/issues/264",
374
+ get_start_method(allow_none=True), e,
375
+ )
376
+ self.stop_processes()
377
+ raise
335
378
  self.__start_monitor_thread()
336
379
  logger.info("Started all processes")
337
380
 
@@ -345,7 +388,7 @@ class TaskHandler:
345
388
  self.metrics_provider_process = None
346
389
  return
347
390
  self.metrics_provider_process = Process(
348
- target=MetricsCollector.provide_metrics,
391
+ target=MetricsCollectorBase.provide_metrics,
349
392
  args=(metrics_settings,)
350
393
  )
351
394
  logger.info("Created MetricsProvider process")
@@ -434,6 +477,21 @@ class TaskHandler:
434
477
  worker = self.workers[i] if i < len(self.workers) else None
435
478
  worker_name = worker.get_task_definition_name() if worker is not None else f"worker[{i}]"
436
479
  logger.warning("Worker process exited (worker=%s, pid=%s, exitcode=%s)", worker_name, process.pid, exitcode)
480
+ if exitcode < 0:
481
+ # Negative exitcode == killed by signal (e.g. -11 is
482
+ # SIGSEGV). Under the 'fork' start method this is the
483
+ # classic symptom of fork-unsafe native libraries in the
484
+ # parent (Apple frameworks on macOS, numpy/Accelerate,
485
+ # grpc, ...).
486
+ logger.warning(
487
+ "Worker process %s was killed by signal %s. If this "
488
+ "repeats on every restart, the process is likely "
489
+ "crashing at startup: use the 'spawn' start method "
490
+ "(CONDUCTOR_MP_START_METHOD=spawn, the default) and "
491
+ "set PYTHONFAULTHANDLER=1 to capture the crashing "
492
+ "stack trace.",
493
+ worker_name, -exitcode,
494
+ )
437
495
  if not self.restart_on_failure:
438
496
  continue
439
497
  self.__restart_worker_process(i)
@@ -30,7 +30,7 @@ from conductor.client.http.models.schema_def import SchemaDef, SchemaType
30
30
  from conductor.client.http.rest import AuthorizationException, ApiException
31
31
  from conductor.client.orkes.orkes_metadata_client import OrkesMetadataClient
32
32
  from conductor.client.orkes.orkes_schema_client import OrkesSchemaClient
33
- from conductor.client.telemetry.metrics_collector import MetricsCollector
33
+ from conductor.client.telemetry.metrics_factory import create_metrics_collector
34
34
  from conductor.client.worker.worker import ASYNC_TASK_RUNNING
35
35
  from conductor.client.worker.worker_interface import WorkerInterface
36
36
  from conductor.client.worker.worker_config import resolve_worker_config, get_worker_config_oneline
@@ -69,7 +69,7 @@ class TaskRunner:
69
69
 
70
70
  self.metrics_collector = None
71
71
  if metrics_settings is not None:
72
- self.metrics_collector = MetricsCollector(
72
+ self.metrics_collector = create_metrics_collector(
73
73
  metrics_settings
74
74
  )
75
75
  # Register metrics collector as event listener
@@ -972,6 +972,7 @@ class TaskRunner:
972
972
  if attempt > 0:
973
973
  # Exponential backoff: [10s, 20s, 30s] before retry
974
974
  time.sleep(attempt * 10)
975
+ update_start = time.time()
975
976
  try:
976
977
  if self._use_update_v2:
977
978
  next_task = self.task_client.update_task_v2(body=task_result)
@@ -982,6 +983,10 @@ class TaskRunner:
982
983
  task_definition_name,
983
984
  next_task.task_id if next_task else None
984
985
  )
986
+ if self.metrics_collector is not None:
987
+ self.metrics_collector.record_task_update_time(
988
+ task_definition_name, time.time() - update_start, status="SUCCESS"
989
+ )
985
990
  return next_task
986
991
  else:
987
992
  self.task_client.update_task(body=task_result)
@@ -991,6 +996,10 @@ class TaskRunner:
991
996
  task_result.workflow_instance_id,
992
997
  task_definition_name,
993
998
  )
999
+ if self.metrics_collector is not None:
1000
+ self.metrics_collector.record_task_update_time(
1001
+ task_definition_name, time.time() - update_start, status="SUCCESS"
1002
+ )
994
1003
  return None
995
1004
  except ApiException as e:
996
1005
  if e.status in (404, 405) and self._use_update_v2:
@@ -1004,12 +1013,19 @@ class TaskRunner:
1004
1013
  # Retry immediately with v1
1005
1014
  try:
1006
1015
  self.task_client.update_task(body=task_result)
1016
+ if self.metrics_collector is not None:
1017
+ self.metrics_collector.record_task_update_time(
1018
+ task_definition_name, time.time() - update_start, status="SUCCESS"
1019
+ )
1007
1020
  return None
1008
1021
  except Exception as fallback_e:
1009
1022
  last_exception = fallback_e
1010
1023
  continue
1011
1024
  last_exception = e
1012
1025
  if self.metrics_collector is not None:
1026
+ self.metrics_collector.record_task_update_time(
1027
+ task_definition_name, time.time() - update_start, status="FAILURE"
1028
+ )
1013
1029
  self.metrics_collector.increment_task_update_error(
1014
1030
  task_definition_name, type(e)
1015
1031
  )
@@ -1044,6 +1060,9 @@ class TaskRunner:
1044
1060
  except Exception as e:
1045
1061
  last_exception = e
1046
1062
  if self.metrics_collector is not None:
1063
+ self.metrics_collector.record_task_update_time(
1064
+ task_definition_name, time.time() - update_start, status="FAILURE"
1065
+ )
1047
1066
  self.metrics_collector.increment_task_update_error(
1048
1067
  task_definition_name, type(e)
1049
1068
  )