?
TRCKR-219
bug sync
Created: 2025-12-09 Updated: 2025-12-16
Relationships Loading...
Attachments
Loading...
Comments (2)
qa-agent · 2025-12-16
## QA PASSED See QA report document: 45f5ce4c-feac-485a-bcf3-83c53b16aa77 **All hypotheses tested, no issues found:** - identifier_exists() correctly detects soft-deleted issues - Sync collision detection triggers and assigns new identifiers - E2E tests validate the exact reproduction scenario - No regressions in sync test suite (53 tests pass) Fix verified working.
agent · 2025-12-09
## Fix Implemented ### Problem Found The root cause was in `server/routes/sync.py:390` where `store.get_issue_by_identifier(identifier)` only checks for active issues (`deleted_at IS NULL`). This allowed the check to pass even when a soft-deleted issue with the same identifier existed, leading to a UNIQUE constraint violation when trying to INSERT. ### Changes Made **1. Added `identifier_exists()` method to LocalStore** - File: `client/store.py:434-456` - Checks for identifier existence including soft-deleted issues - Parameters: `identifier` (string), `include_deleted` (bool, default True) - Returns: `True` if identifier exists (in any state), `False` otherwise **2. Updated server sync collision detection** - File: `server/routes/sync.py:388-401` - Changed from `get_issue_by_identifier()` to `identifier_exists(include_deleted=True)` - Now properly detects collisions with soft-deleted issues - Logs collision detection with INFO level for debugging - Assigns next available identifier using `_next_issue_identifier()` **3. Added comprehensive E2E tests** - File: `tests/test_sync_e2e.py:750-915` - `test_identifier_collision_with_soft_deleted_server_entity`: Tests the exact scenario from the issue - `test_two_clients_create_same_identifier_simultaneously`: Tests race condition between clients - Both tests verify proper identifier reassignment and successful sync ### Test Results ``` tests/test_sync_e2e.py::TestIdentifierCollisionE2E::test_identifier_collision_with_soft_deleted_server_entity PASSED tests/test_sync_e2e.py::TestIdentifierCollisionE2E::test_two_clients_create_same_identifier_simultaneously PASSED tests/test_counter_sync.py - All PASSED (no regression) ``` ### How It Works 1. Client creates issue with identifier `TRCKR-157` 2. Server checks `identifier_exists("TRCKR-157", include_deleted=True)` 3. Finds soft-deleted issue with that identifier 4. Logs: "Identifier collision detected: TRCKR-157 exists (possibly soft-deleted). Assigning new identifier." 5. Calls `_next_issue_identifier()` which finds the lowest available number (TRCKR-158+) 6. Creates issue with new identifier 7. Returns `canonical_identifier` in sync response 8. Client updates local identifier to match canonical ### Edge Cases Handled - Multiple soft-deleted issues with same prefix - Client counter reset scenarios - Two clients creating same identifier simultaneously - Project-specific identifiers (PROJECT-N) vs global (TRCKR-N)