Skip to content

Conversation

@abhishekagrawal-atlan
Copy link
Collaborator

Changelog

  • Added Atlas Query Transformer support for in application-sdk
  • Added for both AtlasTransformer as well as for QueryTransformer

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

  • Developed as part of Redshift Query Extraction effort.

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.

SanilK2108 and others added 2 commits June 15, 2025 23:45
* feat: basic eventstore completed

* fix: workflow and activity state cleanup

* refactor: move triggers to models

* fix: Fixed UI bug

* style: fix minor comment typo

* feat: Updated to use programmatic subscription with manifest file

* Merge branch 'main' into APP-6781-event-based-workflows

* chore: minor fix post-merge

* fix: general bug fixes

* fix: general bug fixes

* fix: Adding support for dropping events when no matcher is found

* fix: Bug fixes

* fix: fixes for http bindings

* Merge remote-tracking branch 'origin/APP-6781-event-based-workflows' into APP-6781-event-based-workflows

* fix: precommits

* fix: event naming

* fix: unit tests

* fix: unit tests

* fix: application->server

* fix: Removed the example sample app to move them to sample-apps repo

* chore: Removing unneeded code

* fix: unit tests

* fix: minor PR fixes

* chore: Updated eventstore name to be retrieved from env

* fix: Minor PR fixes

* fix: Minor fix self.event_subscriptions never set
Copilot AI review requested due to automatic review settings June 17, 2025 04:41
@snyk-io-us
Copy link

snyk-io-us bot commented Jun 17, 2025

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

security/snyk check is complete. No issues have been found. (View Details)

license/snyk check is complete. No issues have been found. (View Details)

code/snyk check is complete. No issues have been found. (View Details)

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

