hatchet-sdk 0.47.1__py3-none-any.whl → 1.0.0a1__py3-none-any.whl
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.
Potentially problematic release.
This version of hatchet-sdk might be problematic. Click here for more details.
- hatchet_sdk/__init__.py +45 -25
- hatchet_sdk/client.py +19 -94
- hatchet_sdk/clients/admin.py +309 -389
- hatchet_sdk/clients/dispatcher/action_listener.py +131 -109
- hatchet_sdk/clients/dispatcher/dispatcher.py +39 -37
- hatchet_sdk/clients/durable_event_listener.py +327 -0
- hatchet_sdk/clients/event_ts.py +23 -10
- hatchet_sdk/clients/events.py +96 -99
- hatchet_sdk/clients/rest/__init__.py +35 -0
- hatchet_sdk/clients/rest/api/__init__.py +2 -0
- hatchet_sdk/clients/rest/api/log_api.py +258 -0
- hatchet_sdk/clients/rest/api/task_api.py +2200 -0
- hatchet_sdk/clients/rest/api/workflow_runs_api.py +1274 -116
- hatchet_sdk/clients/rest/api_client.py +1 -1
- hatchet_sdk/clients/rest/configuration.py +8 -1
- hatchet_sdk/clients/rest/exceptions.py +21 -0
- hatchet_sdk/clients/rest/models/__init__.py +33 -0
- hatchet_sdk/clients/rest/models/tenant.py +4 -0
- hatchet_sdk/clients/rest/models/tenant_version.py +37 -0
- hatchet_sdk/clients/rest/models/update_tenant_request.py +7 -0
- hatchet_sdk/clients/rest/models/v1_cancel_task_request.py +104 -0
- hatchet_sdk/clients/rest/models/v1_dag_children.py +102 -0
- hatchet_sdk/clients/rest/models/v1_log_line.py +94 -0
- hatchet_sdk/clients/rest/models/v1_log_line_level.py +39 -0
- hatchet_sdk/clients/rest/models/v1_log_line_list.py +110 -0
- hatchet_sdk/clients/rest/models/v1_replay_task_request.py +104 -0
- hatchet_sdk/clients/rest/models/v1_task.py +174 -0
- hatchet_sdk/clients/rest/models/v1_task_event.py +118 -0
- hatchet_sdk/clients/rest/models/v1_task_event_list.py +110 -0
- hatchet_sdk/clients/rest/models/v1_task_event_type.py +55 -0
- hatchet_sdk/clients/rest/models/v1_task_filter.py +106 -0
- hatchet_sdk/clients/rest/models/v1_task_point_metric.py +92 -0
- hatchet_sdk/clients/rest/models/v1_task_point_metrics.py +100 -0
- hatchet_sdk/clients/rest/models/v1_task_run_metric.py +88 -0
- hatchet_sdk/clients/rest/models/v1_task_run_status.py +40 -0
- hatchet_sdk/clients/rest/models/v1_task_status.py +40 -0
- hatchet_sdk/clients/rest/models/v1_task_summary.py +228 -0
- hatchet_sdk/clients/rest/models/v1_task_summary_list.py +110 -0
- hatchet_sdk/clients/rest/models/v1_trigger_workflow_run_request.py +95 -0
- hatchet_sdk/clients/rest/models/v1_workflow_run.py +171 -0
- hatchet_sdk/clients/rest/models/v1_workflow_run_details.py +145 -0
- hatchet_sdk/clients/rest/models/v1_workflow_run_display_name.py +98 -0
- hatchet_sdk/clients/rest/models/v1_workflow_run_display_name_list.py +114 -0
- hatchet_sdk/clients/rest/models/v1_workflow_type.py +37 -0
- hatchet_sdk/clients/rest/models/workflow_run_shape_item_for_workflow_run_details.py +104 -0
- hatchet_sdk/clients/rest/rest.py +37 -26
- hatchet_sdk/clients/rest/tenacity_utils.py +1 -1
- hatchet_sdk/clients/rest_client.py +153 -116
- hatchet_sdk/clients/run_event_listener.py +65 -60
- hatchet_sdk/clients/workflow_listener.py +75 -66
- hatchet_sdk/config.py +117 -0
- hatchet_sdk/connection.py +27 -13
- hatchet_sdk/context/__init__.py +0 -1
- hatchet_sdk/context/context.py +118 -280
- hatchet_sdk/contracts/dispatcher_pb2_grpc.py +1 -1
- hatchet_sdk/contracts/events_pb2.py +2 -2
- hatchet_sdk/contracts/events_pb2_grpc.py +1 -1
- hatchet_sdk/contracts/v1/dispatcher_pb2.py +36 -0
- hatchet_sdk/contracts/v1/dispatcher_pb2.pyi +38 -0
- hatchet_sdk/contracts/v1/dispatcher_pb2_grpc.py +145 -0
- hatchet_sdk/contracts/v1/shared/condition_pb2.py +39 -0
- hatchet_sdk/contracts/v1/shared/condition_pb2.pyi +72 -0
- hatchet_sdk/contracts/v1/shared/condition_pb2_grpc.py +29 -0
- hatchet_sdk/contracts/v1/workflows_pb2.py +67 -0
- hatchet_sdk/contracts/v1/workflows_pb2.pyi +228 -0
- hatchet_sdk/contracts/v1/workflows_pb2_grpc.py +234 -0
- hatchet_sdk/contracts/workflows_pb2_grpc.py +1 -1
- hatchet_sdk/features/cron.py +43 -57
- hatchet_sdk/features/scheduled.py +60 -74
- hatchet_sdk/hatchet.py +491 -218
- hatchet_sdk/labels.py +4 -6
- hatchet_sdk/metadata.py +1 -1
- hatchet_sdk/opentelemetry/instrumentor.py +17 -18
- hatchet_sdk/rate_limit.py +40 -55
- hatchet_sdk/runnables/contextvars.py +12 -0
- hatchet_sdk/runnables/standalone.py +194 -0
- hatchet_sdk/runnables/task.py +144 -0
- hatchet_sdk/runnables/types.py +138 -0
- hatchet_sdk/runnables/workflow.py +764 -0
- hatchet_sdk/token.py +13 -9
- hatchet_sdk/utils/aio_utils.py +0 -119
- hatchet_sdk/utils/proto_enums.py +47 -0
- hatchet_sdk/utils/timedelta_to_expression.py +23 -0
- hatchet_sdk/utils/typing.py +10 -2
- hatchet_sdk/v0/__init__.py +251 -0
- hatchet_sdk/v0/client.py +119 -0
- hatchet_sdk/v0/clients/admin.py +541 -0
- hatchet_sdk/v0/clients/dispatcher/action_listener.py +422 -0
- hatchet_sdk/v0/clients/dispatcher/dispatcher.py +204 -0
- hatchet_sdk/v0/clients/event_ts.py +28 -0
- hatchet_sdk/v0/clients/events.py +182 -0
- hatchet_sdk/v0/clients/rest/__init__.py +307 -0
- hatchet_sdk/v0/clients/rest/api/__init__.py +19 -0
- hatchet_sdk/v0/clients/rest/api/api_token_api.py +858 -0
- hatchet_sdk/v0/clients/rest/api/default_api.py +2259 -0
- hatchet_sdk/v0/clients/rest/api/event_api.py +2548 -0
- hatchet_sdk/v0/clients/rest/api/github_api.py +331 -0
- hatchet_sdk/v0/clients/rest/api/healthcheck_api.py +483 -0
- hatchet_sdk/v0/clients/rest/api/log_api.py +449 -0
- hatchet_sdk/v0/clients/rest/api/metadata_api.py +728 -0
- hatchet_sdk/v0/clients/rest/api/rate_limits_api.py +423 -0
- hatchet_sdk/v0/clients/rest/api/slack_api.py +577 -0
- hatchet_sdk/v0/clients/rest/api/sns_api.py +872 -0
- hatchet_sdk/v0/clients/rest/api/step_run_api.py +2202 -0
- hatchet_sdk/v0/clients/rest/api/tenant_api.py +4430 -0
- hatchet_sdk/v0/clients/rest/api/user_api.py +2888 -0
- hatchet_sdk/v0/clients/rest/api/worker_api.py +858 -0
- hatchet_sdk/v0/clients/rest/api/workflow_api.py +6312 -0
- hatchet_sdk/v0/clients/rest/api/workflow_run_api.py +1932 -0
- hatchet_sdk/v0/clients/rest/api/workflow_runs_api.py +610 -0
- hatchet_sdk/v0/clients/rest/api_client.py +759 -0
- hatchet_sdk/v0/clients/rest/api_response.py +22 -0
- hatchet_sdk/v0/clients/rest/configuration.py +611 -0
- hatchet_sdk/v0/clients/rest/exceptions.py +200 -0
- hatchet_sdk/v0/clients/rest/models/__init__.py +274 -0
- hatchet_sdk/v0/clients/rest/models/accept_invite_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/api_error.py +102 -0
- hatchet_sdk/v0/clients/rest/models/api_errors.py +100 -0
- hatchet_sdk/v0/clients/rest/models/api_meta.py +144 -0
- hatchet_sdk/v0/clients/rest/models/api_meta_auth.py +85 -0
- hatchet_sdk/v0/clients/rest/models/api_meta_integration.py +88 -0
- hatchet_sdk/v0/clients/rest/models/api_meta_posthog.py +90 -0
- hatchet_sdk/v0/clients/rest/models/api_resource_meta.py +98 -0
- hatchet_sdk/v0/clients/rest/models/api_token.py +105 -0
- hatchet_sdk/v0/clients/rest/models/bulk_create_event_request.py +100 -0
- hatchet_sdk/v0/clients/rest/models/bulk_create_event_response.py +110 -0
- hatchet_sdk/v0/clients/rest/models/cancel_event_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/cancel_step_run_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/concurrency_limit_strategy.py +39 -0
- hatchet_sdk/v0/clients/rest/models/create_api_token_request.py +92 -0
- hatchet_sdk/v0/clients/rest/models/create_api_token_response.py +83 -0
- hatchet_sdk/v0/clients/rest/models/create_cron_workflow_trigger_request.py +98 -0
- hatchet_sdk/v0/clients/rest/models/create_event_request.py +95 -0
- hatchet_sdk/v0/clients/rest/models/create_pull_request_from_step_run.py +83 -0
- hatchet_sdk/v0/clients/rest/models/create_sns_integration_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/create_tenant_alert_email_group_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/create_tenant_invite_request.py +86 -0
- hatchet_sdk/v0/clients/rest/models/create_tenant_request.py +84 -0
- hatchet_sdk/v0/clients/rest/models/cron_workflows.py +131 -0
- hatchet_sdk/v0/clients/rest/models/cron_workflows_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/cron_workflows_method.py +37 -0
- hatchet_sdk/v0/clients/rest/models/cron_workflows_order_by_field.py +37 -0
- hatchet_sdk/v0/clients/rest/models/event.py +143 -0
- hatchet_sdk/v0/clients/rest/models/event_data.py +83 -0
- hatchet_sdk/v0/clients/rest/models/event_key_list.py +98 -0
- hatchet_sdk/v0/clients/rest/models/event_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/event_order_by_direction.py +37 -0
- hatchet_sdk/v0/clients/rest/models/event_order_by_field.py +36 -0
- hatchet_sdk/v0/clients/rest/models/event_update_cancel200_response.py +85 -0
- hatchet_sdk/v0/clients/rest/models/event_workflow_run_summary.py +116 -0
- hatchet_sdk/v0/clients/rest/models/events.py +110 -0
- hatchet_sdk/v0/clients/rest/models/get_step_run_diff_response.py +100 -0
- hatchet_sdk/v0/clients/rest/models/github_app_installation.py +107 -0
- hatchet_sdk/v0/clients/rest/models/github_branch.py +86 -0
- hatchet_sdk/v0/clients/rest/models/github_repo.py +86 -0
- hatchet_sdk/v0/clients/rest/models/info_get_version200_response.py +83 -0
- hatchet_sdk/v0/clients/rest/models/job.py +132 -0
- hatchet_sdk/v0/clients/rest/models/job_run.py +176 -0
- hatchet_sdk/v0/clients/rest/models/job_run_status.py +41 -0
- hatchet_sdk/v0/clients/rest/models/link_github_repository_request.py +106 -0
- hatchet_sdk/v0/clients/rest/models/list_api_tokens_response.py +110 -0
- hatchet_sdk/v0/clients/rest/models/list_github_app_installations_response.py +112 -0
- hatchet_sdk/v0/clients/rest/models/list_pull_requests_response.py +100 -0
- hatchet_sdk/v0/clients/rest/models/list_slack_webhooks.py +110 -0
- hatchet_sdk/v0/clients/rest/models/list_sns_integrations.py +110 -0
- hatchet_sdk/v0/clients/rest/models/log_line.py +94 -0
- hatchet_sdk/v0/clients/rest/models/log_line_level.py +39 -0
- hatchet_sdk/v0/clients/rest/models/log_line_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/log_line_order_by_direction.py +37 -0
- hatchet_sdk/v0/clients/rest/models/log_line_order_by_field.py +36 -0
- hatchet_sdk/v0/clients/rest/models/pagination_response.py +95 -0
- hatchet_sdk/v0/clients/rest/models/pull_request.py +112 -0
- hatchet_sdk/v0/clients/rest/models/pull_request_state.py +37 -0
- hatchet_sdk/v0/clients/rest/models/queue_metrics.py +97 -0
- hatchet_sdk/v0/clients/rest/models/rate_limit.py +117 -0
- hatchet_sdk/v0/clients/rest/models/rate_limit_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_direction.py +37 -0
- hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_field.py +38 -0
- hatchet_sdk/v0/clients/rest/models/recent_step_runs.py +118 -0
- hatchet_sdk/v0/clients/rest/models/reject_invite_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/replay_event_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_response.py +100 -0
- hatchet_sdk/v0/clients/rest/models/rerun_step_run_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/schedule_workflow_run_request.py +92 -0
- hatchet_sdk/v0/clients/rest/models/scheduled_run_status.py +42 -0
- hatchet_sdk/v0/clients/rest/models/scheduled_workflows.py +149 -0
- hatchet_sdk/v0/clients/rest/models/scheduled_workflows_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/scheduled_workflows_method.py +37 -0
- hatchet_sdk/v0/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
- hatchet_sdk/v0/clients/rest/models/semaphore_slots.py +113 -0
- hatchet_sdk/v0/clients/rest/models/slack_webhook.py +127 -0
- hatchet_sdk/v0/clients/rest/models/sns_integration.py +114 -0
- hatchet_sdk/v0/clients/rest/models/step.py +123 -0
- hatchet_sdk/v0/clients/rest/models/step_run.py +202 -0
- hatchet_sdk/v0/clients/rest/models/step_run_archive.py +142 -0
- hatchet_sdk/v0/clients/rest/models/step_run_archive_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/step_run_diff.py +91 -0
- hatchet_sdk/v0/clients/rest/models/step_run_event.py +122 -0
- hatchet_sdk/v0/clients/rest/models/step_run_event_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/step_run_event_reason.py +52 -0
- hatchet_sdk/v0/clients/rest/models/step_run_event_severity.py +38 -0
- hatchet_sdk/v0/clients/rest/models/step_run_status.py +44 -0
- hatchet_sdk/v0/clients/rest/models/tenant.py +118 -0
- hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group.py +98 -0
- hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group_list.py +112 -0
- hatchet_sdk/v0/clients/rest/models/tenant_alerting_settings.py +143 -0
- hatchet_sdk/v0/clients/rest/models/tenant_invite.py +120 -0
- hatchet_sdk/v0/clients/rest/models/tenant_invite_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/tenant_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/tenant_member.py +123 -0
- hatchet_sdk/v0/clients/rest/models/tenant_member_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/tenant_member_role.py +38 -0
- hatchet_sdk/v0/clients/rest/models/tenant_queue_metrics.py +116 -0
- hatchet_sdk/v0/clients/rest/models/tenant_resource.py +40 -0
- hatchet_sdk/v0/clients/rest/models/tenant_resource_limit.py +135 -0
- hatchet_sdk/v0/clients/rest/models/tenant_resource_policy.py +102 -0
- hatchet_sdk/v0/clients/rest/models/tenant_step_run_queue_metrics.py +83 -0
- hatchet_sdk/v0/clients/rest/models/trigger_workflow_run_request.py +91 -0
- hatchet_sdk/v0/clients/rest/models/update_tenant_alert_email_group_request.py +83 -0
- hatchet_sdk/v0/clients/rest/models/update_tenant_invite_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/update_tenant_request.py +137 -0
- hatchet_sdk/v0/clients/rest/models/update_worker_request.py +87 -0
- hatchet_sdk/v0/clients/rest/models/user.py +126 -0
- hatchet_sdk/v0/clients/rest/models/user_change_password_request.py +88 -0
- hatchet_sdk/v0/clients/rest/models/user_login_request.py +86 -0
- hatchet_sdk/v0/clients/rest/models/user_register_request.py +91 -0
- hatchet_sdk/v0/clients/rest/models/user_tenant_memberships_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/user_tenant_public.py +86 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker.py +100 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_create_request.py +94 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_create_response.py +98 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_created.py +102 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_list_response.py +110 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_request.py +102 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_request_list_response.py +104 -0
- hatchet_sdk/v0/clients/rest/models/webhook_worker_request_method.py +38 -0
- hatchet_sdk/v0/clients/rest/models/worker.py +239 -0
- hatchet_sdk/v0/clients/rest/models/worker_label.py +102 -0
- hatchet_sdk/v0/clients/rest/models/worker_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/worker_runtime_info.py +103 -0
- hatchet_sdk/v0/clients/rest/models/worker_runtime_sdks.py +38 -0
- hatchet_sdk/v0/clients/rest/models/worker_type.py +38 -0
- hatchet_sdk/v0/clients/rest/models/workflow.py +165 -0
- hatchet_sdk/v0/clients/rest/models/workflow_concurrency.py +107 -0
- hatchet_sdk/v0/clients/rest/models/workflow_deployment_config.py +136 -0
- hatchet_sdk/v0/clients/rest/models/workflow_kind.py +38 -0
- hatchet_sdk/v0/clients/rest/models/workflow_list.py +120 -0
- hatchet_sdk/v0/clients/rest/models/workflow_metrics.py +97 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run.py +188 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_cancel200_response.py +85 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_list.py +110 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_direction.py +37 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_field.py +39 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_shape.py +186 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_status.py +42 -0
- hatchet_sdk/v0/clients/rest/models/workflow_run_triggered_by.py +112 -0
- hatchet_sdk/v0/clients/rest/models/workflow_runs_cancel_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics.py +94 -0
- hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics_counts.py +104 -0
- hatchet_sdk/v0/clients/rest/models/workflow_tag.py +84 -0
- hatchet_sdk/v0/clients/rest/models/workflow_trigger_cron_ref.py +86 -0
- hatchet_sdk/v0/clients/rest/models/workflow_trigger_event_ref.py +86 -0
- hatchet_sdk/v0/clients/rest/models/workflow_triggers.py +141 -0
- hatchet_sdk/v0/clients/rest/models/workflow_update_request.py +85 -0
- hatchet_sdk/v0/clients/rest/models/workflow_version.py +170 -0
- hatchet_sdk/v0/clients/rest/models/workflow_version_concurrency.py +114 -0
- hatchet_sdk/v0/clients/rest/models/workflow_version_definition.py +85 -0
- hatchet_sdk/v0/clients/rest/models/workflow_version_meta.py +123 -0
- hatchet_sdk/v0/clients/rest/models/workflow_workers_count.py +95 -0
- hatchet_sdk/v0/clients/rest/rest.py +187 -0
- hatchet_sdk/v0/clients/rest/tenacity_utils.py +39 -0
- hatchet_sdk/v0/clients/rest_client.py +622 -0
- hatchet_sdk/v0/clients/run_event_listener.py +260 -0
- hatchet_sdk/v0/clients/workflow_listener.py +277 -0
- hatchet_sdk/v0/connection.py +63 -0
- hatchet_sdk/v0/context/__init__.py +1 -0
- hatchet_sdk/v0/context/context.py +446 -0
- hatchet_sdk/v0/context/worker_context.py +28 -0
- hatchet_sdk/v0/contracts/dispatcher_pb2.py +102 -0
- hatchet_sdk/v0/contracts/dispatcher_pb2.pyi +387 -0
- hatchet_sdk/v0/contracts/dispatcher_pb2_grpc.py +621 -0
- hatchet_sdk/v0/contracts/events_pb2.py +46 -0
- hatchet_sdk/v0/contracts/events_pb2.pyi +87 -0
- hatchet_sdk/v0/contracts/events_pb2_grpc.py +274 -0
- hatchet_sdk/v0/contracts/workflows_pb2.py +80 -0
- hatchet_sdk/v0/contracts/workflows_pb2.pyi +312 -0
- hatchet_sdk/v0/contracts/workflows_pb2_grpc.py +277 -0
- hatchet_sdk/v0/features/cron.py +286 -0
- hatchet_sdk/v0/features/scheduled.py +248 -0
- hatchet_sdk/v0/hatchet.py +310 -0
- hatchet_sdk/v0/labels.py +10 -0
- hatchet_sdk/v0/logger.py +13 -0
- hatchet_sdk/v0/metadata.py +2 -0
- hatchet_sdk/v0/opentelemetry/instrumentor.py +396 -0
- hatchet_sdk/v0/rate_limit.py +126 -0
- hatchet_sdk/v0/token.py +27 -0
- hatchet_sdk/v0/utils/aio_utils.py +137 -0
- hatchet_sdk/v0/utils/backoff.py +9 -0
- hatchet_sdk/v0/utils/typing.py +12 -0
- hatchet_sdk/{v2 → v0/v2}/callable.py +8 -8
- hatchet_sdk/{v2 → v0/v2}/concurrency.py +2 -2
- hatchet_sdk/{v2 → v0/v2}/hatchet.py +10 -10
- hatchet_sdk/v0/worker/__init__.py +1 -0
- hatchet_sdk/v0/worker/action_listener_process.py +294 -0
- hatchet_sdk/v0/worker/runner/run_loop_manager.py +112 -0
- hatchet_sdk/v0/worker/runner/runner.py +460 -0
- hatchet_sdk/v0/worker/runner/utils/capture_logs.py +81 -0
- hatchet_sdk/v0/worker/worker.py +391 -0
- hatchet_sdk/{workflow.py → v0/workflow.py} +4 -4
- hatchet_sdk/v0/workflow_run.py +59 -0
- hatchet_sdk/waits.py +120 -0
- hatchet_sdk/worker/__init__.py +0 -1
- hatchet_sdk/worker/action_listener_process.py +80 -55
- hatchet_sdk/worker/runner/run_loop_manager.py +46 -34
- hatchet_sdk/worker/runner/runner.py +82 -87
- hatchet_sdk/worker/runner/utils/capture_logs.py +26 -23
- hatchet_sdk/worker/worker.py +172 -149
- hatchet_sdk/workflow_run.py +7 -21
- {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/METADATA +2 -2
- hatchet_sdk-1.0.0a1.dist-info/RECORD +505 -0
- {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/entry_points.txt +2 -0
- hatchet_sdk/utils/serialization.py +0 -18
- hatchet_sdk-0.47.1.dist-info/RECORD +0 -237
- /hatchet_sdk/{loader.py → v0/loader.py} +0 -0
- /hatchet_sdk/{semver.py → v0/semver.py} +0 -0
- /hatchet_sdk/{utils → v0/utils}/types.py +0 -0
- /hatchet_sdk/{worker → v0/worker}/runner/utils/error_with_traceback.py +0 -0
- {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/WHEEL +0 -0
hatchet_sdk/clients/admin.py
CHANGED
|
@@ -1,70 +1,56 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import json
|
|
2
3
|
from datetime import datetime
|
|
3
|
-
from typing import
|
|
4
|
+
from typing import Union, cast
|
|
4
5
|
|
|
5
6
|
import grpc
|
|
6
7
|
from google.protobuf import timestamp_pb2
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
7
9
|
|
|
8
|
-
from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
|
|
9
10
|
from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
|
|
10
|
-
from hatchet_sdk.clients.run_event_listener import
|
|
11
|
+
from hatchet_sdk.clients.run_event_listener import RunEventListenerClient
|
|
11
12
|
from hatchet_sdk.clients.workflow_listener import PooledWorkflowRunListener
|
|
13
|
+
from hatchet_sdk.config import ClientConfig
|
|
12
14
|
from hatchet_sdk.connection import new_conn
|
|
13
|
-
from hatchet_sdk.contracts
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
CreateWorkflowVersionOpts,
|
|
17
|
-
PutRateLimitRequest,
|
|
18
|
-
PutWorkflowRequest,
|
|
19
|
-
RateLimitDuration,
|
|
20
|
-
ScheduleWorkflowRequest,
|
|
21
|
-
TriggerWorkflowRequest,
|
|
22
|
-
TriggerWorkflowResponse,
|
|
23
|
-
WorkflowVersion,
|
|
24
|
-
)
|
|
15
|
+
from hatchet_sdk.contracts import workflows_pb2 as v0_workflow_protos
|
|
16
|
+
from hatchet_sdk.contracts.v1 import workflows_pb2 as workflow_protos
|
|
17
|
+
from hatchet_sdk.contracts.v1.workflows_pb2_grpc import AdminServiceStub
|
|
25
18
|
from hatchet_sdk.contracts.workflows_pb2_grpc import WorkflowServiceStub
|
|
26
|
-
from hatchet_sdk.
|
|
27
|
-
from hatchet_sdk.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class ScheduleTriggerWorkflowOptions(TypedDict, total=False):
|
|
39
|
-
parent_id: Optional[str]
|
|
40
|
-
parent_step_run_id: Optional[str]
|
|
41
|
-
child_index: Optional[int]
|
|
42
|
-
child_key: Optional[str]
|
|
43
|
-
namespace: Optional[str]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class ChildTriggerWorkflowOptions(TypedDict, total=False):
|
|
47
|
-
additional_metadata: Dict[str, str] | None = None
|
|
48
|
-
sticky: bool | None = None
|
|
19
|
+
from hatchet_sdk.metadata import get_metadata
|
|
20
|
+
from hatchet_sdk.rate_limit import RateLimitDuration
|
|
21
|
+
from hatchet_sdk.runnables.contextvars import (
|
|
22
|
+
ctx_step_run_id,
|
|
23
|
+
ctx_worker_id,
|
|
24
|
+
ctx_workflow_run_id,
|
|
25
|
+
spawn_index_lock,
|
|
26
|
+
workflow_spawn_indices,
|
|
27
|
+
)
|
|
28
|
+
from hatchet_sdk.utils.proto_enums import convert_python_enum_to_proto
|
|
29
|
+
from hatchet_sdk.utils.typing import JSONSerializableMapping
|
|
30
|
+
from hatchet_sdk.workflow_run import WorkflowRunRef
|
|
49
31
|
|
|
50
32
|
|
|
51
|
-
class
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
33
|
+
class ScheduleTriggerWorkflowOptions(BaseModel):
|
|
34
|
+
parent_id: str | None = None
|
|
35
|
+
parent_step_run_id: str | None = None
|
|
36
|
+
child_index: int | None = None
|
|
37
|
+
child_key: str | None = None
|
|
38
|
+
namespace: str | None = None
|
|
56
39
|
|
|
57
40
|
|
|
58
|
-
class TriggerWorkflowOptions(ScheduleTriggerWorkflowOptions
|
|
59
|
-
additional_metadata:
|
|
41
|
+
class TriggerWorkflowOptions(ScheduleTriggerWorkflowOptions):
|
|
42
|
+
additional_metadata: JSONSerializableMapping = Field(default_factory=dict)
|
|
60
43
|
desired_worker_id: str | None = None
|
|
61
44
|
namespace: str | None = None
|
|
45
|
+
sticky: bool = False
|
|
46
|
+
key: str | None = None
|
|
62
47
|
|
|
63
48
|
|
|
64
|
-
class
|
|
49
|
+
class WorkflowRunTriggerConfig(BaseModel):
|
|
65
50
|
workflow_name: str
|
|
66
|
-
input:
|
|
67
|
-
options: TriggerWorkflowOptions
|
|
51
|
+
input: JSONSerializableMapping
|
|
52
|
+
options: TriggerWorkflowOptions
|
|
53
|
+
key: str | None = None
|
|
68
54
|
|
|
69
55
|
|
|
70
56
|
class DedupeViolationErr(Exception):
|
|
@@ -73,259 +59,198 @@ class DedupeViolationErr(Exception):
|
|
|
73
59
|
pass
|
|
74
60
|
|
|
75
61
|
|
|
76
|
-
class
|
|
77
|
-
|
|
62
|
+
class AdminClient:
|
|
63
|
+
def __init__(self, config: ClientConfig):
|
|
64
|
+
conn = new_conn(config, False)
|
|
65
|
+
self.config = config
|
|
66
|
+
self.client = AdminServiceStub(conn) # type: ignore[no-untyped-call]
|
|
67
|
+
self.v0_client = WorkflowServiceStub(conn) # type: ignore[no-untyped-call]
|
|
68
|
+
self.token = config.token
|
|
69
|
+
self.listener_client = RunEventListenerClient(config=config)
|
|
70
|
+
self.namespace = config.namespace
|
|
78
71
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
):
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
self.pooled_workflow_listener: PooledWorkflowRunListener | None = None
|
|
73
|
+
|
|
74
|
+
class TriggerWorkflowRequest(BaseModel):
|
|
75
|
+
model_config = ConfigDict(extra="ignore")
|
|
76
|
+
|
|
77
|
+
parent_id: str | None = None
|
|
78
|
+
parent_step_run_id: str | None = None
|
|
79
|
+
child_index: int | None = None
|
|
80
|
+
child_key: str | None = None
|
|
81
|
+
additional_metadata: str | None = None
|
|
82
|
+
desired_worker_id: str | None = None
|
|
83
|
+
priority: int | None = None
|
|
84
|
+
|
|
85
|
+
@field_validator("additional_metadata", mode="before")
|
|
86
|
+
@classmethod
|
|
87
|
+
def validate_additional_metadata(
|
|
88
|
+
cls, v: JSONSerializableMapping | None
|
|
89
|
+
) -> bytes | None:
|
|
90
|
+
if not v:
|
|
91
|
+
return None
|
|
84
92
|
|
|
85
93
|
try:
|
|
86
|
-
|
|
87
|
-
None
|
|
88
|
-
if options is None or "additional_metadata" not in options
|
|
89
|
-
else options["additional_metadata"]
|
|
90
|
-
)
|
|
91
|
-
if meta is not None:
|
|
92
|
-
options = {
|
|
93
|
-
**options,
|
|
94
|
-
"additional_metadata": json.dumps(meta).encode("utf-8"),
|
|
95
|
-
}
|
|
94
|
+
return json.dumps(v).encode("utf-8")
|
|
96
95
|
except json.JSONDecodeError as e:
|
|
97
96
|
raise ValueError(f"Error encoding payload: {e}")
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
def _prepare_workflow_request(
|
|
99
|
+
self,
|
|
100
|
+
workflow_name: str,
|
|
101
|
+
input: JSONSerializableMapping,
|
|
102
|
+
options: TriggerWorkflowOptions,
|
|
103
|
+
) -> v0_workflow_protos.TriggerWorkflowRequest:
|
|
104
|
+
try:
|
|
105
|
+
payload_data = json.dumps(input)
|
|
102
106
|
except json.JSONDecodeError as e:
|
|
103
107
|
raise ValueError(f"Error encoding payload: {e}")
|
|
104
108
|
|
|
109
|
+
_options = self.TriggerWorkflowRequest.model_validate(
|
|
110
|
+
options.model_dump()
|
|
111
|
+
).model_dump()
|
|
112
|
+
|
|
113
|
+
return v0_workflow_protos.TriggerWorkflowRequest(
|
|
114
|
+
name=workflow_name, input=payload_data, **_options
|
|
115
|
+
)
|
|
116
|
+
|
|
105
117
|
def _prepare_put_workflow_request(
|
|
106
118
|
self,
|
|
107
119
|
name: str,
|
|
108
|
-
workflow:
|
|
109
|
-
overrides:
|
|
110
|
-
):
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
workflow: workflow_protos.CreateWorkflowVersionRequest,
|
|
121
|
+
overrides: workflow_protos.CreateWorkflowVersionRequest | None = None,
|
|
122
|
+
) -> workflow_protos.CreateWorkflowVersionRequest:
|
|
123
|
+
if overrides is not None:
|
|
124
|
+
workflow.MergeFrom(overrides)
|
|
125
|
+
|
|
126
|
+
workflow.name = name
|
|
127
|
+
|
|
128
|
+
return workflow
|
|
129
|
+
|
|
130
|
+
def _parse_schedule(
|
|
131
|
+
self, schedule: datetime | timestamp_pb2.Timestamp
|
|
132
|
+
) -> timestamp_pb2.Timestamp:
|
|
133
|
+
if isinstance(schedule, datetime):
|
|
134
|
+
t = schedule.timestamp()
|
|
135
|
+
seconds = int(t)
|
|
136
|
+
nanos = int(t % 1 * 1e9)
|
|
137
|
+
return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
|
|
138
|
+
elif isinstance(schedule, timestamp_pb2.Timestamp):
|
|
139
|
+
return schedule
|
|
140
|
+
else:
|
|
141
|
+
raise ValueError(
|
|
142
|
+
"Invalid schedule type. Must be datetime or timestamp_pb2.Timestamp."
|
|
126
143
|
)
|
|
127
|
-
except grpc.RpcError as e:
|
|
128
|
-
raise ValueError(f"Could not put workflow: {e}")
|
|
129
144
|
|
|
130
145
|
def _prepare_schedule_workflow_request(
|
|
131
146
|
self,
|
|
132
147
|
name: str,
|
|
133
|
-
schedules:
|
|
134
|
-
input={},
|
|
135
|
-
options: ScheduleTriggerWorkflowOptions =
|
|
136
|
-
):
|
|
137
|
-
|
|
138
|
-
for schedule in schedules:
|
|
139
|
-
if isinstance(schedule, datetime):
|
|
140
|
-
t = schedule.timestamp()
|
|
141
|
-
seconds = int(t)
|
|
142
|
-
nanos = int(t % 1 * 1e9)
|
|
143
|
-
timestamp = timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
|
|
144
|
-
timestamp_schedules.append(timestamp)
|
|
145
|
-
elif isinstance(schedule, timestamp_pb2.Timestamp):
|
|
146
|
-
timestamp_schedules.append(schedule)
|
|
147
|
-
else:
|
|
148
|
-
raise ValueError(
|
|
149
|
-
"Invalid schedule type. Must be datetime or timestamp_pb2.Timestamp."
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
return ScheduleWorkflowRequest(
|
|
148
|
+
schedules: list[Union[datetime, timestamp_pb2.Timestamp]],
|
|
149
|
+
input: JSONSerializableMapping = {},
|
|
150
|
+
options: ScheduleTriggerWorkflowOptions = ScheduleTriggerWorkflowOptions(),
|
|
151
|
+
) -> v0_workflow_protos.ScheduleWorkflowRequest:
|
|
152
|
+
return v0_workflow_protos.ScheduleWorkflowRequest(
|
|
153
153
|
name=name,
|
|
154
|
-
schedules=
|
|
154
|
+
schedules=[self._parse_schedule(schedule) for schedule in schedules],
|
|
155
155
|
input=json.dumps(input),
|
|
156
|
-
**(
|
|
156
|
+
**options.model_dump(),
|
|
157
157
|
)
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
class AdminClientAioImpl(AdminClientBase):
|
|
164
|
-
def __init__(self, config: ClientConfig):
|
|
165
|
-
aio_conn = new_conn(config, True)
|
|
166
|
-
self.config = config
|
|
167
|
-
self.aio_client = WorkflowServiceStub(aio_conn)
|
|
168
|
-
self.token = config.token
|
|
169
|
-
self.listener_client = new_listener(config)
|
|
170
|
-
self.namespace = config.namespace
|
|
171
|
-
|
|
172
|
-
async def run(
|
|
159
|
+
@tenacity_retry
|
|
160
|
+
async def aio_put_workflow(
|
|
173
161
|
self,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
) ->
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
wrr = await self.run_workflow(workflow_name, input, options)
|
|
162
|
+
name: str,
|
|
163
|
+
workflow: workflow_protos.CreateWorkflowVersionRequest,
|
|
164
|
+
overrides: workflow_protos.CreateWorkflowVersionRequest | None = None,
|
|
165
|
+
) -> workflow_protos.CreateWorkflowVersionResponse:
|
|
166
|
+
## IMPORTANT: The `pooled_workflow_listener` must be created 1) lazily, and not at `init` time, and 2) on the
|
|
167
|
+
## main thread. If 1) is not followed, you'll get an error about something being attached to the wrong event
|
|
168
|
+
## loop. If 2) is not followed, you'll get an error about the event loop not being set up.
|
|
169
|
+
if not self.pooled_workflow_listener:
|
|
170
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
184
171
|
|
|
185
|
-
return
|
|
186
|
-
wrr.workflow_run_id, wrr.workflow_listener, wrr.workflow_run_event_listener
|
|
187
|
-
)
|
|
172
|
+
return await asyncio.to_thread(self.put_workflow, name, workflow, overrides)
|
|
188
173
|
|
|
189
|
-
## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
|
|
190
174
|
@tenacity_retry
|
|
191
|
-
async def
|
|
192
|
-
self,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
and "namespace" in options
|
|
203
|
-
and options["namespace"] is not None
|
|
204
|
-
):
|
|
205
|
-
namespace = options.pop("namespace")
|
|
206
|
-
|
|
207
|
-
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
208
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
209
|
-
|
|
210
|
-
request = self._prepare_workflow_request(workflow_name, input, options)
|
|
211
|
-
|
|
212
|
-
resp: TriggerWorkflowResponse = await self.aio_client.TriggerWorkflow(
|
|
213
|
-
request,
|
|
214
|
-
metadata=get_metadata(self.token),
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
return WorkflowRunRef(
|
|
218
|
-
workflow_run_id=resp.workflow_run_id,
|
|
219
|
-
workflow_listener=self.pooled_workflow_listener,
|
|
220
|
-
workflow_run_event_listener=self.listener_client,
|
|
221
|
-
)
|
|
222
|
-
except (grpc.RpcError, grpc.aio.AioRpcError) as e:
|
|
223
|
-
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
224
|
-
raise DedupeViolationErr(e.details())
|
|
175
|
+
async def aio_put_rate_limit(
|
|
176
|
+
self,
|
|
177
|
+
key: str,
|
|
178
|
+
limit: int,
|
|
179
|
+
duration: RateLimitDuration = RateLimitDuration.SECOND,
|
|
180
|
+
) -> None:
|
|
181
|
+
## IMPORTANT: The `pooled_workflow_listener` must be created 1) lazily, and not at `init` time, and 2) on the
|
|
182
|
+
## main thread. If 1) is not followed, you'll get an error about something being attached to the wrong event
|
|
183
|
+
## loop. If 2) is not followed, you'll get an error about the event loop not being set up.
|
|
184
|
+
if not self.pooled_workflow_listener:
|
|
185
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
225
186
|
|
|
226
|
-
|
|
187
|
+
return await asyncio.to_thread(self.put_rate_limit, key, limit, duration)
|
|
227
188
|
|
|
228
|
-
## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
|
|
229
189
|
@tenacity_retry
|
|
230
|
-
async def
|
|
190
|
+
async def aio_schedule_workflow(
|
|
231
191
|
self,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
192
|
+
name: str,
|
|
193
|
+
schedules: list[Union[datetime, timestamp_pb2.Timestamp]],
|
|
194
|
+
input: JSONSerializableMapping = {},
|
|
195
|
+
options: ScheduleTriggerWorkflowOptions = ScheduleTriggerWorkflowOptions(),
|
|
196
|
+
) -> v0_workflow_protos.WorkflowVersion:
|
|
197
|
+
## IMPORTANT: The `pooled_workflow_listener` must be created 1) lazily, and not at `init` time, and 2) on the
|
|
198
|
+
## main thread. If 1) is not followed, you'll get an error about something being attached to the wrong event
|
|
199
|
+
## loop. If 2) is not followed, you'll get an error about the event loop not being set up.
|
|
238
200
|
if not self.pooled_workflow_listener:
|
|
239
201
|
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
240
202
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
options is not None
|
|
245
|
-
and "namespace" in options
|
|
246
|
-
and options["namespace"] is not None
|
|
247
|
-
):
|
|
248
|
-
namespace = options["namespace"]
|
|
249
|
-
del options["namespace"]
|
|
250
|
-
|
|
251
|
-
workflow_run_requests: TriggerWorkflowRequest = []
|
|
252
|
-
|
|
253
|
-
for workflow in workflows:
|
|
254
|
-
workflow_name = workflow["workflow_name"]
|
|
255
|
-
input_data = workflow["input"]
|
|
256
|
-
options = workflow["options"]
|
|
257
|
-
|
|
258
|
-
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
259
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
260
|
-
|
|
261
|
-
# Prepare and trigger workflow for each workflow name and input
|
|
262
|
-
request = self._prepare_workflow_request(workflow_name, input_data, options)
|
|
263
|
-
workflow_run_requests.append(request)
|
|
264
|
-
|
|
265
|
-
request = BulkTriggerWorkflowRequest(workflows=workflow_run_requests)
|
|
266
|
-
|
|
267
|
-
resp: BulkTriggerWorkflowResponse = await self.aio_client.BulkTriggerWorkflow(
|
|
268
|
-
request,
|
|
269
|
-
metadata=get_metadata(self.token),
|
|
203
|
+
return await asyncio.to_thread(
|
|
204
|
+
self.schedule_workflow, name, schedules, input, options
|
|
270
205
|
)
|
|
271
206
|
|
|
272
|
-
return [
|
|
273
|
-
WorkflowRunRef(
|
|
274
|
-
workflow_run_id=workflow_run_id,
|
|
275
|
-
workflow_listener=self.pooled_workflow_listener,
|
|
276
|
-
workflow_run_event_listener=self.listener_client,
|
|
277
|
-
)
|
|
278
|
-
for workflow_run_id in resp.workflow_run_ids
|
|
279
|
-
]
|
|
280
|
-
|
|
281
207
|
@tenacity_retry
|
|
282
|
-
|
|
208
|
+
def put_workflow(
|
|
283
209
|
self,
|
|
284
210
|
name: str,
|
|
285
|
-
workflow:
|
|
286
|
-
overrides:
|
|
287
|
-
) ->
|
|
211
|
+
workflow: workflow_protos.CreateWorkflowVersionRequest,
|
|
212
|
+
overrides: workflow_protos.CreateWorkflowVersionRequest | None = None,
|
|
213
|
+
) -> workflow_protos.CreateWorkflowVersionResponse:
|
|
288
214
|
opts = self._prepare_put_workflow_request(name, workflow, overrides)
|
|
289
215
|
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
|
|
216
|
+
return cast(
|
|
217
|
+
workflow_protos.CreateWorkflowVersionResponse,
|
|
218
|
+
self.client.PutWorkflow(
|
|
219
|
+
opts,
|
|
220
|
+
metadata=get_metadata(self.token),
|
|
221
|
+
),
|
|
293
222
|
)
|
|
294
223
|
|
|
295
224
|
@tenacity_retry
|
|
296
|
-
|
|
225
|
+
def put_rate_limit(
|
|
297
226
|
self,
|
|
298
227
|
key: str,
|
|
299
228
|
limit: int,
|
|
300
229
|
duration: RateLimitDuration = RateLimitDuration.SECOND,
|
|
301
|
-
):
|
|
302
|
-
|
|
303
|
-
|
|
230
|
+
) -> None:
|
|
231
|
+
duration_proto = convert_python_enum_to_proto(
|
|
232
|
+
duration, workflow_protos.RateLimitDuration
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
self.v0_client.PutRateLimit(
|
|
236
|
+
v0_workflow_protos.PutRateLimitRequest(
|
|
304
237
|
key=key,
|
|
305
238
|
limit=limit,
|
|
306
|
-
duration=
|
|
239
|
+
duration=duration_proto, # type: ignore[arg-type]
|
|
307
240
|
),
|
|
308
241
|
metadata=get_metadata(self.token),
|
|
309
242
|
)
|
|
310
243
|
|
|
311
244
|
@tenacity_retry
|
|
312
|
-
|
|
245
|
+
def schedule_workflow(
|
|
313
246
|
self,
|
|
314
247
|
name: str,
|
|
315
|
-
schedules:
|
|
316
|
-
input={},
|
|
317
|
-
options: ScheduleTriggerWorkflowOptions =
|
|
318
|
-
) -> WorkflowVersion:
|
|
248
|
+
schedules: list[Union[datetime, timestamp_pb2.Timestamp]],
|
|
249
|
+
input: JSONSerializableMapping = {},
|
|
250
|
+
options: ScheduleTriggerWorkflowOptions = ScheduleTriggerWorkflowOptions(),
|
|
251
|
+
) -> v0_workflow_protos.WorkflowVersion:
|
|
319
252
|
try:
|
|
320
|
-
namespace = self.namespace
|
|
321
|
-
|
|
322
|
-
if (
|
|
323
|
-
options is not None
|
|
324
|
-
and "namespace" in options
|
|
325
|
-
and options["namespace"] is not None
|
|
326
|
-
):
|
|
327
|
-
namespace = options["namespace"]
|
|
328
|
-
del options["namespace"]
|
|
253
|
+
namespace = options.namespace or self.namespace
|
|
329
254
|
|
|
330
255
|
if namespace != "" and not name.startswith(self.namespace):
|
|
331
256
|
name = f"{namespace}{name}"
|
|
@@ -334,128 +259,112 @@ class AdminClientAioImpl(AdminClientBase):
|
|
|
334
259
|
name, schedules, input, options
|
|
335
260
|
)
|
|
336
261
|
|
|
337
|
-
return
|
|
338
|
-
|
|
339
|
-
|
|
262
|
+
return cast(
|
|
263
|
+
v0_workflow_protos.WorkflowVersion,
|
|
264
|
+
self.v0_client.ScheduleWorkflow(
|
|
265
|
+
request,
|
|
266
|
+
metadata=get_metadata(self.token),
|
|
267
|
+
),
|
|
340
268
|
)
|
|
341
|
-
except (grpc.
|
|
269
|
+
except (grpc.RpcError, grpc.aio.AioRpcError) as e:
|
|
342
270
|
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
343
271
|
raise DedupeViolationErr(e.details())
|
|
344
272
|
|
|
345
273
|
raise e
|
|
346
274
|
|
|
347
|
-
|
|
348
|
-
class AdminClient(AdminClientBase):
|
|
349
|
-
def __init__(self, config: ClientConfig):
|
|
350
|
-
conn = new_conn(config)
|
|
351
|
-
self.config = config
|
|
352
|
-
self.client = WorkflowServiceStub(conn)
|
|
353
|
-
self.aio = AdminClientAioImpl(config)
|
|
354
|
-
self.token = config.token
|
|
355
|
-
self.listener_client = new_listener(config)
|
|
356
|
-
self.namespace = config.namespace
|
|
357
|
-
|
|
358
|
-
@tenacity_retry
|
|
359
|
-
def put_workflow(
|
|
275
|
+
def _create_workflow_run_request(
|
|
360
276
|
self,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
) ->
|
|
365
|
-
|
|
277
|
+
workflow_name: str,
|
|
278
|
+
input: JSONSerializableMapping,
|
|
279
|
+
options: TriggerWorkflowOptions,
|
|
280
|
+
) -> v0_workflow_protos.TriggerWorkflowRequest:
|
|
281
|
+
workflow_run_id = ctx_workflow_run_id.get()
|
|
282
|
+
step_run_id = ctx_step_run_id.get()
|
|
283
|
+
worker_id = ctx_worker_id.get()
|
|
284
|
+
spawn_index = workflow_spawn_indices[workflow_run_id] if workflow_run_id else 0
|
|
285
|
+
|
|
286
|
+
## Increment the spawn_index for the parent workflow
|
|
287
|
+
if workflow_run_id:
|
|
288
|
+
workflow_spawn_indices[workflow_run_id] += 1
|
|
289
|
+
|
|
290
|
+
desired_worker_id = (
|
|
291
|
+
(options.desired_worker_id or worker_id) if options.sticky else None
|
|
292
|
+
)
|
|
293
|
+
child_index = (
|
|
294
|
+
options.child_index if options.child_index is not None else spawn_index
|
|
295
|
+
)
|
|
366
296
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
297
|
+
trigger_options = TriggerWorkflowOptions(
|
|
298
|
+
parent_id=options.parent_id or workflow_run_id,
|
|
299
|
+
parent_step_run_id=options.parent_step_run_id or step_run_id,
|
|
300
|
+
child_key=options.child_key,
|
|
301
|
+
child_index=child_index,
|
|
302
|
+
additional_metadata=options.additional_metadata,
|
|
303
|
+
desired_worker_id=desired_worker_id,
|
|
370
304
|
)
|
|
371
305
|
|
|
372
|
-
|
|
306
|
+
namespace = options.namespace or self.namespace
|
|
373
307
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
limit: int,
|
|
379
|
-
duration: Union[RateLimitDuration.Value, str] = RateLimitDuration.SECOND,
|
|
380
|
-
):
|
|
381
|
-
self.client.PutRateLimit(
|
|
382
|
-
PutRateLimitRequest(
|
|
383
|
-
key=key,
|
|
384
|
-
limit=limit,
|
|
385
|
-
duration=duration,
|
|
386
|
-
),
|
|
387
|
-
metadata=get_metadata(self.token),
|
|
388
|
-
)
|
|
308
|
+
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
309
|
+
workflow_name = f"{namespace}{workflow_name}"
|
|
310
|
+
|
|
311
|
+
return self._prepare_workflow_request(workflow_name, input, trigger_options)
|
|
389
312
|
|
|
313
|
+
## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
|
|
390
314
|
@tenacity_retry
|
|
391
|
-
def
|
|
315
|
+
def run_workflow(
|
|
392
316
|
self,
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
try:
|
|
399
|
-
namespace = self.namespace
|
|
400
|
-
|
|
401
|
-
if (
|
|
402
|
-
options is not None
|
|
403
|
-
and "namespace" in options
|
|
404
|
-
and options["namespace"] is not None
|
|
405
|
-
):
|
|
406
|
-
namespace = options["namespace"]
|
|
407
|
-
del options["namespace"]
|
|
408
|
-
|
|
409
|
-
if namespace != "" and not name.startswith(self.namespace):
|
|
410
|
-
name = f"{namespace}{name}"
|
|
317
|
+
workflow_name: str,
|
|
318
|
+
input: JSONSerializableMapping,
|
|
319
|
+
options: TriggerWorkflowOptions = TriggerWorkflowOptions(),
|
|
320
|
+
) -> WorkflowRunRef:
|
|
321
|
+
request = self._create_workflow_run_request(workflow_name, input, options)
|
|
411
322
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
)
|
|
323
|
+
if not self.pooled_workflow_listener:
|
|
324
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
415
325
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
326
|
+
try:
|
|
327
|
+
resp = cast(
|
|
328
|
+
v0_workflow_protos.TriggerWorkflowResponse,
|
|
329
|
+
self.v0_client.TriggerWorkflow(
|
|
330
|
+
request,
|
|
331
|
+
metadata=get_metadata(self.token),
|
|
332
|
+
),
|
|
419
333
|
)
|
|
420
334
|
except (grpc.RpcError, grpc.aio.AioRpcError) as e:
|
|
421
335
|
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
422
336
|
raise DedupeViolationErr(e.details())
|
|
423
337
|
|
|
424
|
-
|
|
338
|
+
return WorkflowRunRef(
|
|
339
|
+
workflow_run_id=resp.workflow_run_id,
|
|
340
|
+
workflow_listener=self.pooled_workflow_listener,
|
|
341
|
+
workflow_run_event_listener=self.listener_client,
|
|
342
|
+
)
|
|
425
343
|
|
|
426
344
|
## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
|
|
427
345
|
@tenacity_retry
|
|
428
|
-
def
|
|
429
|
-
self,
|
|
346
|
+
async def aio_run_workflow(
|
|
347
|
+
self,
|
|
348
|
+
workflow_name: str,
|
|
349
|
+
input: JSONSerializableMapping,
|
|
350
|
+
options: TriggerWorkflowOptions = TriggerWorkflowOptions(),
|
|
430
351
|
) -> WorkflowRunRef:
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
## TODO: Factor this out - it's repeated a lot of places
|
|
438
|
-
if (
|
|
439
|
-
options is not None
|
|
440
|
-
and "namespace" in options
|
|
441
|
-
and options["namespace"] is not None
|
|
442
|
-
):
|
|
443
|
-
namespace = options.pop("namespace")
|
|
444
|
-
|
|
445
|
-
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
446
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
352
|
+
## IMPORTANT: The `pooled_workflow_listener` must be created 1) lazily, and not at `init` time, and 2) on the
|
|
353
|
+
## main thread. If 1) is not followed, you'll get an error about something being attached to the wrong event
|
|
354
|
+
## loop. If 2) is not followed, you'll get an error about the event loop not being set up.
|
|
355
|
+
async with spawn_index_lock:
|
|
356
|
+
request = self._create_workflow_run_request(workflow_name, input, options)
|
|
447
357
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
resp: TriggerWorkflowResponse = self.client.TriggerWorkflow(
|
|
451
|
-
request,
|
|
452
|
-
metadata=get_metadata(self.token),
|
|
453
|
-
)
|
|
358
|
+
if not self.pooled_workflow_listener:
|
|
359
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
454
360
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
361
|
+
try:
|
|
362
|
+
resp = cast(
|
|
363
|
+
v0_workflow_protos.TriggerWorkflowResponse,
|
|
364
|
+
self.v0_client.TriggerWorkflow(
|
|
365
|
+
request,
|
|
366
|
+
metadata=get_metadata(self.token),
|
|
367
|
+
),
|
|
459
368
|
)
|
|
460
369
|
except (grpc.RpcError, grpc.aio.AioRpcError) as e:
|
|
461
370
|
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
@@ -463,43 +372,36 @@ class AdminClient(AdminClientBase):
|
|
|
463
372
|
|
|
464
373
|
raise e
|
|
465
374
|
|
|
375
|
+
return WorkflowRunRef(
|
|
376
|
+
workflow_run_id=resp.workflow_run_id,
|
|
377
|
+
workflow_listener=self.pooled_workflow_listener,
|
|
378
|
+
workflow_run_event_listener=self.listener_client,
|
|
379
|
+
)
|
|
380
|
+
|
|
466
381
|
## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
|
|
467
382
|
@tenacity_retry
|
|
468
383
|
def run_workflows(
|
|
469
|
-
self,
|
|
384
|
+
self,
|
|
385
|
+
workflows: list[WorkflowRunTriggerConfig],
|
|
470
386
|
) -> list[WorkflowRunRef]:
|
|
471
|
-
workflow_run_requests: TriggerWorkflowRequest = []
|
|
472
387
|
if not self.pooled_workflow_listener:
|
|
473
388
|
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
474
389
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
options is not None
|
|
484
|
-
and "namespace" in options
|
|
485
|
-
and options["namespace"] is not None
|
|
486
|
-
):
|
|
487
|
-
namespace = options["namespace"]
|
|
488
|
-
del options["namespace"]
|
|
489
|
-
|
|
490
|
-
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
491
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
492
|
-
|
|
493
|
-
# Prepare and trigger workflow for each workflow name and input
|
|
494
|
-
request = self._prepare_workflow_request(workflow_name, input_data, options)
|
|
495
|
-
|
|
496
|
-
workflow_run_requests.append(request)
|
|
497
|
-
|
|
498
|
-
request = BulkTriggerWorkflowRequest(workflows=workflow_run_requests)
|
|
390
|
+
bulk_request = v0_workflow_protos.BulkTriggerWorkflowRequest(
|
|
391
|
+
workflows=[
|
|
392
|
+
self._create_workflow_run_request(
|
|
393
|
+
workflow.workflow_name, workflow.input, workflow.options
|
|
394
|
+
)
|
|
395
|
+
for workflow in workflows
|
|
396
|
+
]
|
|
397
|
+
)
|
|
499
398
|
|
|
500
|
-
resp
|
|
501
|
-
|
|
502
|
-
|
|
399
|
+
resp = cast(
|
|
400
|
+
v0_workflow_protos.BulkTriggerWorkflowResponse,
|
|
401
|
+
self.v0_client.BulkTriggerWorkflow(
|
|
402
|
+
bulk_request,
|
|
403
|
+
metadata=get_metadata(self.token),
|
|
404
|
+
),
|
|
503
405
|
)
|
|
504
406
|
|
|
505
407
|
return [
|
|
@@ -511,32 +413,50 @@ class AdminClient(AdminClientBase):
|
|
|
511
413
|
for workflow_run_id in resp.workflow_run_ids
|
|
512
414
|
]
|
|
513
415
|
|
|
514
|
-
|
|
416
|
+
@tenacity_retry
|
|
417
|
+
async def aio_run_workflows(
|
|
515
418
|
self,
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
workflow_name = function.function_name
|
|
419
|
+
workflows: list[WorkflowRunTriggerConfig],
|
|
420
|
+
) -> list[WorkflowRunRef]:
|
|
421
|
+
## IMPORTANT: The `pooled_workflow_listener` must be created 1) lazily, and not at `init` time, and 2) on the
|
|
422
|
+
## main thread. If 1) is not followed, you'll get an error about something being attached to the wrong event
|
|
423
|
+
## loop. If 2) is not followed, you'll get an error about the event loop not being set up.
|
|
424
|
+
if not self.pooled_workflow_listener:
|
|
425
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
524
426
|
|
|
525
|
-
|
|
427
|
+
async with spawn_index_lock:
|
|
428
|
+
bulk_request = v0_workflow_protos.BulkTriggerWorkflowRequest(
|
|
429
|
+
workflows=[
|
|
430
|
+
self._create_workflow_run_request(
|
|
431
|
+
workflow.workflow_name, workflow.input, workflow.options
|
|
432
|
+
)
|
|
433
|
+
for workflow in workflows
|
|
434
|
+
]
|
|
435
|
+
)
|
|
526
436
|
|
|
527
|
-
|
|
528
|
-
|
|
437
|
+
resp = cast(
|
|
438
|
+
v0_workflow_protos.BulkTriggerWorkflowResponse,
|
|
439
|
+
self.v0_client.BulkTriggerWorkflow(
|
|
440
|
+
bulk_request,
|
|
441
|
+
metadata=get_metadata(self.token),
|
|
442
|
+
),
|
|
529
443
|
)
|
|
530
444
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if not self.pooled_workflow_listener:
|
|
534
|
-
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
535
|
-
|
|
536
|
-
return WorkflowRunRef(
|
|
445
|
+
return [
|
|
446
|
+
WorkflowRunRef(
|
|
537
447
|
workflow_run_id=workflow_run_id,
|
|
538
448
|
workflow_listener=self.pooled_workflow_listener,
|
|
539
449
|
workflow_run_event_listener=self.listener_client,
|
|
540
450
|
)
|
|
541
|
-
|
|
542
|
-
|
|
451
|
+
for workflow_run_id in resp.workflow_run_ids
|
|
452
|
+
]
|
|
453
|
+
|
|
454
|
+
def get_workflow_run(self, workflow_run_id: str) -> WorkflowRunRef:
|
|
455
|
+
if not self.pooled_workflow_listener:
|
|
456
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
457
|
+
|
|
458
|
+
return WorkflowRunRef(
|
|
459
|
+
workflow_run_id=workflow_run_id,
|
|
460
|
+
workflow_listener=self.pooled_workflow_listener,
|
|
461
|
+
workflow_run_event_listener=self.listener_client,
|
|
462
|
+
)
|