Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit e55a9b3

Browse files
authored
Fix downgrading to previous version of Synapse (#15907)
We do this by marking the constraint as deferrable.
1 parent 6774f26 commit e55a9b3

File tree

5 files changed

+24
-6
lines changed

5 files changed

+24
-6
lines changed

changelog.d/15907.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add foreign key constraint to `event_forward_extremities`.

synapse/storage/background_updates.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,14 @@ class ForeignKeyConstraint(Constraint):
8080
Attributes:
8181
referenced_table: The "parent" table name.
8282
columns: The list of mappings of columns from table to referenced table
83+
deferred: Whether to defer checking of the constraint to the end of the
84+
transaction. This is useful for e.g. backwards compatibility where
85+
an older version inserted data in the wrong order.
8386
"""
8487

8588
referenced_table: str
8689
columns: Sequence[Tuple[str, str]]
90+
deferred: bool
8791

8892
def make_check_clause(self, table: str) -> str:
8993
join_clause = " AND ".join(
@@ -94,7 +98,8 @@ def make_check_clause(self, table: str) -> str:
9498
def make_constraint_clause_postgres(self) -> str:
9599
column1_list = ", ".join(col1 for col1, col2 in self.columns)
96100
column2_list = ", ".join(col2 for col1, col2 in self.columns)
97-
return f"FOREIGN KEY ({column1_list}) REFERENCES {self.referenced_table} ({column2_list})"
101+
defer_clause = " DEFERRABLE INITIALLY DEFERRED" if self.deferred else ""
102+
return f"FOREIGN KEY ({column1_list}) REFERENCES {self.referenced_table} ({column2_list}) {defer_clause}"
98103

99104

100105
@attr.s(auto_attribs=True)

synapse/storage/databases/main/event_federation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ def __init__(
146146
update_name="event_forward_extremities_event_id_foreign_key_constraint_update",
147147
table="event_forward_extremities",
148148
constraint_name="event_forward_extremities_event_id",
149-
constraint=ForeignKeyConstraint("events", [("event_id", "event_id")]),
149+
constraint=ForeignKeyConstraint(
150+
"events", [("event_id", "event_id")], deferred=True
151+
),
150152
unique_columns=("event_id", "room_id"),
151153
)
152154

synapse/storage/schema/main/delta/78/03event_extremities_constraints.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,25 @@
2828
event_id TEXT NOT NULL,
2929
room_id TEXT NOT NULL,
3030
UNIQUE (event_id, room_id),
31-
CONSTRAINT event_forward_extremities_event_id FOREIGN KEY (event_id) REFERENCES events (event_id)
31+
CONSTRAINT event_forward_extremities_event_id FOREIGN KEY (event_id) REFERENCES events (event_id) DEFERRABLE INITIALLY DEFERRED
3232
)
3333
"""
3434

3535

3636
def run_create(cur: LoggingTransaction, database_engine: BaseDatabaseEngine) -> None:
37+
# We mark this as a deferred constraint, as the previous version of Synapse
38+
# inserted the event into the forward extremities *before* the events table.
39+
# By marking as deferred we ensure that downgrading to the previous version
40+
# will continue to work.
3741
run_validate_constraint_and_delete_rows_schema_delta(
3842
cur,
3943
ordering=7803,
4044
update_name="event_forward_extremities_event_id_foreign_key_constraint_update",
4145
table="event_forward_extremities",
4246
constraint_name="event_forward_extremities_event_id",
43-
constraint=ForeignKeyConstraint("events", [("event_id", "event_id")]),
47+
constraint=ForeignKeyConstraint(
48+
"events", [("event_id", "event_id")], deferred=True
49+
),
4450
sqlite_table_name="event_forward_extremities2",
4551
sqlite_table_schema=FORWARD_EXTREMITIES_TABLE_SCHEMA,
4652
)

tests/storage/test_background_update.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ def delta(txn: LoggingTransaction) -> None:
586586
update_name="test_bg_update",
587587
table="test_constraint",
588588
constraint_name="test_constraint_name",
589-
constraint=ForeignKeyConstraint("base_table", [("b", "b")]),
589+
constraint=ForeignKeyConstraint(
590+
"base_table", [("b", "b")], deferred=False
591+
),
590592
sqlite_table_name="test_constraint2",
591593
sqlite_table_schema=table2_sqlite,
592594
)
@@ -604,7 +606,9 @@ def delta(txn: LoggingTransaction) -> None:
604606
"test_bg_update",
605607
table="test_constraint",
606608
constraint_name="test_constraint_name",
607-
constraint=ForeignKeyConstraint("base_table", [("b", "b")]),
609+
constraint=ForeignKeyConstraint(
610+
"base_table", [("b", "b")], deferred=False
611+
),
608612
unique_columns=["a"],
609613
)
610614

0 commit comments

Comments
 (0)