|
|
@@ -449,26 +449,28 @@ class PushRuleStore(PushRulesWorkerStore): |
|
|
|
before: str, |
|
|
|
after: str, |
|
|
|
) -> None: |
|
|
|
# Lock the table since otherwise we'll have annoying races between the |
|
|
|
# SELECT here and the UPSERT below. |
|
|
|
self.database_engine.lock_table(txn, "push_rules") |
|
|
|
|
|
|
|
relative_to_rule = before or after |
|
|
|
|
|
|
|
res = self.db_pool.simple_select_one_txn( |
|
|
|
txn, |
|
|
|
table="push_rules", |
|
|
|
keyvalues={"user_name": user_id, "rule_id": relative_to_rule}, |
|
|
|
retcols=["priority_class", "priority"], |
|
|
|
allow_none=True, |
|
|
|
) |
|
|
|
sql = """ |
|
|
|
SELECT priority, priority_class FROM push_rules |
|
|
|
WHERE user_name = ? AND rule_id = ? |
|
|
|
""" |
|
|
|
|
|
|
|
if isinstance(self.database_engine, PostgresEngine): |
|
|
|
sql += " FOR UPDATE" |
|
|
|
else: |
|
|
|
# Annoyingly SQLite doesn't support row level locking, so lock the whole table |
|
|
|
self.database_engine.lock_table(txn, "push_rules") |
|
|
|
|
|
|
|
txn.execute(sql, (user_id, relative_to_rule)) |
|
|
|
row = txn.fetchone() |
|
|
|
|
|
|
|
if not res: |
|
|
|
if row is None: |
|
|
|
raise RuleNotFoundException( |
|
|
|
"before/after rule not found: %s" % (relative_to_rule,) |
|
|
|
) |
|
|
|
|
|
|
|
base_priority_class, base_rule_priority = res |
|
|
|
base_rule_priority, base_priority_class = row |
|
|
|
|
|
|
|
if base_priority_class != priority_class: |
|
|
|
raise InconsistentRuleException( |
|
|
@@ -516,9 +518,18 @@ class PushRuleStore(PushRulesWorkerStore): |
|
|
|
conditions_json: str, |
|
|
|
actions_json: str, |
|
|
|
) -> None: |
|
|
|
# Lock the table since otherwise we'll have annoying races between the |
|
|
|
# SELECT here and the UPSERT below. |
|
|
|
self.database_engine.lock_table(txn, "push_rules") |
|
|
|
if isinstance(self.database_engine, PostgresEngine): |
|
|
|
# Postgres doesn't do FOR UPDATE on aggregate functions, so select the rows first |
|
|
|
# then re-select the count/max below. |
|
|
|
sql = """ |
|
|
|
SELECT * FROM push_rules |
|
|
|
WHERE user_name = ? and priority_class = ? |
|
|
|
FOR UPDATE |
|
|
|
""" |
|
|
|
txn.execute(sql, (user_id, priority_class)) |
|
|
|
else: |
|
|
|
# Annoyingly SQLite doesn't support row level locking, so lock the whole table |
|
|
|
self.database_engine.lock_table(txn, "push_rules") |
|
|
|
|
|
|
|
# find the highest priority rule in that class |
|
|
|
sql = ( |
|
|
|