📜 Docstring Coverage Report

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

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                                                      |     1 |    0 |     1 |   100% |
| application_sdk/version.py                                                        |     1 |    0 |     1 |   100% |
| application_sdk/worker.py                                                         |     4 |    0 |     4 |   100% |
| application_sdk/activities/__init__.py                                            |     9 |    0 |     9 |   100% |
| application_sdk/activities/common/__init__.py                                     |     1 |    1 |     0 |     0% |
| application_sdk/activities/common/models.py                                       |     2 |    0 |     2 |   100% |
| application_sdk/activities/common/utils.py                                        |     5 |    1 |     4 |    80% |
| application_sdk/activities/metadata_extraction/__init__.py                        |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/rest.py                            |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/sql.py                             |    15 |    1 |    14 |    93% |
| application_sdk/activities/query_extraction/__init__.py                           |     1 |    1 |     0 |     0% |
| application_sdk/activities/query_extraction/sql.py                                |    10 |    1 |     9 |    90% |
| application_sdk/application/__init__.py                                           |    10 |    3 |     7 |    70% |
| application_sdk/application/metadata_extraction/sql.py                            |     7 |    1 |     6 |    86% |
| application_sdk/clients/__init__.py                                               |     4 |    0 |     4 |   100% |
| application_sdk/clients/sql.py                                                    |    15 |    0 |    15 |   100% |
| application_sdk/clients/temporal.py                                               |    19 |    1 |    18 |    95% |
| application_sdk/clients/utils.py                                                  |     2 |    1 |     1 |    50% |
| application_sdk/clients/workflow.py                                               |     9 |    2 |     7 |    78% |
| application_sdk/common/__init__.py                                                |     1 |    1 |     0 |     0% |
| application_sdk/common/aws_utils.py                                               |     4 |    1 |     3 |    75% |
| application_sdk/common/credential_utils.py                                        |     2 |    0 |     2 |   100% |
| application_sdk/common/dataframe_utils.py                                         |     2 |    1 |     1 |    50% |
| application_sdk/common/error_codes.py                                             |    14 |    2 |    12 |    86% |
| application_sdk/common/utils.py                                                   |    12 |    2 |    10 |    83% |
| 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                                              |     6 |    1 |     5 |    83% |
| application_sdk/handlers/sql.py                                                   |    16 |    3 |    13 |    81% |
| application_sdk/inputs/__init__.py                                                |     6 |    1 |     5 |    83% |
| application_sdk/inputs/iceberg.py                                                 |     7 |    3 |     4 |    57% |
| application_sdk/inputs/json.py                                                    |     8 |    2 |     6 |    75% |
| application_sdk/inputs/objectstore.py                                             |     4 |    1 |     3 |    75% |
| application_sdk/inputs/parquet.py                                                 |     8 |    1 |     7 |    88% |
| application_sdk/inputs/secretstore.py                                             |     6 |    1 |     5 |    83% |
| application_sdk/inputs/sql_query.py                                               |    11 |    1 |    10 |    91% |
| application_sdk/inputs/statestore.py                                              |     4 |    1 |     3 |    75% |
| application_sdk/observability/__init__.py                                         |     1 |    1 |     0 |     0% |
| application_sdk/observability/logger_adaptor.py                                   |    31 |    3 |    28 |    90% |
| application_sdk/observability/metrics_adaptor.py                                  |    16 |    2 |    14 |    88% |
| application_sdk/observability/observability.py                                    |    24 |    1 |    23 |    96% |
| application_sdk/observability/traces_adaptor.py                                   |    16 |    1 |    15 |    94% |
| application_sdk/observability/decorators/observability_decorator.py               |     7 |    4 |     3 |    43% |
| application_sdk/outputs/__init__.py                                               |     9 |    0 |     9 |   100% |
| application_sdk/outputs/eventstore.py                                             |    14 |    9 |     5 |    36% |
| application_sdk/outputs/iceberg.py                                                |     5 |    1 |     4 |    80% |
| application_sdk/outputs/json.py                                                   |     8 |    1 |     7 |    88% |
| application_sdk/outputs/objectstore.py                                            |     4 |    1 |     3 |    75% |
| application_sdk/outputs/parquet.py                                                |     7 |    1 |     6 |    86% |
| application_sdk/outputs/secretstore.py                                            |     3 |    1 |     2 |    67% |
| application_sdk/outputs/statestore.py                                             |     4 |    1 |     3 |    75% |
| application_sdk/server/__init__.py                                                |     4 |    0 |     4 |   100% |
| application_sdk/server/fastapi/__init__.py                                        |    22 |    4 |    18 |    82% |
| application_sdk/server/fastapi/models.py                                          |    25 |   25 |     0 |     0% |
| application_sdk/server/fastapi/utils.py                                           |     2 |    0 |     2 |   100% |
| application_sdk/server/fastapi/middleware/logmiddleware.py                        |     4 |    4 |     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/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/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                                         |    27 |    4 |    23 |    85% |
| application_sdk/transformers/common/__init__.py                                   |     1 |    1 |     0 |     0% |
| application_sdk/transformers/common/utils.py                                      |     5 |    0 |     5 |   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                         |     2 |    2 |     0 |     0% |
| application_sdk/workflows/metadata_extraction/sql.py                              |     7 |    0 |     7 |   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/unit/__init__.py                                                            |     1 |    1 |     0 |     0% |
| tests/unit/worker.py                                                              |     5 |    5 |     0 |     0% |
| tests/unit/activities/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/clients/__init__.py                                                    |     1 |    1 |     0 |     0% |
| tests/unit/clients/test_async_sql_client.py                                       |    13 |   13 |     0 |     0% |
| tests/unit/clients/test_sql_client.py                                             |    28 |    6 |    22 |    79% |
| tests/unit/clients/test_temporal_client.py                                        |    17 |   11 |     6 |    35% |
| tests/unit/common/test_logger_adapter.py                                          |    19 |    1 |    18 |    95% |
| tests/unit/common/test_metrics_adapter.py                                         |    14 |    1 |    13 |    93% |
| tests/unit/common/test_traces_adaptor.py                                          |    10 |    1 |     9 |    90% |
| tests/unit/common/test_utils.py                                                   |    25 |    5 |    20 |    80% |
| tests/unit/credentials/test_credential_utils.py                                   |    16 |    1 |    15 |    94% |
| 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/sql/test_auth.py                                              |    10 |    4 |     6 |    60% |
| tests/unit/handlers/sql/test_check_schemas_and_databases.py                       |    13 |    4 |     9 |    69% |
| 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/inputs/test_json_input.py                                              |     4 |    4 |     0 |     0% |
| tests/unit/outputs/test_iceberg.py                                                |    11 |    4 |     7 |    64% |
| tests/unit/outputs/test_json_output.py                                            |     7 |    6 |     1 |    14% |
| tests/unit/outputs/test_objectstore.py                                            |     9 |    8 |     1 |    11% |
| tests/unit/outputs/test_output.py                                                 |    19 |    6 |    13 |    68% |
| tests/unit/outputs/test_statestore.py                                             |    11 |   11 |     0 |     0% |
| tests/unit/server/__init__.py                                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/test__init__.py                                         |     8 |    3 |     5 |    62% |
| tests/unit/server/fastapi/routers/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/routers/server.py                                       |     1 |    1 |     0 |     0% |
| 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                             |    14 |    4 |    10 |    71% |
| tests/unit/transformers/query/test_sql_transformer_output_validation.py           |     5 |    2 |     3 |    60% |
| tests/unit/workflows/sql/__init__.py                                              |     1 |    1 |     0 |     0% |
| tests/unit/workflows/sql/test_workflow.py                                         |     9 |    4 |     5 |    56% |
|-----------------------------------------------------------------------------------|-------|------|-------|--------|
| TOTAL                                                                             |  1208 |  453 |   755 |  62.5% |
---------------- RESULT: PASSED (minimum: 30.0%, actual: 62.5%) ----------------

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

