Skip to content

Commit 173fbef

Browse files
committed
[IMP] util/pg: retry queries failed due to SerializationFailure
Extend the mechanism used for `DeadlockDetected` to `SerializationFailure` closes #49 Signed-off-by: Christophe Simonis (chs) <[email protected]>
1 parent 20c3b5b commit 173fbef

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/base/tests/test_util.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,50 @@ def test_parallel_rowcount_threaded(self):
525525
self.test_parallel_rowcount()
526526
threading.current_thread().testing = True
527527

528+
def test_parallel_execute_retry_on_serialization_failure(self):
529+
TEST_TABLE_NAME = "_upgrade_serialization_failure_test_table"
530+
N_ROWS = 10
531+
532+
cr = self.env.cr
533+
534+
cr.execute(
535+
util.format_query(
536+
cr,
537+
"""
538+
DROP TABLE IF EXISTS {table};
539+
540+
CREATE TABLE {table} (
541+
id SERIAL PRIMARY KEY,
542+
other_id INTEGER,
543+
FOREIGN KEY (other_id) REFERENCES {table} ON DELETE CASCADE
544+
);
545+
546+
INSERT INTO {table} SELECT GENERATE_SERIES(1, %s);
547+
548+
-- map odd numbers `n` to `n + 1` and viceversa (`n + 1` to `n`)
549+
UPDATE {table} SET other_id = id + (MOD(id, 2) - 0.5)*2;
550+
"""
551+
% N_ROWS,
552+
table=TEST_TABLE_NAME,
553+
)
554+
)
555+
556+
threading.current_thread().testing = False
557+
# exploded queries will generate a SerializationFailed error, causing some of the queries to be retried
558+
util.explode_execute(
559+
cr, util.format_query(cr, "DELETE FROM {}", TEST_TABLE_NAME), TEST_TABLE_NAME, bucket_size=1
560+
)
561+
threading.current_thread().testing = True
562+
563+
if hasattr(self, "_savepoint_id"):
564+
# `explode_execute` causes the cursor to be committed, losing the automatic checkpoint
565+
# Force a new one to avoid issues when cleaning up
566+
self.addCleanup(cr.execute, f"SAVEPOINT test_{self._savepoint_id}")
567+
self.addCleanup(cr.execute, util.format_query(cr, "DROP TABLE IF EXISTS {}", TEST_TABLE_NAME))
568+
569+
cr.execute(util.format_query(cr, "SELECT 1 FROM {}", TEST_TABLE_NAME))
570+
self.assertFalse(cr.rowcount)
571+
528572
def test_create_column_with_fk(self):
529573
cr = self.env.cr
530574
self.assertFalse(util.column_exists(cr, "res_partner", "_test_lang_id"))

src/util/pg.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ def execute(query):
104104

105105
cr.commit()
106106

107-
CONCURRENCY_ERRORCODES = {errorcodes.DEADLOCK_DETECTED}
107+
CONCURRENCY_ERRORCODES = {
108+
errorcodes.DEADLOCK_DETECTED,
109+
errorcodes.SERIALIZATION_FAILURE,
110+
}
108111
failed_queries = []
109112
tot_cnt = 0
110113
with ThreadPoolExecutor(max_workers=max_workers) as executor:

0 commit comments

Comments
 (0)