From ba8ea12922bc21541bfe7888084705c997c86dab Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Mon, 8 Jun 2026 17:24:48 -0700 Subject: [PATCH] refactor(pagination): hoist cursor codec to utils/ for cross-domain reuse The keyset cursor codec was asset-namespaced (app/assets/services/cursor.py) but the wire format and encode/decode logic are domain-agnostic. Move it to utils/cursor.py so the jobs endpoint can share one codec instead of importing across domains or duplicating it. --- app/assets/api/routes.py | 2 +- app/assets/services/asset_management.py | 2 +- tests-unit/assets_test/services/test_cursor.py | 4 ++-- {app/assets/services => utils}/cursor.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename {app/assets/services => utils}/cursor.py (99%) diff --git a/app/assets/api/routes.py b/app/assets/api/routes.py index 544a614f2..389ca1462 100644 --- a/app/assets/api/routes.py +++ b/app/assets/api/routes.py @@ -39,7 +39,7 @@ from app.assets.services import ( update_asset_metadata, upload_from_temp_path, ) -from app.assets.services.cursor import InvalidCursorError +from utils.cursor import InvalidCursorError from app.assets.services.tagging import list_tag_histogram ROUTES = web.RouteTableDef() diff --git a/app/assets/services/asset_management.py b/app/assets/services/asset_management.py index 1072c95fa..5df630156 100644 --- a/app/assets/services/asset_management.py +++ b/app/assets/services/asset_management.py @@ -4,7 +4,7 @@ import os from datetime import timezone from typing import Sequence -from app.assets.services.cursor import ( +from utils.cursor import ( CursorPayload, InvalidCursorError, decode_cursor, diff --git a/tests-unit/assets_test/services/test_cursor.py b/tests-unit/assets_test/services/test_cursor.py index 47970e168..18863cd22 100644 --- a/tests-unit/assets_test/services/test_cursor.py +++ b/tests-unit/assets_test/services/test_cursor.py @@ -1,4 +1,4 @@ -"""Tests for app.assets.services.cursor. +"""Tests for utils.cursor. Cursors are opaque tokens internal to this server — these tests cover round-tripping, validation, and length caps, not any particular wire @@ -11,7 +11,7 @@ from datetime import datetime, timedelta, timezone import pytest -from app.assets.services.cursor import ( +from utils.cursor import ( MAX_CURSOR_ID_LENGTH, MAX_CURSOR_VALUE_LENGTH, MAX_ENCODED_CURSOR_LENGTH, diff --git a/app/assets/services/cursor.py b/utils/cursor.py similarity index 99% rename from app/assets/services/cursor.py rename to utils/cursor.py index 6c7791528..d140f8fef 100644 --- a/app/assets/services/cursor.py +++ b/utils/cursor.py @@ -1,4 +1,4 @@ -"""Opaque keyset-pagination cursor for /api/assets. +"""Opaque keyset-pagination cursor shared by /api/assets and /api/jobs. Payload JSON uses short keys to keep the encoded length small: