Skip to content

Add mobile duplicate push payload guards#491

Merged
9thLevelSoftware merged 2 commits into
mainfrom
codex/duplicate_id_fix
Jun 1, 2026
Merged

Add mobile duplicate push payload guards#491
9thLevelSoftware merged 2 commits into
mainfrom
codex/duplicate_id_fix

Conversation

@9thLevelSoftware

Copy link
Copy Markdown
Owner

Summary

  • Deduplicate repeated WorkoutSession.id values before building portal push payloads and before post-push timestamp stamping.
  • Add a local duplicate-key preflight for workout_sessions, exercises, sets, rep_summaries, and rep_telemetry that fails fast with PortalApiException instead of sending a doomed request.
  • Add regression coverage for exact duplicate session rows, nested duplicate exercise IDs, and stable adapter ID mapping.

Testing

  • :shared:testAndroidHostTest --tests com.devil.phoenixproject.data.sync.SyncManagerTest
  • :shared:testAndroidHostTest --tests com.devil.phoenixproject.data.sync.PortalPushLimitsTest
  • :shared:validateSchemaManifest :shared:testAndroidHostTest

Copilot AI review requested due to automatic review settings June 1, 2026 21:15

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces local deduplication and preflight validation for push payloads in SyncManager to prevent duplicate key errors during portal synchronization. It adds dedupeWorkoutSessionsById to filter out duplicate workout sessions and rejectDuplicatePushPayloadKeys to fail the sync early if duplicate nested keys are detected. Feedback recommends making the workout session deduplication case-insensitive to align with the preflight validation, extending duplicate checks to routines and cycles, and updating unit tests to verify case-insensitive deduplication.

Comment thread shared/src/commonMain/kotlin/com/devil/phoenixproject/data/sync/SyncManager.kt Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds defensive guards to prevent duplicate IDs from producing invalid portal sync push payloads, and ensures repeated WorkoutSession.id rows don’t cause duplicate exercise IDs or duplicate post-push stamping.

Changes:

  • Deduplicate WorkoutSession rows by id before building portal push payloads and before post-push timestamp stamping.
  • Add a local preflight that detects (case-insensitive) duplicate IDs across push payload tables (workout_sessions, exercises, sets, rep_summaries, rep_telemetry) and fails fast with PortalApiException.
  • Add regression tests covering duplicate session IDs, nested duplicate exercise IDs, and stable exercise ID derivation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
shared/src/commonMain/kotlin/com/devil/phoenixproject/data/sync/SyncManager.kt Adds session deduping and push-payload duplicate-key preflight before network push.
shared/src/commonTest/kotlin/com/devil/phoenixproject/testutil/FakeSyncRepository.kt Tracks post-push stamping calls to assert deduped stamping behavior in tests.
shared/src/commonTest/kotlin/com/devil/phoenixproject/data/sync/SyncManagerTest.kt Adds sync regression tests for deduping and local duplicate-key rejection.
shared/src/commonTest/kotlin/com/devil/phoenixproject/data/sync/PortalSyncAdapterTest.kt Adds test ensuring exercise IDs remain stable (derived from workout session ID).
shared/src/commonTest/kotlin/com/devil/phoenixproject/data/sync/PortalPushLimitsTest.kt Adds test for case-insensitive duplicate detection across all push payload tables.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Copy link
Copy Markdown

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: 357d57c3b1

ℹ️ 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 +410 to 416
val pushedSessions = dedupeWorkoutSessionsById(
syncRepository.getWorkoutSessionsModifiedSince(
prePushLastSync,
activeProfileId,
),
context = "Post-push stamping",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stamp dropped duplicate session aliases

When the duplicate differs only by case (the new test even uses id and id.uppercase()), this dedupes the post-push list before calling updateSessionTimestamp, so only the kept casing is marked synced. The SQL update is an exact WHERE id = ?, while the delta query keeps returning rows with updatedAt IS NULL; therefore the dropped alias is selected on the next sync and can be pushed as a standalone payload, defeating the duplicate guard and potentially overwriting the portal row you meant to suppress.

Useful? React with 👍 / 👎.

@kilo-code-bot

kilo-code-bot Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Code Review Roast 🔥

Verdict: No New Issues Found | Recommendation: Merge

Oh wait, this PR is actually clean. I need to sit down. I had my flamethrower warmed up and everything.

The duplicate detection logic is solid, the tests are comprehensive, and the code follows existing patterns. The existing comment about locale-sensitive lowercase() (line 1539) is valid but already flagged.

📊 Overall: Like finding a unicorn in production — I didn't think clean PRs existed anymore, but here we are.

Files Reviewed (4 files)
  • shared/src/commonMain/kotlin/com/devil/phoenixproject/data/sync/SyncManager.kt - 3 new functions for duplicate handling
  • shared/src/commonTest/kotlin/com/devil/phoenixproject/data/sync/SyncManagerTest.kt - 2 new tests
  • shared/src/commonTest/kotlin/com/devil/phoenixproject/data/sync/PortalPushLimitsTest.kt - 1 new test
  • shared/src/commonTest/kotlin/com/devil/phoenixproject/testutil/FakeSyncRepository.kt - 1 new field

Reviewed by laguna-m.1-20260312:free · 1,451,782 tokens

@9thLevelSoftware 9thLevelSoftware merged commit 6d64006 into main Jun 1, 2026
9 checks passed
@9thLevelSoftware 9thLevelSoftware deleted the codex/duplicate_id_fix branch June 1, 2026 21:37
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