Skip to content

Fix/resilient thread based heartbeater#1443

Draft
SanilK2108 wants to merge 6 commits intomainfrom
fix/resilient-thread-based-heartbeater
Draft

Fix/resilient thread based heartbeater#1443
SanilK2108 wants to merge 6 commits intomainfrom
fix/resilient-thread-based-heartbeater

Conversation

@SanilK2108
Copy link
Copy Markdown
Collaborator

Changelog

  • to be added

Additional context (e.g. screenshots, logs, links)

  • to be added

Checklist

  • Additional tests added
  • All CI checks passed
  • Relevant documentation updated

Copyleft License Compliance

  • Have you used any code that is subject to a Copyleft license (e.g., GPL, AGPL, LGPL)?
  • If yes, have you modified the code in the context of this project? please share additional details.

anuj-atlan and others added 6 commits April 15, 2026 10:59
Move heartbeat mechanism from asyncio task to background thread for both
async and sync activities. This prevents event loop starvation when async
activities call blocking/sync code (e.g. DaprClient, subprocess, requests).

Also fix silent heartbeat death: both send_periodic_heartbeat (async) and
send_periodic_heartbeat_sync now catch exceptions and retry on the next
interval instead of dying permanently on the first transient error.

Signed-off-by: Anuj Agrawal <anuj.agrawal@atlan.com>
On consecutive heartbeat failures, apply exponential backoff (2^n,
capped at 5x base delay) to avoid hammering an unhealthy Temporal
server. Reset to normal interval after a successful heartbeat.
Logs recovery with failure count for observability.

Signed-off-by: Anuj Agrawal <anuj.agrawal@atlan.com>
…nd activity

If the heartbeat thread crashes (BaseException escaping retry logic), the
activity now detects it and fails fast instead of running to completion
without heartbeats. For async activities, a monitor task races against the
activity via asyncio.wait. For sync activities, thread_failed is checked
after the function returns.

Adds tests proving:
- heartbeats continue when the event loop is blocked by sync code
- async activity is cancelled when the heartbeat thread crashes
- sync activity raises when the heartbeat thread crashed during execution
…t timeout

- Remove send_periodic_heartbeat (async version) which is no longer
  called after the switch to thread-based heartbeating, along with its
  tests.
- Cap exponential backoff in send_periodic_heartbeat_sync at the
  heartbeat timeout (delay * 3) instead of 5x the interval. Previously
  backoff could reach 200s with a 120s timeout, meaning Temporal would
  kill the activity before the next retry attempt.
@snykgituser
Copy link
Copy Markdown

snykgituser commented Apr 17, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

📜 Docstring Coverage Report

RESULT: PASSED (minimum: 30.0%, actual: 80.1%)

