Fix concurrent activity summary insert conflicts #26
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: McPringle/fitpub#26
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-race-condition"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
When multiple activities were processed in quick succession, asynchronous updates of
ActivitySummaryentries could run into a race condition.The sequence was:
ActivitySummaryrow.user_idperiod_typeperiod_startThis resulted in errors such as:
duplicate key value violates unique constraint "activity_summaries_user_id_period_type_period_start_key"DataIntegrityViolationExceptioninupdateSummariesForActivity(...)Root cause
The summary update logic was not robust against concurrent inserts for the same period summary.
The code followed a pattern like:
findByUserIdAndPeriodTypeAndPeriodStart(...)ActivitySummarysave(...)This "check then insert" flow is not atomic under parallel execution.
Impact
Solution
The update flow now handles concurrent insert conflicts explicitly.
When saving a newly created summary fails with a
DataIntegrityViolationException, the service assumes that another concurrent task has already created the row. It then reloads the existingActivitySummary, recalculates the summary values for the same period, and saves the entity again as a normal update.This keeps the asynchronous workflow intact while making summary updates resilient to concurrent activity processing.
Expected behavior
If another concurrent task creates the same summary row first, the second task should not fail with an uncaught exception. It should reload the existing summary and continue with a normal update.
please wait with a merge of this PR - last night I got an idea of a possibly way easier solution.
The current implementation is unnecessarily complicated. I'm withdrawing my PR and would rather work on a simpler solution. See Issue #30.
Pull request closed