Skip to content

Commit f74a423

Browse files
committed
graph, store: address review comments
- Remove logs and the logger from the RowGroup - Simplify schema tests - Add ObjectMutability enum instead of two booleans
1 parent 59d8bc7 commit f74a423

11 files changed

Lines changed: 88 additions & 221 deletions

File tree

graph/examples/append_row.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,7 @@ pub fn main() -> anyhow::Result<()> {
104104
};
105105
mods.push(md);
106106
}
107-
let mut group = RowGroup::new(
108-
THING_TYPE.clone(),
109-
false,
110-
false,
111-
slog::Logger::root(slog::Discard, slog::o!()),
112-
);
107+
let mut group = RowGroup::new(THING_TYPE.clone());
113108

114109
let start = Instant::now();
115110
for md in mods {

graph/src/components/store/write.rs

Lines changed: 15 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{
44
sync::Arc,
55
};
66

7-
use slog::{warn, Logger};
7+
use slog::Logger;
88

99
use crate::{
1010
blockchain::{block_stream::FirehoseCursor, BlockPtr, BlockTime},
@@ -340,33 +340,22 @@ impl LastMod {
340340
#[derive(Debug, CacheWeight)]
341341
pub struct RowGroup {
342342
pub entity_type: EntityType,
343+
343344
/// All changes for this entity type, ordered by block; i.e., if `i < j`
344345
/// then `rows[i].block() <= rows[j].block()`. Several methods on this
345346
/// struct rely on the fact that this ordering is observed.
346347
rows: Vec<EntityModification>,
347348

348-
immutable: bool,
349-
skip_duplicates: bool,
350-
logger: Logger,
351-
352349
/// Map the `key.entity_id` of all entries in `rows` to the index with
353350
/// the most recent entry for that id to speed up lookups.
354351
last_mod: LastMod,
355352
}
356353

357354
impl RowGroup {
358-
pub fn new(
359-
entity_type: EntityType,
360-
immutable: bool,
361-
skip_duplicates: bool,
362-
logger: Logger,
363-
) -> Self {
355+
pub fn new(entity_type: EntityType) -> Self {
364356
Self {
365357
entity_type,
366358
rows: Vec::new(),
367-
immutable,
368-
skip_duplicates,
369-
logger,
370359
last_mod: LastMod::new(),
371360
}
372361
}
@@ -482,7 +471,7 @@ impl RowGroup {
482471
/// Append `row` to `self.rows` by combining it with a previously
483472
/// existing row, if that is possible
484473
fn append_row(&mut self, row: EntityModification) -> Result<(), StoreError> {
485-
if self.immutable {
474+
if self.entity_type.is_immutable() {
486475
match row {
487476
EntityModification::Insert { .. } => {
488477
// Check if this is an attempt to overwrite an immutable
@@ -499,11 +488,7 @@ impl RowGroup {
499488
.and_then(|&idx| self.rows.get(idx))
500489
{
501490
Some(prev) if prev.block() != row.block() => {
502-
if self.skip_duplicates {
503-
warn!(self.logger, "Skipping duplicate insert for immutable entity";
504-
"entity" => row.key().to_string(),
505-
"block" => row.block(),
506-
"previous_block" => prev.block());
491+
if self.entity_type.skip_duplicates() {
507492
return Ok(());
508493
}
509494
return Err(StoreError::Input(
@@ -516,10 +501,7 @@ impl RowGroup {
516501
self.push_row(row);
517502
}
518503
EntityModification::Overwrite { .. } | EntityModification::Remove { .. } => {
519-
if self.skip_duplicates {
520-
warn!(self.logger, "Skipping unsupported operation for immutable entity";
521-
"entity_type" => self.entity_type.to_string(),
522-
"operation" => format!("{:?}", row));
504+
if self.entity_type.skip_duplicates() {
523505
return Ok(());
524506
}
525507
return Err(internal_error!(
@@ -628,18 +610,8 @@ impl RowGroup {
628610
pub struct RowGroupForPerfTest(RowGroup);
629611

630612
impl RowGroupForPerfTest {
631-
pub fn new(
632-
entity_type: EntityType,
633-
immutable: bool,
634-
skip_duplicates: bool,
635-
logger: Logger,
636-
) -> Self {
637-
Self(RowGroup::new(
638-
entity_type,
639-
immutable,
640-
skip_duplicates,
641-
logger,
642-
))
613+
pub fn new(entity_type: EntityType) -> Self {
614+
Self(RowGroup::new(entity_type))
643615
}
644616

645617
pub fn push(&mut self, emod: EntityModification, block: BlockNumber) -> Result<(), StoreError> {
@@ -722,14 +694,7 @@ impl RowGroups {
722694
match pos {
723695
Some(pos) => &mut self.groups[pos],
724696
None => {
725-
let immutable = entity_type.is_immutable();
726-
let skip_duplicates = entity_type.skip_duplicates();
727-
self.groups.push(RowGroup::new(
728-
entity_type.clone(),
729-
immutable,
730-
skip_duplicates,
731-
self.logger.clone(),
732-
));
697+
self.groups.push(RowGroup::new(entity_type.clone()));
733698
// unwrap: we just pushed an entry
734699
self.groups.last_mut().unwrap()
735700
}
@@ -1092,8 +1057,6 @@ mod test {
10921057
};
10931058
use lazy_static::lazy_static;
10941059

1095-
use slog::Logger;
1096-
10971060
use super::{LastMod, RowGroup};
10981061

10991062
#[track_caller]
@@ -1125,9 +1088,6 @@ mod test {
11251088
let group = RowGroup {
11261089
entity_type: ENTRY_TYPE.clone(),
11271090
rows,
1128-
immutable: false,
1129-
skip_duplicates: false,
1130-
logger: Logger::root(slog::Discard, slog::o!()),
11311091
last_mod,
11321092
};
11331093
let act = group
@@ -1239,12 +1199,7 @@ mod test {
12391199
impl Group {
12401200
fn new() -> Self {
12411201
Self {
1242-
group: RowGroup::new(
1243-
THING_TYPE.clone(),
1244-
false,
1245-
false,
1246-
Logger::root(slog::Discard, slog::o!()),
1247-
),
1202+
group: RowGroup::new(THING_TYPE.clone()),
12481203
}
12491204
}
12501205

@@ -1379,13 +1334,9 @@ mod test {
13791334
}
13801335
}
13811336

1382-
fn discard_logger() -> Logger {
1383-
Logger::root(slog::Discard, slog::o!())
1384-
}
1385-
13861337
#[test]
13871338
fn append_row_immutable_default_rejects_cross_block_duplicate() {
1388-
let mut group = RowGroup::new(IMM_THING_TYPE.clone(), true, false, discard_logger());
1339+
let mut group = RowGroup::new(IMM_THING_TYPE.clone());
13891340
let res = group.push(make_insert(&IMM_THING_TYPE, "one", 1), 1);
13901341
assert!(res.is_ok());
13911342
let res = group.push(make_insert(&IMM_THING_TYPE, "one", 2), 2);
@@ -1394,7 +1345,7 @@ mod test {
13941345

13951346
#[test]
13961347
fn append_row_skip_duplicates_allows_cross_block_duplicate() {
1397-
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone(), true, true, discard_logger());
1348+
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone());
13981349
let res = group.push(make_insert(&SKIP_DUP_THING_TYPE, "one", 1), 1);
13991350
assert!(res.is_ok());
14001351
let res = group.push(make_insert(&SKIP_DUP_THING_TYPE, "one", 2), 2);
@@ -1404,21 +1355,21 @@ mod test {
14041355

14051356
#[test]
14061357
fn append_row_skip_duplicates_allows_overwrite() {
1407-
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone(), true, true, discard_logger());
1358+
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone());
14081359
let res = group.append_row(make_overwrite(&SKIP_DUP_THING_TYPE, "one", 1));
14091360
assert!(res.is_ok());
14101361
}
14111362

14121363
#[test]
14131364
fn append_row_skip_duplicates_allows_remove() {
1414-
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone(), true, true, discard_logger());
1365+
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone());
14151366
let res = group.append_row(make_remove(&SKIP_DUP_THING_TYPE, "one", 1));
14161367
assert!(res.is_ok());
14171368
}
14181369

14191370
#[test]
14201371
fn append_row_skip_duplicates_same_block_still_pushes() {
1421-
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone(), true, true, discard_logger());
1372+
let mut group = RowGroup::new(SKIP_DUP_THING_TYPE.clone());
14221373
let res = group.push(make_insert(&SKIP_DUP_THING_TYPE, "one", 1), 1);
14231374
assert!(res.is_ok());
14241375
let res = group.push(make_insert(&SKIP_DUP_THING_TYPE, "one", 1), 1);

graph/src/schema/input/mod.rs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,22 @@ impl TypeInfo {
126126

127127
fn is_immutable(&self) -> bool {
128128
match self {
129-
TypeInfo::Object(obj_type) => obj_type.immutable,
129+
TypeInfo::Object(obj_type) => {
130+
matches!(obj_type.mutability, ObjectMutability::Immutable { .. })
131+
}
130132
TypeInfo::Interface(_) => false,
131133
TypeInfo::Aggregation(_) => true,
132134
}
133135
}
134136

135137
fn skip_duplicates(&self) -> bool {
136138
match self {
137-
TypeInfo::Object(obj_type) => obj_type.immutable && obj_type.skip_duplicates,
139+
TypeInfo::Object(obj_type) => matches!(
140+
obj_type.mutability,
141+
ObjectMutability::Immutable {
142+
skip_duplicates: true
143+
}
144+
),
138145
TypeInfo::Interface(_) => false,
139146
TypeInfo::Aggregation(_) => false,
140147
}
@@ -418,12 +425,11 @@ pub struct ObjectType {
418425
pub name: Atom,
419426
pub id_type: IdType,
420427
pub fields: Box<[Field]>,
421-
pub immutable: bool,
428+
pub mutability: ObjectMutability,
422429
/// The name of the aggregation to which this object type belongs if it
423430
/// is part of an aggregation
424431
aggregation: Option<Atom>,
425432
pub timeseries: bool,
426-
pub skip_duplicates: bool,
427433
interfaces: Box<[Word]>,
428434
shared_interfaces: Box<[Atom]>,
429435
}
@@ -458,23 +464,30 @@ impl ObjectType {
458464
None => false,
459465
_ => unreachable!("validations ensure we don't get here"),
460466
};
461-
let immutable = match dir.argument("immutable") {
467+
let immutable = match dir.argument(kw::IMMUTABLE) {
462468
Some(Value::Boolean(im)) => *im,
463469
None => timeseries,
464470
_ => unreachable!("validations ensure we don't get here"),
465471
};
466-
let skip_duplicates = match dir.argument(kw::SKIP_DUPLICATES) {
467-
Some(Value::Boolean(sd)) => *sd,
468-
_ => false,
472+
473+
let mutability = if immutable {
474+
let skip_duplicates = match dir.argument(kw::SKIP_DUPLICATES) {
475+
Some(Value::Boolean(sd)) => *sd,
476+
_ => false,
477+
};
478+
479+
ObjectMutability::Immutable { skip_duplicates }
480+
} else {
481+
ObjectMutability::Mutable
469482
};
483+
470484
Self {
471485
name,
472486
fields,
473487
id_type,
474-
immutable,
488+
mutability,
475489
aggregation: None,
476490
timeseries,
477-
skip_duplicates,
478491
interfaces,
479492
shared_interfaces,
480493
}
@@ -503,10 +516,9 @@ impl ObjectType {
503516
name,
504517
interfaces: Box::new([]),
505518
id_type: IdType::String,
506-
immutable: false,
519+
mutability: ObjectMutability::Mutable,
507520
aggregation: None,
508521
timeseries: false,
509-
skip_duplicates: false,
510522
fields,
511523
shared_interfaces: Box::new([]),
512524
}
@@ -522,6 +534,12 @@ impl ObjectType {
522534
}
523535
}
524536

537+
#[derive(Debug, Clone, Copy, PartialEq)]
538+
pub enum ObjectMutability {
539+
Mutable,
540+
Immutable { skip_duplicates: bool },
541+
}
542+
525543
#[derive(PartialEq, Debug)]
526544
pub struct InterfaceType {
527545
pub name: Atom,
@@ -902,10 +920,11 @@ impl Aggregation {
902920
.cloned()
903921
.chain(aggregates.iter().map(Aggregate::as_agg_field))
904922
.collect(),
905-
immutable: true,
923+
mutability: ObjectMutability::Immutable {
924+
skip_duplicates: false,
925+
},
906926
aggregation: Some(name),
907927
timeseries: false,
908-
skip_duplicates: false,
909928
interfaces: Box::new([]),
910929
shared_interfaces: Box::new([]),
911930
}
@@ -1368,7 +1387,7 @@ impl InputSchema {
13681387
TypeInfo::Object(obj_type) => Some(obj_type),
13691388
TypeInfo::Interface(_) | TypeInfo::Aggregation(_) => None,
13701389
})
1371-
.filter(|obj_type| obj_type.immutable)
1390+
.filter(|obj_type| matches!(obj_type.mutability, ObjectMutability::Immutable { .. }))
13721391
.map(|obj_type| EntityType::new(self.cheap_clone(), obj_type.name))
13731392
}
13741393

@@ -3187,43 +3206,6 @@ type Gravatar @entity {
31873206
}
31883207
}
31893208
}
3190-
3191-
#[test]
3192-
fn validate_entity_directives_skip_duplicates_non_boolean() {
3193-
let schema =
3194-
parse("type Foo @entity(immutable: true, skipDuplicates: \"yes\") { id: ID! }");
3195-
let errors = validate(&schema).unwrap_err();
3196-
assert!(
3197-
errors.contains(&SchemaValidationError::EntityDirectiveNonBooleanArgValue(
3198-
"skipDuplicates".to_string()
3199-
)),
3200-
"expected EntityDirectiveNonBooleanArgValue for non-boolean skipDuplicates, got: {errors:?}"
3201-
);
3202-
}
3203-
3204-
#[test]
3205-
fn validate_entity_directives_skip_duplicates_requires_immutable() {
3206-
let schema = parse("type Foo @entity(skipDuplicates: true) { id: ID! }");
3207-
let errors = validate(&schema).unwrap_err();
3208-
assert!(
3209-
errors.contains(&SchemaValidationError::SkipDuplicatesRequiresImmutable(
3210-
"Foo".to_string()
3211-
)),
3212-
"expected SkipDuplicatesRequiresImmutable for mutable entity, got: {errors:?}"
3213-
);
3214-
}
3215-
3216-
#[test]
3217-
fn validate_entity_directives_timeseries_skip_duplicates_valid() {
3218-
let schema = parse(
3219-
"type Foo @entity(timeseries: true, skipDuplicates: true) { id: Int8! timestamp: Timestamp! }",
3220-
);
3221-
let result = validate(&schema);
3222-
assert!(
3223-
result.is_ok(),
3224-
"expected timeseries + skipDuplicates to pass validation, got: {result:?}"
3225-
);
3226-
}
32273209
}
32283210
}
32293211

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# fail: EntityDirectiveNonBooleanArgValue("skipDuplicates")
2+
3+
type Data @entity(immutable: true, skipDuplicates: "yes") {
4+
id: Bytes!
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# fail: SkipDuplicatesRequiresImmutable("Data")
2+
3+
type Data @entity(skipDuplicates: true) {
4+
id: Bytes!
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# valid: Minimal example
2+
3+
type Data @entity(immutable: true, skipDuplicates: true) {
4+
id: Bytes!
5+
}

0 commit comments

Comments
 (0)