📦 Trivy Vulnerability Scan Results

Schema Version Created At Artifact Type
2 2025-06-17T05:16:35.735341117Z . filesystem

Report Summary

Target Type Vulnerabilities . filesystem ✅ None found

Scan Result Details

✅ No vulnerabilities found during the scan for ..

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

📦 Trivy Secret Scan Results

Schema Version Created At Artifact Type
2 2025-06-17T05:16:42.884288269Z . filesystem

Report Summary

Target Type Secrets . filesystem ✅ None found

Scan Result Details

✅ No secrets found during the scan for ..

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

🛠 Docs available at: https://k.atlan.dev/application-sdk/add_query_transformer

@atlan-ci
Copy link
Collaborator

atlan-ci commented Jun 17, 2025

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
5317 2876 54% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
application_sdk/transformers/atlas/init.py 79% 🟢
application_sdk/transformers/atlas/sql.py 61% 🟢
TOTAL 70% 🟢

updated for commit: 9f0b35b by action🐍

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds support for Atlas Query transformation and enhances event-driven workflow triggers in the FastAPI server.

  • Introduces a new Query transformer class and its YAML template for Atlas entities.
  • Refactors event publishing (EventStore.publish_event) and updates server to use Dapr-based event routing with EventWorkflowTrigger.
  • Updates tests to exercise the new event endpoint and adjusts project tooling (Dapr port).

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/server/fastapi/test__init__.py Refactored event-trigger tests to use httpx client
pyproject.toml Changed Dapr app port from 3000 to 8000
application_sdk/transformers/query/templates/query.yaml Added Atlas Query entity template
application_sdk/transformers/atlas/sql.py Added Query transformer class
application_sdk/test_utils/hypothesis/strategies/server/fastapi/init.py Switched event strategy from specific to generic
application_sdk/server/fastapi/models.py Added EventWorkflowRequest/Response models
application_sdk/server/fastapi/init.py Overhauled event routing, Dapr subscriptions, drop
application_sdk/outputs/eventstore.py Replaced create_event with publish_event and enrich metadata
application_sdk/constants.py Introduced EVENT_STORE_NAME constant
Comments suppressed due to low confidence (4)

tests/unit/server/fastapi/test__init__.py:96

  • [nitpick] The test docstring still refers to "hypothesis generated event data" although Hypothesis is no longer used; please update or remove the misleading docstring.
    async def test_event_trigger_success(self):

docs/docs/concepts/server.md:28

  • The description no longer mentions event_id, event_filters, or routing via Dapr; please update to reflect the new properties of EventWorkflowTrigger.
*   `EventWorkflowTrigger`: Triggers a workflow based on incoming events

application_sdk/test_utils/hypothesis/strategies/server/fastapi/init.py:64

  • Using st.builds(Event, event_type=..., event_name=..., data={}) will pass those as positional args after metadata, likely resulting in an invalid constructor call; consider supplying a default metadata argument or using keyword-only builds.
    Event,

application_sdk/transformers/atlas/sql.py:1244

  • [nitpick] The transformer reads obj.get("querytxt") but the field name is inconsistent with typical SQL conventions; please confirm the correct input key or rename to match the template's longRawQuery attribute.
            attributes["longRawQuery"] = obj.get("querytxt")

start-dapr = "dapr run --enable-api-logging --log-level debug --app-id app --app-port 8000 --dapr-http-port 3500 --dapr-grpc-port 50001 --dapr-http-max-request-size 1024 --resources-path components"
start-temporal = "temporal server start-dev --db-filename /tmp/temporal.db"
start-deps.shell = "poe start-dapr & poe start-temporal &"
stop-deps.shell = "lsof -ti:3000,3500,7233,50001 | xargs kill -9 2>/dev/null || true"
Copy link

