Skip to content

Commit a60fdc9

Browse files
committed
graph: Check for update attempts of immutable entities in one batch
The ultimate check that immutable entities are not updated is the unique constraint in the database. But we check when adding immutable entities to a batch, too, to provide a clearer and more timely error message.
1 parent e505fc0 commit a60fdc9

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

graph/src/components/store/write.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,27 @@ impl RowGroup {
474474
if self.immutable {
475475
match row {
476476
EntityModification::Insert { .. } => {
477+
// Check if this is an attempt to overwrite an immutable
478+
// entity. We allow overwriting immutable entities in
479+
// the same block, but not across blocks; if such an
480+
// attempt happens across two batches, it would result
481+
// in a database constraint violation. This check is
482+
// simply here to provide a friendlier error message and
483+
// to raise the error earlier, before we actually write
484+
// to the database
485+
match self
486+
.last_mod
487+
.get(row.id())
488+
.and_then(|&idx| self.rows.get(idx))
489+
{
490+
Some(prev) if prev.block() != row.block() => {
491+
return Err(StoreError::Input(
492+
format!("entity {} is immutable; inserting it at block {} is not possible as it was already inserted at block {}",
493+
row.key(), row.block(), prev.block())));
494+
}
495+
_ => { /* nothing to check */ }
496+
}
497+
477498
self.push_row(row);
478499
}
479500
EntityModification::Overwrite { .. } | EntityModification::Remove { .. } => {

graph/src/schema/entity_key.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,17 @@ impl std::fmt::Debug for EntityKey {
5959
)
6060
}
6161
}
62+
63+
impl std::fmt::Display for EntityKey {
64+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65+
if self.causality_region == CausalityRegion::ONCHAIN {
66+
write!(f, "{}[{}]", self.entity_type, self.entity_id)
67+
} else {
68+
write!(
69+
f,
70+
"{}/{}[{}]",
71+
self.entity_type, self.causality_region, self.entity_id
72+
)
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)