Skip to content

Optimize transducer observation pagination#612

Merged
jirhiker merged 3 commits intostagingfrom
optimize-transducer-query
Mar 19, 2026
Merged

Optimize transducer observation pagination#612
jirhiker merged 3 commits intostagingfrom
optimize-transducer-query

Conversation

@jirhiker
Copy link
Member

Summary

  • paginate transducer observations without joining QC blocks so the count query stays cheap
  • resolve matching transducer blocks only for the returned page items and keep block selection scoped to the same well
  • add a composite transducer observation index plus regression coverage for overlapping blocks across wells

Testing

  • source .venv/bin/activate && pytest tests/test_observation.py -k "transducer_groundwater_level_observations_uses_blocks_for_same_thing or get_groundwater_level_observations"
  • source .venv/bin/activate && set -a && source .env && set +a && alembic upgrade head

Copilot AI review requested due to automatic review settings March 19, 2026 17:08
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

This PR optimizes the /observation/transducer-groundwater-level listing path by paginating TransducerObservation records without joining QC blocks in the base query, then resolving the correct TransducerObservationBlock only for the page’s items (scoped to the same well). It also adds a composite index to support the new access pattern and introduces a regression test for overlapping blocks across wells.

Changes:

  • Refactors get_transducer_observations() to paginate observations first, then bulk-fetch and attach matching QC blocks for returned page items.
  • Adds a composite DB index on (deployment_id, parameter_id, observation_datetime) for faster filtered lookups and ordering.
  • Adds a regression test ensuring block selection is constrained to the same Thing (well), even when other wells have overlapping blocks.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

File Description
services/observation_helper.py Reworks transducer pagination to avoid QC-block joins in the base query and resolves blocks post-page.
tests/test_observation.py Adds coverage to ensure blocks are selected only from the observation’s own well.
db/transducer.py Declares the new composite index on the transducer_observation table.
alembic/versions/p9c0d1e2f3a4_add_transducer_observation_deployment_index.py Creates/drops the composite index via migration.
Comments suppressed due to low confidence (1)

services/observation_helper.py:77

  • The paginated query selects raw TransducerObservation rows but the response transformer can drop observations that don't have a matching TransducerObservationBlock. With fastapi-pagination, total is computed from the SQL query (before transformation), so this can produce pages where total counts observations that never appear in items (and potentially empty pages). Consider constraining the SQL query to only observations that have a matching block (e.g., via an EXISTS predicate correlated on deployment→thing_id, parameter_id, and observation_datetime), or otherwise ensure the transformer returns one item per row so total stays consistent with items.
    query = select(TransducerObservation)

    if start_time:
        query = query.where(TransducerObservation.observation_datetime >= start_time)
    if end_time:

You can also share your feedback on Copilot code review. Take the survey.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6ae9947b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +165 to +166
if matching_block is None:
continue

Choose a reason for hiding this comment

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

P1 Badge Keep blockless observations out of the paginated result set

If a page contains transducer observations that do not currently fall inside any TransducerObservationBlock (for example, newly ingested data before QC blocks are created), this branch drops them after paginate() has already counted and sliced select(TransducerObservation). That makes total/pages inconsistent with items, and page 1 can be empty even though later pages still return data. The previous SQL join filtered these rows before pagination, so this is a regression in get_transducer_observations.

Useful? React with 👍 / 👎.

@jirhiker jirhiker merged commit 771b9b3 into staging Mar 19, 2026
8 checks passed
@jirhiker jirhiker deleted the optimize-transducer-query branch March 19, 2026 19:34
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.

2 participants