Copilot AI Jun 17, 2025

Choose a reason for hiding this comment

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

The Dapr stop-deps command still targets port 3000, but the app now runs on 8000; update the stop-deps shell task to kill the correct port.

Suggested change
stop-deps.shell = "lsof -ti:3000,3500,7233,50001 | xargs kill -9 2>/dev/null || true"
stop-deps.shell = "lsof -ti:8000,3500,7233,50001 | xargs kill -9 2>/dev/null || true"

Copilot uses AI. Check for mistakes.
)

app.include_router(workflow_router, prefix="/workflows/v1")
self.app.include_router(self.workflow_router, prefix="/workflows/v1")
Copy link

Copilot AI Jun 17, 2025

Choose a reason for hiding this comment

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

Including the same router inside each trigger registration can lead to duplicate routes; move include_router calls out of the loop to a single centralized inclusion.

Suggested change
self.app.include_router(self.workflow_router, prefix="/workflows/v1")

Copilot uses AI. Check for mistakes.
cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Attribute Mapping Fails, Data Duplicates

The Query.get_attributes method duplicates data in custom_attributes. The loop intended for unmapped fields incorrectly adds fields already mapped to attributes (e.g., "querytxt", "dbname", "schemaname"). This occurs because the check k not in attributes fails: input keys are mapped to different attribute names (e.g., "longRawQuery", "defaultDatabaseQualifiedName"), so the original input keys are not found in the attributes dictionary, leading to their re-addition to custom_attributes.

application_sdk/transformers/atlas/sql.py#L1274-L1278

# Add any other fields not mapped above to custom_attributes
for k, v in obj.items():
if k not in attributes and k not in custom_attributes:
custom_attributes[k] = v

Fix in Cursor


Bug: Missing Fundamental Attributes in Query Entity

The Query.get_attributes method is missing the required Atlas entity attributes 'name' and 'qualified_name'. These are fundamental attributes consistently set by all other entity transformers (Database, Schema, Table, Column, Function, Procedure, TagAttachment), and their omission will likely cause issues when creating Atlas Query entities.

application_sdk/transformers/atlas/sql.py#L1239-L1284

attributes = {}
custom_attributes = {}
# Map fields from input to Query entity attributes
attributes["longRawQuery"] = obj.get("querytxt")
attributes["rawQueryText"] = obj.get("querytxt")
attributes["defaultDatabaseQualifiedName"] = obj.get("dbname")
attributes["defaultSchemaQualifiedName"] = obj.get("schemaname")
attributes["parentQualifiedName"] = obj["parentQualifiedName"]
attributes["collectionQualifiedName"] = obj["collectionQualifiedName"]
attributes["isPrivate"] = obj.get("isPrivate")
attributes["isSqlSnippet"] = obj.get("isSqlSnippet")
attributes["isVisualQuery"] = obj.get("isVisualQuery")
attributes["visualBuilderSchemaBase64"] = obj.get(
"visualBuilderSchemaBase64"
)
attributes["variablesSchemaBase64"] = obj.get("variablesSchemaBase64")
# Deprecated field for backward compatibility
attributes["rawQuery"] = obj.get("rawQuery")
# Place username and sessionid in custom_attributes
if obj.get("username"):
custom_attributes["username"] = obj["username"]
if obj.get("sessionid"):
custom_attributes["sessionid"] = obj["sessionid"]
if obj.get("starttime"):
custom_attributes["starttime"] = obj["starttime"]
if obj.get("endtime"):
custom_attributes["endtime"] = obj["endtime"]
if obj.get("session_starttime"):
custom_attributes["session_starttime"] = obj["session_starttime"]
if obj.get("session_endtime"):
custom_attributes["session_endtime"] = obj["session_endtime"]
# Add any other fields not mapped above to custom_attributes
for k, v in obj.items():
if k not in attributes and k not in custom_attributes:
custom_attributes[k] = v
return {
"attributes": attributes,
"custom_attributes": custom_attributes,
"entity_class": Query,
}

Fix in Cursor


Was this report helpful? Give feedback by reacting with 👍 or 👎

@inishchith inishchith marked this pull request as draft June 17, 2025 06:17
@AtMrun AtMrun closed this Jun 24, 2025
@AtMrun AtMrun deleted the add_query_transformer branch June 24, 2025 05:26
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