mirror of
https://github.com/discourse/discourse.git
synced 2026-08-09 21:45:25 +08:00
The sharded write path (#41262) merges every shard table with `INSERT OR IGNORE`. That's right for `uploads`, but for every other table it silently swallows a genuine cross-step/cross-shard duplicate row that the single-writer path would have raised on — so a concurrency bug that doubles a key becomes silent data loss with no error and no baseline to diff against. This scopes the `OR IGNORE` back to just the tables that actually want it, derived from the models rather than a hardcoded table name: - `IntermediateDB.conflict_strategy_for(table)` resolves a table's model and reads its declared `conflict_strategy`, defaulting to `:raise`. - Only `upload` declares `:ignore` (its rows are content-identical for a given id-hash, so first-writer-wins is intended). A future `OR IGNORE` model flips its own merge clause with no change to the merge code. - `Connection#merge_database` takes `dedupe_tables:` and picks the clause per table; a plain-table conflict raises, wrapped with the table name, and the error surfaces through `Consolidator#drain` as a run failure. This restores the earlier behaviour where a genuine duplicate on a plain table is an error, not a dropped row. |
||
|---|---|---|
| .. | ||
| intermediate_db | ||
| connection_spec.rb | ||
| intermediate_db_spec.rb | ||
| migrator_spec.rb | ||
| prepared_statement_cache_spec.rb | ||