aws-durable-execution-sdk-python 1.5.0__tar.gz → 1.7.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.
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/.gitignore +6 -3
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/PKG-INFO +3 -5
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/README.md +2 -2
- aws_durable_execution_sdk_python-1.7.0/pyproject.toml +83 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/__about__.py +1 -1
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/__init__.py +3 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/concurrency/executor.py +77 -15
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/config.py +12 -0
- aws_durable_execution_sdk_python-1.7.0/src/aws_durable_execution_sdk_python/constants.py +6 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/context.py +304 -170
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/execution.py +63 -64
- aws_durable_execution_sdk_python-1.7.0/src/aws_durable_execution_sdk_python/filesystem_serdes.py +264 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/identifier.py +10 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/lambda_service.py +95 -1
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/logger.py +31 -9
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/child.py +11 -7
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/step.py +8 -1
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/wait_for_condition.py +7 -1
- aws_durable_execution_sdk_python-1.7.0/src/aws_durable_execution_sdk_python/plugin.py +563 -0
- aws_durable_execution_sdk_python-1.7.0/src/aws_durable_execution_sdk_python/preview.py +196 -0
- aws_durable_execution_sdk_python-1.7.0/src/aws_durable_execution_sdk_python/retries.py +377 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/state.py +151 -61
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/types.py +46 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/concurrency_test.py +247 -14
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/context_test.py +541 -28
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/e2e/checkpoint_response_int_test.py +10 -10
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/e2e/execution_int_test.py +7 -7
- aws_durable_execution_sdk_python-1.7.0/tests/e2e/filesystem_serdes_int_test.py +488 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/e2e/map_with_concurrent_waits_int_test.py +2 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/execution_test.py +363 -56
- aws_durable_execution_sdk_python-1.7.0/tests/filesystem_serdes_test.py +790 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/lambda_service_test.py +86 -14
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/logger_test.py +25 -20
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/callback_test.py +92 -34
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/child_test.py +109 -24
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/invoke_test.py +101 -35
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/map_test.py +233 -172
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/parallel_test.py +216 -161
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/step_test.py +58 -25
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/wait_for_condition_test.py +140 -31
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/wait_test.py +29 -11
- aws_durable_execution_sdk_python-1.7.0/tests/plugin_test.py +937 -0
- aws_durable_execution_sdk_python-1.7.0/tests/preview_test.py +212 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/retries_test.py +147 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/state_test.py +887 -45
- aws_durable_execution_sdk_python-1.7.0/tests/with_retry_test.py +372 -0
- aws_durable_execution_sdk_python-1.5.0/.github/ISSUE_TEMPLATE/bug_report.yml +0 -91
- aws_durable_execution_sdk_python-1.5.0/.github/ISSUE_TEMPLATE/config.yml +0 -5
- aws_durable_execution_sdk_python-1.5.0/.github/ISSUE_TEMPLATE/documentation.yml +0 -36
- aws_durable_execution_sdk_python-1.5.0/.github/ISSUE_TEMPLATE/feature_request.yml +0 -57
- aws_durable_execution_sdk_python-1.5.0/.github/dependabot.yml +0 -14
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/__init__.py +0 -1
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/ci-checks.sh +0 -18
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/lintcommit.py +0 -265
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/parse_sdk_branch.py +0 -31
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/tests/__init__.py +0 -1
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/tests/test_lintcommit.py +0 -261
- aws_durable_execution_sdk_python-1.5.0/.github/scripts/tests/test_parse_sdk_branch.py +0 -84
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/ci.yml +0 -52
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/deploy-examples.yml +0 -134
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/integration-tests.yml +0 -162
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/notify-issues.yml +0 -23
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/notify-pr.yml +0 -24
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/notify-release.yml +0 -29
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/pypi-publish.yml +0 -79
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/scorecard.yml +0 -80
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/sync-package.yml +0 -72
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/test-parser.yml +0 -24
- aws_durable_execution_sdk_python-1.5.0/.github/workflows/update-sam-template.yml +0 -42
- aws_durable_execution_sdk_python-1.5.0/AGENTS.md +0 -929
- aws_durable_execution_sdk_python-1.5.0/CODE_OF_CONDUCT.md +0 -4
- aws_durable_execution_sdk_python-1.5.0/CONTRIBUTING.md +0 -388
- aws_durable_execution_sdk_python-1.5.0/examples/cli.py +0 -487
- aws_durable_execution_sdk_python-1.5.0/examples/examples-catalog.json +0 -607
- aws_durable_execution_sdk_python-1.5.0/examples/scripts/generate_sam_template.py +0 -106
- aws_durable_execution_sdk_python-1.5.0/examples/src/__init__.py +0 -3
- aws_durable_execution_sdk_python-1.5.0/examples/src/block_example/block_example.py +0 -47
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_concurrency.py +0 -51
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_heartbeat.py +0 -22
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_mixed_ops.py +0 -35
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_serdes.py +0 -76
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_simple.py +0 -22
- aws_durable_execution_sdk_python-1.5.0/examples/src/callback/callback_with_timeout.py +0 -23
- aws_durable_execution_sdk_python-1.5.0/examples/src/comprehensive_operations/comprehensive_operations.py +0 -51
- aws_durable_execution_sdk_python-1.5.0/examples/src/handler_error/handler_error.py +0 -13
- aws_durable_execution_sdk_python-1.5.0/examples/src/hello_world.py +0 -62
- aws_durable_execution_sdk_python-1.5.0/examples/src/logger_example/logger_example.py +0 -64
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_completion.py +0 -117
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_operations.py +0 -23
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_operations_flat.py +0 -23
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_batch_serdes.py +0 -96
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_custom_serdes.py +0 -63
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_failure_tolerance.py +0 -53
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_item_namer.py +0 -30
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_large_scale.py +0 -64
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_max_concurrency.py +0 -23
- aws_durable_execution_sdk_python-1.5.0/examples/src/map/map_with_min_successful.py +0 -43
- aws_durable_execution_sdk_python-1.5.0/examples/src/no_replay_execution/no_replay_execution.py +0 -15
- aws_durable_execution_sdk_python-1.5.0/examples/src/none_results/none_results.py +0 -31
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_first_successful.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_flat.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_batch_serdes.py +0 -97
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_custom_serdes.py +0 -60
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_failure_tolerance.py +0 -59
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_max_concurrency.py +0 -25
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_named_branches.py +0 -51
- aws_durable_execution_sdk_python-1.5.0/examples/src/parallel/parallel_with_wait.py +0 -24
- aws_durable_execution_sdk_python-1.5.0/examples/src/run_in_child_context/run_in_child_context.py +0 -22
- aws_durable_execution_sdk_python-1.5.0/examples/src/run_in_child_context/run_in_child_context_large_data.py +0 -73
- aws_durable_execution_sdk_python-1.5.0/examples/src/run_in_child_context/run_in_child_context_step_failure.py +0 -50
- aws_durable_execution_sdk_python-1.5.0/examples/src/simple_execution/simple_execution.py +0 -18
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step.py +0 -19
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step_no_name.py +0 -11
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step_semantics_at_most_once.py +0 -18
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step_with_exponential_backoff.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step_with_name.py +0 -11
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/step_with_retry.py +0 -46
- aws_durable_execution_sdk_python-1.5.0/examples/src/step/steps_with_retry.py +0 -81
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait/multiple_wait.py +0 -19
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait/wait.py +0 -11
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait/wait_with_name.py +0 -12
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_anonymous.py +0 -20
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_child.py +0 -42
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_heartbeat.py +0 -33
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_mixed_ops.py +0 -47
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_multiple_invocations.py +0 -53
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_nested.py +0 -66
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_serdes.py +0 -90
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_submitter_failure.py +0 -39
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py +0 -52
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_callback/wait_for_callback_timeout.py +0 -35
- aws_durable_execution_sdk_python-1.5.0/examples/src/wait_for_condition/wait_for_condition.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/template.yaml +0 -982
- aws_durable_execution_sdk_python-1.5.0/examples/test/README.md +0 -119
- aws_durable_execution_sdk_python-1.5.0/examples/test/__init__.py +0 -1
- aws_durable_execution_sdk_python-1.5.0/examples/test/block_example/test_block_example.py +0 -104
- aws_durable_execution_sdk_python-1.5.0/examples/test/callback/test_callback_concurrency.py +0 -83
- aws_durable_execution_sdk_python-1.5.0/examples/test/callback/test_callback_heartbeat.py +0 -51
- aws_durable_execution_sdk_python-1.5.0/examples/test/callback/test_callback_mixed_ops.py +0 -49
- aws_durable_execution_sdk_python-1.5.0/examples/test/callback/test_callback_serdes.py +0 -60
- aws_durable_execution_sdk_python-1.5.0/examples/test/callback/test_callback_simple.py +0 -47
- aws_durable_execution_sdk_python-1.5.0/examples/test/comprehensive_operations/test_comprehensive_operations.py +0 -94
- aws_durable_execution_sdk_python-1.5.0/examples/test/conftest.py +0 -268
- aws_durable_execution_sdk_python-1.5.0/examples/test/handler_error/test_handler_error.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/test/logger_example/test_logger_example.py +0 -35
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_completion.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_operations.py +0 -42
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_operations_flat.py +0 -39
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_batch_serdes.py +0 -43
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_custom_serdes.py +0 -48
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_failure_tolerance.py +0 -52
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_item_namer.py +0 -39
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_large_scale.py +0 -36
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_max_concurrency.py +0 -37
- aws_durable_execution_sdk_python-1.5.0/examples/test/map/test_map_with_min_successful.py +0 -70
- aws_durable_execution_sdk_python-1.5.0/examples/test/no_replay_execution/test_no_replay_execution.py +0 -52
- aws_durable_execution_sdk_python-1.5.0/examples/test/none_results/test_none_results.py +0 -51
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel.py +0 -42
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_flat.py +0 -42
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_batch_serdes.py +0 -43
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_custom_serdes.py +0 -46
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_failure_tolerance.py +0 -49
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_max_concurrency.py +0 -36
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_named_branches.py +0 -57
- aws_durable_execution_sdk_python-1.5.0/examples/test/parallel/test_parallel_with_wait.py +0 -47
- aws_durable_execution_sdk_python-1.5.0/examples/test/run_in_child_context/test_run_in_child_context.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/test/run_in_child_context/test_run_in_child_context_large_data.py +0 -36
- aws_durable_execution_sdk_python-1.5.0/examples/test/run_in_child_context/test_run_in_child_context_step_failure.py +0 -23
- aws_durable_execution_sdk_python-1.5.0/examples/test/simple_execution/test_simple_execution.py +0 -40
- aws_durable_execution_sdk_python-1.5.0/examples/test/step/test_step.py +0 -24
- aws_durable_execution_sdk_python-1.5.0/examples/test/step/test_step_permutations.py +0 -75
- aws_durable_execution_sdk_python-1.5.0/examples/test/step/test_step_semantics_at_most_once.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/test/step/test_step_with_retry.py +0 -40
- aws_durable_execution_sdk_python-1.5.0/examples/test/step/test_steps_with_retry.py +0 -52
- aws_durable_execution_sdk_python-1.5.0/examples/test/test_hello_world.py +0 -24
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait/test_multiple_wait.py +0 -57
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait/test_wait.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait/test_wait_permutations.py +0 -25
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_anonymous.py +0 -39
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_child.py +0 -73
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_failure.py +0 -27
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_heartbeat.py +0 -62
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_mixed_ops.py +0 -52
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py +0 -74
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_nested.py +0 -101
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_serdes.py +0 -66
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py +0 -28
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_success.py +0 -25
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_callback/test_wait_for_callback_timeout.py +0 -32
- aws_durable_execution_sdk_python-1.5.0/examples/test/wait_for_condition/test_wait_for_condition.py +0 -24
- aws_durable_execution_sdk_python-1.5.0/pyproject.toml +0 -134
- aws_durable_execution_sdk_python-1.5.0/src/aws_durable_execution_sdk_python/retries.py +0 -174
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/LICENSE +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/NOTICE +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/.gitignore +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/concurrency/__init__.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/concurrency/models.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/exceptions.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/__init__.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/base.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/callback.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/invoke.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/map.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/parallel.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/operation/wait.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/py.typed +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/serdes.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/suspend.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/threading.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/src/aws_durable_execution_sdk_python/waits.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/__init__.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/config_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/durable_executions_python_language_sdk_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/e2e/__init__.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/exceptions_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/__init__.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/operation/base_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/serdes_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/suspend_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/test_helpers.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/threading_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/types_test.py +0 -0
- {aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/tests/waits_test.py +0 -0
{aws_durable_execution_sdk_python-1.5.0 → aws_durable_execution_sdk_python-1.7.0}/.gitignore
RENAMED
|
@@ -9,6 +9,7 @@ __pycache__/
|
|
|
9
9
|
*$py.class
|
|
10
10
|
*.egg-info/
|
|
11
11
|
|
|
12
|
+
*.coverage
|
|
12
13
|
/.coverage
|
|
13
14
|
/.coverage.*
|
|
14
15
|
/.cache
|
|
@@ -30,7 +31,9 @@ dist/
|
|
|
30
31
|
|
|
31
32
|
.kiro/
|
|
32
33
|
|
|
33
|
-
/
|
|
34
|
-
|
|
34
|
+
**/build/
|
|
35
|
+
**/*.zip
|
|
36
|
+
.aws-sam/
|
|
37
|
+
**/template.generated.json
|
|
35
38
|
|
|
36
|
-
.env
|
|
39
|
+
.env
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-durable-execution-sdk-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: AWS Durable Execution SDK for Python
|
|
5
5
|
Project-URL: Documentation, https://github.com/aws/aws-durable-execution-sdk-python#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/aws/aws-durable-execution-sdk-python/issues
|
|
7
7
|
Project-URL: Source, https://github.com/aws/aws-durable-execution-sdk-python
|
|
8
8
|
Author-email: AWS durable-execution-dev <durable-execution-dev@amazon.com>
|
|
9
9
|
License-Expression: Apache-2.0
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
License-File: NOTICE
|
|
12
10
|
Classifier: Development Status :: 4 - Beta
|
|
13
11
|
Classifier: Programming Language :: Python
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -27,7 +25,7 @@ Description-Content-Type: text/markdown
|
|
|
27
25
|
[](https://pypi.org/project/aws-durable-execution-sdk-python)
|
|
28
26
|
[](https://pypi.org/project/aws-durable-execution-sdk-python)
|
|
29
27
|
[](https://scorecard.dev/viewer/?uri=github.com/aws/aws-durable-execution-sdk-python)
|
|
30
|
-
[](LICENSE)
|
|
28
|
+
[](https://github.com/aws/aws-durable-execution-sdk-python/blob/main/LICENSE)
|
|
31
29
|
|
|
32
30
|
-----
|
|
33
31
|
|
|
@@ -105,4 +103,4 @@ The complete documentation for the AWS Durable Execution SDK for Python lives on
|
|
|
105
103
|
|
|
106
104
|
## 📄 License
|
|
107
105
|
|
|
108
|
-
See the [LICENSE](LICENSE) file for our project's licensing.
|
|
106
|
+
See the [LICENSE](https://github.com/aws/aws-durable-execution-sdk-python/blob/main/LICENSE) file for our project's licensing.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://pypi.org/project/aws-durable-execution-sdk-python)
|
|
5
5
|
[](https://pypi.org/project/aws-durable-execution-sdk-python)
|
|
6
6
|
[](https://scorecard.dev/viewer/?uri=github.com/aws/aws-durable-execution-sdk-python)
|
|
7
|
-
[](LICENSE)
|
|
7
|
+
[](https://github.com/aws/aws-durable-execution-sdk-python/blob/main/LICENSE)
|
|
8
8
|
|
|
9
9
|
-----
|
|
10
10
|
|
|
@@ -82,4 +82,4 @@ The complete documentation for the AWS Durable Execution SDK for Python lives on
|
|
|
82
82
|
|
|
83
83
|
## 📄 License
|
|
84
84
|
|
|
85
|
-
See the [LICENSE](LICENSE) file for our project's licensing.
|
|
85
|
+
See the [LICENSE](https://github.com/aws/aws-durable-execution-sdk-python/blob/main/LICENSE) file for our project's licensing.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aws-durable-execution-sdk-python"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = 'AWS Durable Execution SDK for Python'
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
keywords = []
|
|
13
|
+
authors = [{ name = "AWS durable-execution-dev", email = "durable-execution-dev@amazon.com" }]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
22
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
23
|
+
]
|
|
24
|
+
dependencies = ["boto3>=1.42.1"]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Documentation = "https://github.com/aws/aws-durable-execution-sdk-python#readme"
|
|
28
|
+
Issues = "https://github.com/aws/aws-durable-execution-sdk-python/issues"
|
|
29
|
+
Source = "https://github.com/aws/aws-durable-execution-sdk-python"
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.sdist.force-include]
|
|
32
|
+
"../../LICENSE" = "LICENSE"
|
|
33
|
+
"../../NOTICE" = "NOTICE"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.build.targets.wheel]
|
|
36
|
+
packages = ["src/aws_durable_execution_sdk_python"]
|
|
37
|
+
|
|
38
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
39
|
+
"../../LICENSE" = "aws_durable_execution_sdk_python/LICENSE"
|
|
40
|
+
"../../NOTICE" = "aws_durable_execution_sdk_python/NOTICE"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.version]
|
|
43
|
+
path = "src/aws_durable_execution_sdk_python/__about__.py"
|
|
44
|
+
|
|
45
|
+
[tool.coverage.run]
|
|
46
|
+
source_pkgs = ["aws_durable_execution_sdk_python"]
|
|
47
|
+
branch = true
|
|
48
|
+
parallel = true
|
|
49
|
+
omit = ["src/aws_durable_execution_sdk_python/__about__.py"]
|
|
50
|
+
|
|
51
|
+
[tool.coverage.paths]
|
|
52
|
+
aws_durable_execution_sdk_python = [
|
|
53
|
+
"src/aws_durable_execution_sdk_python",
|
|
54
|
+
"*/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.coverage.report]
|
|
58
|
+
exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff]
|
|
61
|
+
line-length = 88
|
|
62
|
+
target-version = "py311"
|
|
63
|
+
|
|
64
|
+
[tool.ruff.lint]
|
|
65
|
+
preview = true
|
|
66
|
+
select = ["E4", "E7", "E9", "F", "TID252"] # pycodestyle (E4/E7/E9) + Pyflakes + absolute imports
|
|
67
|
+
|
|
68
|
+
[tool.ruff.lint.isort]
|
|
69
|
+
known-first-party = ["aws_durable_execution_sdk_python"]
|
|
70
|
+
force-single-line = false
|
|
71
|
+
lines-after-imports = 2
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint.per-file-ignores]
|
|
74
|
+
"tests/**" = [
|
|
75
|
+
"ARG001",
|
|
76
|
+
"ARG002",
|
|
77
|
+
"ARG005",
|
|
78
|
+
"S101",
|
|
79
|
+
"PLR2004",
|
|
80
|
+
"PLR6301",
|
|
81
|
+
"SIM117",
|
|
82
|
+
"TRY301",
|
|
83
|
+
]
|
|
@@ -25,6 +25,7 @@ from aws_durable_execution_sdk_python.exceptions import (
|
|
|
25
25
|
|
|
26
26
|
# Core decorator - used in every durable function
|
|
27
27
|
from aws_durable_execution_sdk_python.execution import durable_execution
|
|
28
|
+
from aws_durable_execution_sdk_python.retries import WithRetryConfig, with_retry
|
|
28
29
|
|
|
29
30
|
# Essential context types - passed to user functions
|
|
30
31
|
from aws_durable_execution_sdk_python.types import StepContext
|
|
@@ -38,10 +39,12 @@ __all__ = [
|
|
|
38
39
|
"ParallelBranch",
|
|
39
40
|
"StepContext",
|
|
40
41
|
"ValidationError",
|
|
42
|
+
"WithRetryConfig",
|
|
41
43
|
"__version__",
|
|
42
44
|
"durable_execution",
|
|
43
45
|
"durable_parallel_branch",
|
|
44
46
|
"durable_step",
|
|
45
47
|
"durable_wait_for_callback",
|
|
46
48
|
"durable_with_child_context",
|
|
49
|
+
"with_retry",
|
|
47
50
|
]
|
|
@@ -59,7 +59,7 @@ class TimerScheduler:
|
|
|
59
59
|
"""Manage timed suspend tasks with a background timer thread."""
|
|
60
60
|
|
|
61
61
|
def __init__(
|
|
62
|
-
self, resubmit_callback: Callable[[ExecutableWithState], None]
|
|
62
|
+
self, resubmit_callback: Callable[[list[ExecutableWithState]], None]
|
|
63
63
|
) -> None:
|
|
64
64
|
self.resubmit_callback = resubmit_callback
|
|
65
65
|
self._pending_resumes: list[tuple[float, int, ExecutableWithState]] = []
|
|
@@ -114,18 +114,31 @@ class TimerScheduler:
|
|
|
114
114
|
|
|
115
115
|
current_time = time.time()
|
|
116
116
|
if current_time >= next_resume_time:
|
|
117
|
-
#
|
|
117
|
+
# Drain every due resume under the lock, transitioning each to
|
|
118
|
+
# PENDING atomically with the pop. Keeping pop+reset_to_pending
|
|
119
|
+
# together is required: should_execution_suspend reads branch
|
|
120
|
+
# status without this lock, so an item that is removed from the
|
|
121
|
+
# heap but still SUSPENDED_WITH_TIMEOUT could trigger a spurious
|
|
122
|
+
# parent suspend.
|
|
123
|
+
ready: list[ExecutableWithState] = []
|
|
118
124
|
with self._lock:
|
|
119
|
-
|
|
120
|
-
# since the first peek on next_resume_time further up
|
|
121
|
-
if ( # pragma: no branch
|
|
125
|
+
while (
|
|
122
126
|
self._pending_resumes
|
|
123
127
|
and self._pending_resumes[0][0] <= current_time
|
|
124
128
|
):
|
|
125
129
|
_, _, exe_state = heapq.heappop(self._pending_resumes)
|
|
126
130
|
if exe_state.can_resume:
|
|
127
131
|
exe_state.reset_to_pending()
|
|
128
|
-
|
|
132
|
+
ready.append(exe_state)
|
|
133
|
+
# Resubmit outside the lock. Only the heap pop and the PENDING
|
|
134
|
+
# transition need the lock. The checkpoint refresh is a blocking
|
|
135
|
+
# network call and the submit hands work to the pool, so running
|
|
136
|
+
# them off the lock keeps timed resumes from serializing behind
|
|
137
|
+
# the network round trip and keeps the timer thread from
|
|
138
|
+
# re-entering this non-reentrant lock when a submitted future
|
|
139
|
+
# completes inline and its done-callback calls schedule_resume.
|
|
140
|
+
if ready:
|
|
141
|
+
self.resubmit_callback(ready)
|
|
129
142
|
else:
|
|
130
143
|
# Wait until next resume time
|
|
131
144
|
wait_time = min(next_resume_time - current_time, 0.1)
|
|
@@ -169,6 +182,7 @@ class ConcurrentExecutor(ABC, Generic[CallableType, ResultType]):
|
|
|
169
182
|
# Event-driven state tracking for when the executor is done
|
|
170
183
|
self._completion_event = threading.Event()
|
|
171
184
|
self._suspend_exception: SuspendExecution | None = None
|
|
185
|
+
self._resume_error: Exception | None = None
|
|
172
186
|
|
|
173
187
|
# ExecutionCounters will keep track of completion criteria and on-going counters
|
|
174
188
|
min_successful = self.completion_config.min_successful or len(self.executables)
|
|
@@ -222,11 +236,32 @@ class ConcurrentExecutor(ABC, Generic[CallableType, ResultType]):
|
|
|
222
236
|
]
|
|
223
237
|
self._completion_event.clear()
|
|
224
238
|
self._suspend_exception = None
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
239
|
+
self._resume_error = None
|
|
240
|
+
|
|
241
|
+
def resubmitter(ready: list[ExecutableWithState]) -> None:
|
|
242
|
+
"""Resubmit a wave of timed-suspended tasks.
|
|
243
|
+
|
|
244
|
+
One checkpoint refresh serves the whole due wave: the fetch returns
|
|
245
|
+
all operations, so every resumed branch reads fresh state. The
|
|
246
|
+
refresh only raises when the background checkpoint subsystem has
|
|
247
|
+
failed, which is terminal for the whole execution, so record the
|
|
248
|
+
error and wake the parent to re-raise it. Catching here keeps the
|
|
249
|
+
single timer thread alive so a failure does not strand the other
|
|
250
|
+
pending resumes.
|
|
251
|
+
"""
|
|
252
|
+
try:
|
|
253
|
+
execution_state.create_checkpoint()
|
|
254
|
+
except Exception as exc: # noqa: BLE001
|
|
255
|
+
# resubmitter runs only on the single timer thread, so this
|
|
256
|
+
# check-then-set needs no lock. First error wins: keep the
|
|
257
|
+
# earliest failure if several waves fail before execute() reads
|
|
258
|
+
# it (they are the same terminal checkpoint failure anyway).
|
|
259
|
+
if self._resume_error is None: # pragma: no branch
|
|
260
|
+
self._resume_error = exc
|
|
261
|
+
self._completion_event.set()
|
|
262
|
+
return
|
|
263
|
+
for executable_with_state in ready:
|
|
264
|
+
submit_task(executable_with_state)
|
|
230
265
|
|
|
231
266
|
thread_executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
232
267
|
try:
|
|
@@ -259,6 +294,12 @@ class ConcurrentExecutor(ABC, Generic[CallableType, ResultType]):
|
|
|
259
294
|
for future in futures:
|
|
260
295
|
future.cancel()
|
|
261
296
|
|
|
297
|
+
# A timed resume failed to refresh state (terminal checkpoint
|
|
298
|
+
# subsystem failure). Re-raise so the invocation fails and the
|
|
299
|
+
# backend retries from the last durable checkpoint.
|
|
300
|
+
if self._resume_error is not None:
|
|
301
|
+
raise self._resume_error
|
|
302
|
+
|
|
262
303
|
# Suspend execution if everything done and at least one of the tasks raised a suspend exception.
|
|
263
304
|
if self._suspend_exception:
|
|
264
305
|
raise self._suspend_exception
|
|
@@ -428,11 +469,33 @@ class ConcurrentExecutor(ABC, Generic[CallableType, ResultType]):
|
|
|
428
469
|
# For FLAT `child_handler` skips checkpoints, so not used.
|
|
429
470
|
# Construct it unconditionally to keep the call simple.
|
|
430
471
|
operation_identifier = OperationIdentifier(
|
|
431
|
-
operation_id,
|
|
432
|
-
|
|
433
|
-
|
|
472
|
+
operation_id=operation_id,
|
|
473
|
+
sub_type=self.sub_type_iteration,
|
|
474
|
+
parent_id=executor_context._parent_id, # noqa: SLF001
|
|
475
|
+
name=name,
|
|
434
476
|
)
|
|
435
477
|
|
|
478
|
+
# The branch/iteration container op is resolved here via child_handler,
|
|
479
|
+
# bypassing context.run_in_child_context and therefore the parent's
|
|
480
|
+
# `_replay_aware`. Replicate the two things `_replay_aware` would have
|
|
481
|
+
# done for this container op while replaying:
|
|
482
|
+
# 1. Existence flip: a brand-new branch (no checkpoint) is new work,
|
|
483
|
+
# so the child must start in NEW rather than inheriting REPLAY —
|
|
484
|
+
# otherwise logs before the branch's first inner op are wrongly
|
|
485
|
+
# de-duplicated during a map/parallel replay.
|
|
486
|
+
# 2. Replay hook: a branch that already has a checkpoint was observed
|
|
487
|
+
# in a prior invocation, so emit the plugin replay hook (once).
|
|
488
|
+
# Virtual (FLAT) branches do not checkpoint themselves, so neither
|
|
489
|
+
# applies; their inner operations still self-correct via `_replay_aware`.
|
|
490
|
+
if not is_virtual and child_context.is_replaying():
|
|
491
|
+
branch_checkpoint = child_context.state.get_checkpoint_result(operation_id)
|
|
492
|
+
if not branch_checkpoint.is_existent():
|
|
493
|
+
child_context._set_replay_status_new() # noqa: SLF001
|
|
494
|
+
elif branch_checkpoint.operation is not None:
|
|
495
|
+
child_context.state.emit_operation_replay_hook(
|
|
496
|
+
branch_checkpoint.operation
|
|
497
|
+
)
|
|
498
|
+
|
|
436
499
|
def run_in_child_handler() -> ResultType:
|
|
437
500
|
return self.execute_item(child_context, executable)
|
|
438
501
|
|
|
@@ -447,7 +510,6 @@ class ConcurrentExecutor(ABC, Generic[CallableType, ResultType]):
|
|
|
447
510
|
is_virtual=is_virtual,
|
|
448
511
|
),
|
|
449
512
|
)
|
|
450
|
-
child_context.state.track_replay(operation_id=operation_id)
|
|
451
513
|
return result
|
|
452
514
|
|
|
453
515
|
def replay(self, execution_state: ExecutionState, executor_context: DurableContext):
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import math
|
|
5
6
|
import random
|
|
6
7
|
from dataclasses import dataclass, field
|
|
7
8
|
from enum import Enum, StrEnum
|
|
@@ -589,5 +590,16 @@ class JitterStrategy(StrEnum):
|
|
|
589
590
|
# Full jitter: random(0, delay)
|
|
590
591
|
return random.random() * delay # noqa: S311
|
|
591
592
|
|
|
593
|
+
def finalize_delay(self, base_delay: float) -> int:
|
|
594
|
+
"""Apply jitter, round up, and clamp to a minimum of 1 second.
|
|
595
|
+
|
|
596
|
+
Args:
|
|
597
|
+
base_delay: The base delay value before jitter is applied
|
|
598
|
+
|
|
599
|
+
Returns:
|
|
600
|
+
The final delay in whole seconds, at least 1
|
|
601
|
+
"""
|
|
602
|
+
return max(1, math.ceil(self.apply_jitter(base_delay)))
|
|
603
|
+
|
|
592
604
|
|
|
593
605
|
# endregion Jitter
|