Detailed Coverage Report
======= Coverage for /home/runner/work/application-sdk/application-sdk/ ========
----------------------------------- Summary ------------------------------------
| Name                                                                              | Total | Miss | Cover | Cover% |
|-----------------------------------------------------------------------------------|-------|------|-------|--------|
| application_sdk/__init__.py                                                       |     1 |    0 |     1 |   100% |
| application_sdk/constants.py                                                      |     2 |    0 |     2 |   100% |
| application_sdk/version.py                                                        |     1 |    0 |     1 |   100% |
| application_sdk/worker.py                                                         |     8 |    1 |     7 |    88% |
| application_sdk/activities/__init__.py                                            |    10 |    0 |    10 |   100% |
| application_sdk/activities/lock_management.py                                     |     3 |    0 |     3 |   100% |
| application_sdk/activities/common/__init__.py                                     |     1 |    1 |     0 |     0% |
| application_sdk/activities/common/models.py                                       |     3 |    1 |     2 |    67% |
| application_sdk/activities/common/sql_utils.py                                    |     6 |    1 |     5 |    83% |
| application_sdk/activities/common/utils.py                                        |    12 |    3 |     9 |    75% |
| application_sdk/activities/metadata_extraction/__init__.py                        |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/base.py                            |     6 |    1 |     5 |    83% |
| application_sdk/activities/metadata_extraction/incremental.py                     |    19 |    0 |    19 |   100% |
| application_sdk/activities/metadata_extraction/rest.py                            |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/sql.py                             |    20 |    3 |    17 |    85% |
| application_sdk/activities/query_extraction/__init__.py                           |     1 |    1 |     0 |     0% |
| application_sdk/activities/query_extraction/sql.py                                |    13 |    1 |    12 |    92% |
| application_sdk/application/__init__.py                                           |    15 |    6 |     9 |    60% |
| application_sdk/application/metadata_extraction/sql.py                            |    12 |    4 |     8 |    67% |
| application_sdk/clients/__init__.py                                               |     4 |    0 |     4 |   100% |
| application_sdk/clients/atlan.py                                                  |     5 |    3 |     2 |    40% |
| application_sdk/clients/atlan_auth.py                                             |    10 |    0 |    10 |   100% |
| application_sdk/clients/base.py                                                   |     6 |    1 |     5 |    83% |
| application_sdk/clients/models.py                                                 |     3 |    0 |     3 |   100% |
| application_sdk/clients/redis.py                                                  |    27 |    0 |    27 |   100% |
| application_sdk/clients/sql.py                                                    |    23 |    0 |    23 |   100% |
| application_sdk/clients/ssl_utils.py                                              |     8 |    0 |     8 |   100% |
| application_sdk/clients/temporal.py                                               |    16 |    1 |    15 |    94% |
| application_sdk/clients/utils.py                                                  |     2 |    1 |     1 |    50% |
| application_sdk/clients/workflow.py                                               |     9 |    2 |     7 |    78% |
| application_sdk/clients/azure/__init__.py                                         |     1 |    0 |     1 |   100% |
| application_sdk/clients/azure/auth.py                                             |     7 |    0 |     7 |   100% |
| application_sdk/clients/azure/client.py                                           |    13 |    0 |    13 |   100% |
| application_sdk/common/__init__.py                                                |     1 |    1 |     0 |     0% |
| application_sdk/common/aws_utils.py                                               |    10 |    1 |     9 |    90% |
| application_sdk/common/error_codes.py                                             |    14 |    2 |    12 |    86% |
| application_sdk/common/file_converter.py                                          |     9 |    5 |     4 |    44% |
| application_sdk/common/file_ops.py                                                |    16 |    1 |    15 |    94% |
| application_sdk/common/path.py                                                    |     2 |    1 |     1 |    50% |
| application_sdk/common/types.py                                                   |     2 |    1 |     1 |    50% |
| application_sdk/common/utils.py                                                   |    17 |    2 |    15 |    88% |
| application_sdk/common/incremental/__init__.py                                    |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/helpers.py                                     |    12 |    0 |    12 |   100% |
| application_sdk/common/incremental/marker.py                                      |     5 |    0 |     5 |   100% |
| application_sdk/common/incremental/models.py                                      |    11 |    0 |    11 |   100% |
| application_sdk/common/incremental/column_extraction/__init__.py                  |     1 |    0 |     1 |   100% |
| application_sdk/common/incremental/column_extraction/analysis.py                  |     3 |    0 |     3 |   100% |
| application_sdk/common/incremental/column_extraction/backfill.py                  |     3 |    0 |     3 |   100% |
| application_sdk/common/incremental/state/__init__.py                              |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/state/ancestral_merge.py                       |     3 |    0 |     3 |   100% |
| application_sdk/common/incremental/state/incremental_diff.py                      |     4 |    0 |     4 |   100% |
| application_sdk/common/incremental/state/state_reader.py                          |     2 |    0 |     2 |   100% |
| application_sdk/common/incremental/state/state_writer.py                          |     9 |    0 |     9 |   100% |
| application_sdk/common/incremental/state/table_scope.py                           |     8 |    0 |     8 |   100% |
| application_sdk/common/incremental/storage/__init__.py                            |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/storage/duckdb_utils.py                        |    12 |    2 |    10 |    83% |
| application_sdk/common/incremental/storage/rocksdb_utils.py                       |     3 |    0 |     3 |   100% |
| application_sdk/decorators/__init__.py                                            |     1 |    1 |     0 |     0% |
| application_sdk/decorators/locks.py                                               |     3 |    2 |     1 |    33% |
| application_sdk/decorators/mcp_tool.py                                            |     3 |    1 |     2 |    67% |
| application_sdk/docgen/__init__.py                                                |     5 |    2 |     3 |    60% |
| application_sdk/docgen/exporters/__init__.py                                      |     1 |    1 |     0 |     0% |
| application_sdk/docgen/exporters/mkdocs.py                                        |     7 |    3 |     4 |    57% |
| application_sdk/docgen/models/__init__.py                                         |     1 |    1 |     0 |     0% |
| application_sdk/docgen/models/export/__init__.py                                  |     1 |    1 |     0 |     0% |
| application_sdk/docgen/models/export/page.py                                      |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/__init__.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/customer.py                                |     3 |    1 |     2 |    67% |
| application_sdk/docgen/models/manifest/internal.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/metadata.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/page.py                                    |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/section.py                                 |     2 |    1 |     1 |    50% |
| application_sdk/docgen/parsers/__init__.py                                        |     1 |    1 |     0 |     0% |
| application_sdk/docgen/parsers/directory.py                                       |    13 |    2 |    11 |    85% |
| application_sdk/docgen/parsers/manifest.py                                        |     6 |    1 |     5 |    83% |
| application_sdk/handlers/__init__.py                                              |     8 |    1 |     7 |    88% |
| application_sdk/handlers/base.py                                                  |     7 |    1 |     6 |    86% |
| application_sdk/handlers/sql.py                                                   |    19 |    6 |    13 |    68% |
| application_sdk/interceptors/__init__.py                                          |     1 |    1 |     0 |     0% |
| application_sdk/interceptors/activity_failure_logging.py                          |     8 |    0 |     8 |   100% |
| application_sdk/interceptors/cleanup.py                                           |     7 |    1 |     6 |    86% |
| application_sdk/interceptors/correlation_context.py                               |    13 |    0 |    13 |   100% |
| application_sdk/interceptors/events.py                                            |     9 |    1 |     8 |    89% |
| application_sdk/interceptors/lock.py                                              |    10 |    2 |     8 |    80% |
| application_sdk/interceptors/models.py                                            |    13 |    1 |    12 |    92% |
| application_sdk/interceptors/outputs.py                                           |     8 |    0 |     8 |   100% |
| application_sdk/io/__init__.py                                                    |    25 |    0 |    25 |   100% |
| application_sdk/io/json.py                                                        |    15 |    1 |    14 |    93% |
| application_sdk/io/parquet.py                                                     |    22 |    1 |    21 |    95% |
| application_sdk/io/utils.py                                                       |     8 |    1 |     7 |    88% |
| application_sdk/observability/__init__.py                                         |     1 |    1 |     0 |     0% |
| application_sdk/observability/context.py                                          |     1 |    0 |     1 |   100% |
| application_sdk/observability/logger_adaptor.py                                   |    35 |    2 |    33 |    94% |
| application_sdk/observability/metrics_adaptor.py                                  |    12 |    1 |    11 |    92% |
| application_sdk/observability/models.py                                           |     5 |    1 |     4 |    80% |
| application_sdk/observability/observability.py                                    |    25 |    1 |    24 |    96% |
| application_sdk/observability/segment_client.py                                   |    14 |    2 |    12 |    86% |
| application_sdk/observability/traces_adaptor.py                                   |    16 |    1 |    15 |    94% |
| application_sdk/observability/utils.py                                            |     4 |    1 |     3 |    75% |
| application_sdk/observability/decorators/observability_decorator.py               |     7 |    4 |     3 |    43% |
| application_sdk/server/__init__.py                                                |     4 |    0 |     4 |   100% |
| application_sdk/server/fastapi/__init__.py                                        |    26 |    5 |    21 |    81% |
| application_sdk/server/fastapi/models.py                                          |    32 |   28 |     4 |    12% |
| application_sdk/server/fastapi/utils.py                                           |     5 |    0 |     5 |   100% |
| application_sdk/server/fastapi/middleware/logmiddleware.py                        |     4 |    4 |     0 |     0% |
| application_sdk/server/fastapi/middleware/metrics.py                              |     3 |    3 |     0 |     0% |
| application_sdk/server/fastapi/routers/__init__.py                                |     1 |    1 |     0 |     0% |
| application_sdk/server/fastapi/routers/server.py                                  |     8 |    2 |     6 |    75% |
| application_sdk/server/mcp/__init__.py                                            |     1 |    1 |     0 |     0% |
| application_sdk/server/mcp/models.py                                              |     2 |    2 |     0 |     0% |
| application_sdk/server/mcp/server.py                                              |     5 |    0 |     5 |   100% |
| application_sdk/services/__init__.py                                              |     1 |    0 |     1 |   100% |
| application_sdk/services/_utils.py                                                |     2 |    1 |     1 |    50% |
| application_sdk/services/atlan_storage.py                                         |     5 |    0 |     5 |   100% |
| application_sdk/services/eventstore.py                                            |     5 |    0 |     5 |   100% |
| application_sdk/services/objectstore.py                                           |    17 |    0 |    17 |   100% |
| application_sdk/services/secretstore.py                                           |    14 |    0 |    14 |   100% |
| application_sdk/services/statestore.py                                            |     9 |    1 |     8 |    89% |
| application_sdk/test_utils/__init__.py                                            |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/workflow_monitoring.py                                 |     3 |    0 |     3 |   100% |
| application_sdk/test_utils/e2e/__init__.py                                        |    14 |    2 |    12 |    86% |
| application_sdk/test_utils/e2e/base.py                                            |    16 |    2 |    14 |    88% |
| application_sdk/test_utils/e2e/client.py                                          |    10 |    2 |     8 |    80% |
| application_sdk/test_utils/e2e/conftest.py                                        |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/e2e/utils.py                                           |     3 |    1 |     2 |    67% |
| application_sdk/test_utils/hypothesis/__init__.py                                 |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/__init__.py                      |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/sql_client.py                    |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/temporal.py                      |     6 |    1 |     5 |    83% |
| application_sdk/test_utils/hypothesis/strategies/clients/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/clients/sql.py                   |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/common/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/common/logger.py                 |     3 |    0 |     3 |   100% |
| application_sdk/test_utils/hypothesis/strategies/handlers/__init__.py             |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/__init__.py         |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/sql_metadata.py     |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/sql_preflight.py    |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/json_input.py             |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/parquet_input.py          |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/outputs/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/outputs/json_output.py           |     2 |    1 |     1 |    50% |
| application_sdk/test_utils/hypothesis/strategies/outputs/statestore.py            |     3 |    1 |     2 |    67% |
| application_sdk/test_utils/hypothesis/strategies/server/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/server/fastapi/__init__.py       |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/__init__.py                       |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/config_loader.py                  |    10 |    4 |     6 |    60% |
| application_sdk/test_utils/scale_data_generator/data_generator.py                 |    10 |    3 |     7 |    70% |
| application_sdk/test_utils/scale_data_generator/driver.py                         |     3 |    3 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/__init__.py        |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/base.py            |     7 |    3 |     4 |    57% |
| application_sdk/test_utils/scale_data_generator/output_handler/csv_handler.py     |     5 |    5 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/json_handler.py    |     5 |    5 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/parquet_handler.py |     6 |    6 |     0 |     0% |
| application_sdk/transformers/__init__.py                                          |     3 |    1 |     2 |    67% |
| application_sdk/transformers/atlas/__init__.py                                    |     6 |    1 |     5 |    83% |
| application_sdk/transformers/atlas/sql.py                                         |    25 |    4 |    21 |    84% |
| application_sdk/transformers/common/__init__.py                                   |     1 |    1 |     0 |     0% |
| application_sdk/transformers/common/utils.py                                      |     6 |    0 |     6 |   100% |
| application_sdk/transformers/query/__init__.py                                    |    11 |    2 |     9 |    82% |
| application_sdk/workflows/__init__.py                                             |     4 |    0 |     4 |   100% |
| application_sdk/workflows/metadata_extraction/__init__.py                         |     3 |    1 |     2 |    67% |
| application_sdk/workflows/metadata_extraction/incremental_sql.py                  |     5 |    0 |     5 |   100% |
| application_sdk/workflows/metadata_extraction/sql.py                              |     7 |    0 |     7 |   100% |
| application_sdk/workflows/outputs/__init__.py                                     |     2 |    0 |     2 |   100% |
| application_sdk/workflows/outputs/collector.py                                    |     9 |    0 |     9 |   100% |
| application_sdk/workflows/outputs/models.py                                       |     3 |    0 |     3 |   100% |
| application_sdk/workflows/query_extraction/__init__.py                            |     2 |    2 |     0 |     0% |
| application_sdk/workflows/query_extraction/sql.py                                 |     4 |    0 |     4 |   100% |
| examples/application_custom_fastapi.py                                            |    14 |   14 |     0 |     0% |
| examples/application_fastapi.py                                                   |     9 |    9 |     0 |     0% |
| examples/application_hello_world.py                                               |     7 |    7 |     0 |     0% |
| examples/application_sql.py                                                       |     5 |    4 |     1 |    20% |
| examples/application_sql_miner.py                                                 |     5 |    4 |     1 |    20% |
| examples/application_sql_with_custom_pyatlan_transformer.py                       |    11 |    9 |     2 |    18% |
| examples/application_sql_with_custom_transformer.py                               |     9 |    8 |     1 |    11% |
| examples/run_examples.py                                                          |     2 |    1 |     1 |    50% |
| tests/__init__.py                                                                 |     1 |    1 |     0 |     0% |
| tests/conftest.py                                                                 |     4 |    0 |     4 |   100% |
| tests/integration/__init__.py                                                     |     1 |    0 |     1 |   100% |
| tests/integration/test_output_e2e.py                                              |    16 |    0 |    16 |   100% |
| tests/unit/__init__.py                                                            |     1 |    1 |     0 |     0% |
| tests/unit/test_worker.py                                                         |    28 |    8 |    20 |    71% |
| tests/unit/activities/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/activities/test_activities.py                                          |    41 |    3 |    38 |    93% |
| tests/unit/activities/test_base_metadata_extraction_activities.py                 |     7 |    0 |     7 |   100% |
| tests/unit/activities/test_connection_normalization.py                            |    25 |    7 |    18 |    72% |
| tests/unit/activities/test_lock_management.py                                     |    12 |    0 |    12 |   100% |
| tests/unit/activities/common/__init__.py                                          |     1 |    1 |     0 |     0% |
| tests/unit/activities/common/test_sql_utils.py                                    |     4 |    1 |     3 |    75% |
| tests/unit/activities/common/test_utils.py                                        |    47 |   33 |    14 |    30% |
| tests/unit/activities/metadata_extraction/__init__.py                             |     1 |    1 |     0 |     0% |
| tests/unit/activities/metadata_extraction/test_credential_loading.py              |    14 |    4 |    10 |    71% |
| tests/unit/activities/metadata_extraction/test_sql.py                             |    56 |   38 |    18 |    32% |
| tests/unit/activities/query_extraction/__init__.py                                |     1 |    1 |     0 |     0% |
| tests/unit/application/__init__.py                                                |     1 |    1 |     0 |     0% |
| tests/unit/application/test_application.py                                        |    44 |    3 |    41 |    93% |
| tests/unit/application/test_manifest.py                                           |    16 |    3 |    13 |    81% |
| tests/unit/application/metadata_extraction/test_sql.py                            |    36 |    6 |    30 |    83% |
| tests/unit/clients/__init__.py                                                    |     1 |    1 |     0 |     0% |
| tests/unit/clients/test_async_sql_client.py                                       |    15 |   14 |     1 |     7% |
| tests/unit/clients/test_atlan_auth.py                                             |    11 |    0 |    11 |   100% |
| tests/unit/clients/test_atlan_client.py                                           |     7 |    7 |     0 |     0% |
| tests/unit/clients/test_atlanauth.py                                              |    11 |    1 |    10 |    91% |
| tests/unit/clients/test_azure_auth.py                                             |    14 |    0 |    14 |   100% |
| tests/unit/clients/test_azure_client.py                                           |    19 |    0 |    19 |   100% |
| tests/unit/clients/test_base_client.py                                            |    23 |    1 |    22 |    96% |
| tests/unit/clients/test_redis_client.py                                           |    40 |    0 |    40 |   100% |
| tests/unit/clients/test_sql_client.py                                             |    28 |    6 |    22 |    79% |
| tests/unit/clients/test_ssl_utils.py                                              |    40 |    4 |    36 |    90% |
| tests/unit/clients/test_temporal_client.py                                        |    32 |    4 |    28 |    88% |
| tests/unit/common/test_aws_utils.py                                               |    30 |    1 |    29 |    97% |
| tests/unit/common/test_column_extraction.py                                       |    10 |    0 |    10 |   100% |
| tests/unit/common/test_credential_utils.py                                        |    30 |    1 |    29 |    97% |
| tests/unit/common/test_file_converter.py                                          |    29 |    0 |    29 |   100% |
| tests/unit/common/test_file_ops.py                                                |    21 |    0 |    21 |   100% |
| tests/unit/common/test_path.py                                                    |     6 |    0 |     6 |   100% |
| tests/unit/common/test_utils.py                                                   |    74 |    6 |    68 |    92% |
| tests/unit/common/test_utils_file_discovery.py                                    |    11 |    0 |    11 |   100% |
| tests/unit/common/incremental/__init__.py                                         |     1 |    1 |     0 |     0% |
| tests/unit/common/incremental/test_helpers.py                                     |    39 |    1 |    38 |    97% |
| tests/unit/common/incremental/test_marker.py                                      |    18 |    2 |    16 |    89% |
| tests/unit/common/incremental/test_models.py                                      |    15 |    0 |    15 |   100% |
| tests/unit/common/incremental/test_state_reader.py                                |     8 |    2 |     6 |    75% |
| tests/unit/common/incremental/test_state_writer.py                                |    22 |    1 |    21 |    95% |
| tests/unit/decorators/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/decorators/test_mcp_tool.py                                            |    56 |    4 |    52 |    93% |
| tests/unit/docgen/parsers/test_directory_parser.py                                |    14 |    3 |    11 |    79% |
| tests/unit/docgen/parsers/test_manifest_parser.py                                 |    12 |   12 |     0 |     0% |
| tests/unit/handlers/__init__.py                                                   |     1 |    1 |     0 |     0% |
| tests/unit/handlers/test_base_handler.py                                          |    26 |    2 |    24 |    92% |
| tests/unit/handlers/test_handler_configmap.py                                     |    11 |    0 |    11 |   100% |
| tests/unit/handlers/sql/test_auth.py                                              |    10 |    4 |     6 |    60% |
| tests/unit/handlers/sql/test_check_schemas_and_databases.py                       |    14 |    4 |    10 |    71% |
| tests/unit/handlers/sql/test_extract_allowed_schemas.py                           |    11 |    3 |     8 |    73% |
| tests/unit/handlers/sql/test_metadata.py                                          |    27 |   10 |    17 |    63% |
| tests/unit/handlers/sql/test_preflight_check.py                                   |    16 |   15 |     1 |     6% |
| tests/unit/handlers/sql/test_prepare_metadata.py                                  |    14 |    4 |    10 |    71% |
| tests/unit/handlers/sql/test_tables_check.py                                      |     9 |    6 |     3 |    33% |
| tests/unit/handlers/sql/test_validate_filters.py                                  |    12 |    4 |     8 |    67% |
| tests/unit/interceptors/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/interceptors/test_activity_failure_logging.py                          |    27 |    1 |    26 |    96% |
| tests/unit/interceptors/test_correlation_context.py                               |    44 |    0 |    44 |   100% |
| tests/unit/interceptors/test_output_interceptor.py                                |    35 |    3 |    32 |    91% |
| tests/unit/io/test_base_io.py                                                     |    28 |    3 |    25 |    89% |
| tests/unit/io/test_writer_data_integrity.py                                       |    12 |    5 |     7 |    58% |
| tests/unit/io/readers/test_json_reader.py                                         |    38 |   19 |    19 |    50% |
| tests/unit/io/readers/test_parquet_reader.py                                      |    60 |   38 |    22 |    37% |
| tests/unit/io/writers/test_json_writer.py                                         |     7 |    6 |     1 |    14% |
| tests/unit/io/writers/test_parquet_writer.py                                      |    57 |   10 |    47 |    82% |
| tests/unit/observability/__init__.py                                              |     1 |    1 |     0 |     0% |
| tests/unit/observability/test_logger_adaptor.py                                   |    54 |    4 |    50 |    93% |
| tests/unit/observability/test_metrics_adaptor.py                                  |    17 |    1 |    16 |    94% |
| tests/unit/observability/test_traces_adaptor.py                                   |    10 |    1 |     9 |    90% |
| tests/unit/server/__init__.py                                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/test_fastapi.py                                         |    77 |   27 |    50 |    65% |
| tests/unit/server/fastapi/test_fastapi_utils.py                                   |    34 |    0 |    34 |   100% |
| tests/unit/server/fastapi/test_manifest_and_configmaps.py                         |    17 |    7 |    10 |    59% |
| tests/unit/server/fastapi/routers/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/routers/server.py                                       |     1 |    1 |     0 |     0% |
| tests/unit/server/mcp/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/server/mcp/test_mcp_server.py                                          |    24 |    1 |    23 |    96% |
| tests/unit/services/test_atlan_storage.py                                         |    10 |    0 |    10 |   100% |
| tests/unit/services/test_eventstore.py                                            |    18 |    0 |    18 |   100% |
| tests/unit/services/test_objectstore.py                                           |    47 |    5 |    42 |    89% |
| tests/unit/services/test_statestore.py                                            |    14 |    0 |    14 |   100% |
| tests/unit/services/test_statestore_path_traversal.py                             |    23 |   17 |     6 |    26% |
| tests/unit/transformers/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/__init__.py                                         |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/test_column.py                                      |    17 |    6 |    11 |    65% |
| tests/unit/transformers/atlas/test_database.py                                    |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_function.py                                    |     9 |    5 |     4 |    44% |
| tests/unit/transformers/atlas/test_procedure.py                                   |     7 |    6 |     1 |    14% |
| tests/unit/transformers/atlas/test_schema.py                                      |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_table.py                                       |    13 |    6 |     7 |    54% |
| tests/unit/transformers/query/test_sql_transformer.py                             |    16 |    4 |    12 |    75% |
| tests/unit/transformers/query/test_sql_transformer_output_validation.py           |     5 |    2 |     3 |    60% |
| tests/unit/workflows/__init__.py                                                  |     1 |    0 |     1 |   100% |
| tests/unit/workflows/metadata_extraction/test_base_workflow.py                    |     7 |    0 |     7 |   100% |
| tests/unit/workflows/metadata_extraction/test_sql_output_paths.py                 |    10 |    0 |    10 |   100% |
| tests/unit/workflows/metadata_extraction/test_sql_workflow.py                     |     9 |    4 |     5 |    56% |
| tests/unit/workflows/outputs/__init__.py                                          |     1 |    0 |     1 |   100% |
| tests/unit/workflows/outputs/test_collector.py                                    |    39 |    0 |    39 |   100% |
| tests/unit/workflows/query_extraction/__init__.py                                 |     1 |    1 |     0 |     0% |
| tests/unit/workflows/query_extraction/test_sql.py                                 |     8 |    3 |     5 |    62% |
|-----------------------------------------------------------------------------------|-------|------|-------|--------|
| TOTAL                                                                             |  3159 |  725 |  2434 |  77.0% |
---------------- RESULT: PASSED (minimum: 30.0%, actual: 77.0%) ----------------

