Skip to content

feat: add atomic, revisioned tile-order API with set-based updates - #994

Open
devin-ai-integration[bot] wants to merge 16 commits into
mainfrom
devin/1785262304-tile-order
Open

feat: add atomic, revisioned tile-order API with set-based updates#994
devin-ai-integration[bot] wants to merge 16 commits into
mainfrom
devin/1785262304-tile-order

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Closes #978 (epic #975). Adds one atomic, revisioned ordering contract per root/category scope so a reorder can never partially persist and stale writers get an explicit 409.

  • New table tile_order_revisions (migration 0018_tile_order_revisions): scope_key (parent category ID, 0 = root) → revision (CAS counter, lazily created at 1).
  • New endpoints (instructor/admin), backend/app/routers/tile_order.py:
    • GET /api/tile-order?parent_category_id= → authoritative order + current revision.
    • PUT /api/tile-order — in ONE transaction:
      lock_scope_revision      # INSERT..ON CONFLICT DO NOTHING + SELECT..FOR UPDATE
      load_scope_members       # two set-based SELECTs
      validate_submitted_items # duplicates / foreign / missing IDs → 400 (must equal scope set)
      expected_revision != current → 409 {message, current: {revision, items}}
      apply_positions          # one UPDATE..FROM (VALUES..) per entity type — statement count constant
      bump_scope_revision      # revision += 1, RETURNING
      commit                   # failure path rolls back both entity types
      
  • Canonical deterministic tie-breaker shared by reads/writes/normalization (app/tile_order.py): (sort_order, item_type_priority(category=0,image=1), item_id) — never labels/names.
  • Administrative normalization CLI python -m app.tile_order: walks every scope, rewrites contiguous positions, initializes revision rows.
  • Reorder telemetry contract extended with entity="tile" (tile.reorder span, reorder.persisted log, hriv_reorder_* metrics); body operation_id supersedes the header for this endpoint.
  • Reordering never rewrites membership (parent_id/category_id); legacy PUT /categories/reorder + PUT /images/reorder kept for the staged frontend migration (Implement a navigation-safe frontend reorder coordinator and save-state UX #979Migrate Manage Categories to the shared ordering workflow and complete end-to-end verification #982), documented as deprecated in docs/tile-ordering.md.

Stacking

Stacked on PR #993 (#977 telemetry) which is stacked on PR #992 (#976 fixture); this diff includes their commits until they merge. Tile-order-only changes are in commit 4ea973c.

Testing

  • backend/tests/test_tile_order.py: unit tests (canonical rule, validation, mocked endpoint 400/409/success) + PostgreSQL integration tests against the Establish a production-scale reorder fixture and deterministic failure reproduction #976 fixture: atomic mixed commit, rollback of both entity types on failure, duplicate/missing/foreign rejection, CAS exclusivity (second writer with same revision → 409), membership preservation, bounded statement count (600+ image gallery vs small scope), deterministic normalization.
  • Full backend suite locally with fixture DB: 980 passed, 2 xfailed, coverage 86.5%.
  • Fresh-DB Alembic bootstrap verified against a throwaway PostgreSQL database (migration 0018, revision id 25 chars).

Needs human verification

  • Deploy-and-observe: tile.reorder spans / entity="tile" metrics visible in Grafana/Tempo/Loki after deployment.

Link to Devin session: https://app.devin.ai/sessions/414754bd88374dc693f47100ac269e78

…reproduction

Establishes the epic #975 fixture: 80 sibling categories, 600 sibling
images, mixed root and nested scopes, duplicate sort_order values, with
idempotent CLI seeding, backend integration tests against real PostgreSQL,
and frontend latency-injected regression tests reproducing the silent-drop,
stale-refresh-overwrite, and partial-persistence failures.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…arent

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…etry

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ned semantics

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ecording

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…y doc

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot requested a review from kphunter as a code owner July 28, 2026 20:36
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

github-code-quality[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

…uous positions

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…nt scopes

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
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.

Implement an atomic, revisioned tile-order API with set-based updates

0 participants