gongxun0928 opened a new pull request, #1876:
URL: https://github.com/apache/cloudberry/pull/1876

   <!-- Thank you for your contribution to Apache Cloudberry (Incubating)! -->
   
   ### What does this PR do?
   
   Fixes an intermittent `tuple concurrently updated` error in the `task` 
regression test (`ic-orca-parallel` CI job).
   
   **CI failure:**
   ```
   diff -U3 .../expected/task.out .../results/task.out
   @@ -111,6 +111,7 @@
    drop user task_cron;
    drop task vacuum_db;
    drop task valid_task_1;
   +ERROR:  tuple concurrently updated (heapam.c:3112)
    drop task valid_task_2;
   ```
   
   ### Type of Change
   - [x] Bug fix (non-breaking change)
   
   ### Root Cause
   
   `DROP TASK` performs two deletions:
   
   ```
   DropTask()
   ├── UnscheduleCronJob()           → DELETE FROM pg_task
   └── RemoveTaskRunHistoryByJobId() → DELETE FROM pg_task_run_history  ← race 
here
   ```
   
   `RemoveTaskRunHistoryByJobId` used `CatalogTupleDelete` (wrapping 
`simple_heap_delete`) to bulk-delete `pg_task_run_history` rows. When 
`heap_delete` encounters a tuple concurrently updated by a committed 
transaction, it returns `TM_Updated` and `simple_heap_delete` raises `ERROR: 
tuple concurrently updated`.
   
   The concurrent updater is the **pg_cron launcher daemon**, which records 
task execution results by INSERTing and UPDATEing `pg_task_run_history` rows 
for the same jobid. This race is CloudberryDB-specific: the original pg_cron 
extension does not delete run history during `unschedule`.
   
   ### Race Timeline
   
   ```
   Timeline              DROP TASK (session A)          cron daemon (session B)
   ─────────────────────────────────────────────────────────────────────────────
   T1   UnscheduleCronJob → DELETE pg_task row ✓
        SIGHUP sent to daemon (not yet processed)
   
   T2                                                      daemon fires task 
(job list not reloaded yet)
                                                           TaskRunHistoryCreate 
→ INSERT run_history row
                                                           Execute task SQL
                                                           UpdateJobRunDetail → 
UPDATE run_history row
                                                           COMMIT
   
   T3   RemoveTaskRunHistoryByJobId:
        scan finds run_history row (old tuple version)
        ↓ daemon already UPDATEd this row at T2 (committed)
        heap_delete(old t_self) → TM_Updated
        ERROR: tuple concurrently updated
   ```
   
   Even after `UnscheduleCronJob` deletes the `pg_task` row and sends SIGHUP, 
the daemon may fire one more execution before reloading its job list. During 
this window, the daemon UPDATE races with `RemoveTaskRunHistoryByJobId` DELETE.
   
   The 1-second schedule (`valid_task_1`) maximizes collision probability.
   
   ### Fix
   
   Replace `CatalogTupleDelete` with direct `heap_delete` calls and handle 
`TM_Updated`/`TM_Deleted` gracefully:
   
   - Switch from single-pass while-loop to restart-scan `for(;;)` pattern: 
after each delete, restart scan to see the latest committed tuple version.
   - `TM_Updated`/`TM_Deleted` → retry (re-scan picks up updated tuple)
   - `TM_Ok` → success
   - `TM_SelfModified` / unexpected → ERROR
   
   Safe because `UnscheduleCronJob` already deleted the `pg_task` entry — 
run-history rows are orphan data cleaned up best-effort.
   
   ### Breaking Changes
   
   None.
   
   ### Test Plan
   - [x] Passed `make installcheck` for task regression test locally (15 
consecutive runs, 0 failures)
   - [ ] Passed `make -C src/test installcheck-cbdb-parallel`
   
   ### Impact
   
   **Performance:** Minimal — restart-scan loop is O(n²) but n (run-history 
rows per job) is typically small.
   
   **User-facing changes:** None — DROP TASK behavior unchanged, only more 
reliable.
   
   **Dependencies:** None.
   
   ### Checklist
   - [x] Followed [contribution 
guide](https://cloudberry.apache.org/contribute/code)
   - [x] Reviewed code for security implications
   - [ ] This PR contains AI-assisted code generation


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to