@github-actions
Copy link
Copy Markdown
Contributor

📦 Trivy Vulnerability Scan Results

Schema Version Created At Artifact Type
2 2026-04-17T08:55:21.934826765Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

requirements.txt

Vulnerabilities

Severity ID Package Version Fixed Version Title
🔴 CRITICAL CVE-2026-32871 fastmcp 2.14.2 3.2.0 fastmcp: FastMCP: Authenticated Server-Side Request Forgery via path traversal in OpenAPI path parameters
🟠 HIGH CVE-2026-27124 fastmcp 2.14.2 3.2.0 FastMCP: FastMCP OAuthProxy: FastMCP OAuthProxy: Unauthorized actions due to improper consent validation in GitHub OAuth
🟠 HIGH CVE-2026-34444 lupa 2.6 N/A lupa: Lupa: Arbitrary Code Execution due to inconsistent attribute filtering
uv.lock

Vulnerabilities

Severity ID Package Version Fixed Version Title
🔴 CRITICAL CVE-2026-32871 fastmcp 2.14.2 3.2.0 fastmcp: FastMCP: Authenticated Server-Side Request Forgery via path traversal in OpenAPI path parameters
🟠 HIGH CVE-2026-27124 fastmcp 2.14.2 3.2.0 FastMCP: FastMCP OAuthProxy: FastMCP OAuthProxy: Unauthorized actions due to improper consent validation in GitHub OAuth
🟠 HIGH CVE-2026-34444 lupa 2.6 N/A lupa: Lupa: Arbitrary Code Execution due to inconsistent attribute filtering

@github-actions
Copy link
Copy Markdown
Contributor

📦 Trivy Secret Scan Results

Schema Version Created At Artifact Type
2 2026-04-17T08:55:31.931629467Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

requirements.txt
uv.lock

@atlan-ci
Copy link
Copy Markdown
Collaborator

atlan-ci commented Apr 17, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
9328 6461 69% 0% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 61d8b38 by action🐍

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 17, 2026

🛠 Full Test Coverage Report: https://k.atlan.dev/coverage/application-sdk/pr/1443

@Aryamanz29
Copy link
Copy Markdown
Member

v3 relevance check: ✅ Still relevant — resilient heartbeater addresses a real v3 issue (heartbeat failures during Dapr health checks). Please rebase on latest main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants