Skip to content

Commit 25f1d73

Browse files
graph: emit a block only when there's a block_ptr
After this was merged #5160 substreams fatal errors can write SubgraphError{ block_ptr: None }. This introduces a bug that shows in Status API as those records can surface as fatalError.block = null violating the schema of type Block { hash: Bytes! number: BigInt! } A later commit #5971 makes it much easier to trigger this when doing a status API that returns all subgraphs (empty [] array for deployment ID) as failed substreams linger on in the indexing status set as paused instead of being unassigned.
1 parent 55b9465 commit 25f1d73

File tree

1 file changed

+80
-23
lines changed

1 file changed

+80
-23
lines changed

graph/src/data/subgraph/status.rs

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,6 @@ impl IntoValue for Info {
132132
history_blocks,
133133
} = self;
134134

135-
fn subgraph_error_to_value(subgraph_error: SubgraphError) -> r::Value {
136-
let SubgraphError {
137-
subgraph_id,
138-
message,
139-
block_ptr,
140-
handler,
141-
deterministic,
142-
} = subgraph_error;
143-
144-
object! {
145-
__typename: "SubgraphError",
146-
subgraphId: subgraph_id.to_string(),
147-
message: message,
148-
handler: handler,
149-
block: object! {
150-
__typename: "Block",
151-
number: block_ptr.as_ref().map(|x| x.number),
152-
hash: block_ptr.map(|x| r::Value::from(Value::Bytes(x.hash.into()))),
153-
},
154-
deterministic: deterministic,
155-
}
156-
}
157-
158135
let non_fatal_errors: Vec<_> = non_fatal_errors
159136
.into_iter()
160137
.map(subgraph_error_to_value)
@@ -176,3 +153,83 @@ impl IntoValue for Info {
176153
}
177154
}
178155
}
156+
157+
fn subgraph_error_to_value(subgraph_error: SubgraphError) -> r::Value {
158+
let SubgraphError {
159+
subgraph_id,
160+
message,
161+
block_ptr,
162+
handler,
163+
deterministic,
164+
} = subgraph_error;
165+
166+
let block_value = block_ptr
167+
.map(|ptr| {
168+
object! {
169+
__typename: "Block",
170+
number: ptr.number,
171+
hash: r::Value::from(Value::Bytes(ptr.hash.into())),
172+
}
173+
})
174+
.unwrap_or(r::Value::Null);
175+
176+
object! {
177+
__typename: "SubgraphError",
178+
subgraphId: subgraph_id.to_string(),
179+
message: message,
180+
handler: handler,
181+
block: block_value,
182+
deterministic: deterministic,
183+
}
184+
}
185+
186+
#[cfg(test)]
187+
mod tests {
188+
use super::*;
189+
use crate::prelude::DeploymentHash;
190+
use web3::types::H256;
191+
192+
#[test]
193+
fn subgraph_error_block_is_null_without_pointer() {
194+
let deployment = DeploymentHash::new("QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco").unwrap();
195+
let value = subgraph_error_to_value(SubgraphError {
196+
subgraph_id: deployment,
197+
message: "boom".to_string(),
198+
block_ptr: None,
199+
handler: None,
200+
deterministic: true,
201+
});
202+
203+
match value {
204+
r::Value::Object(map) => {
205+
assert_eq!(map.get("block"), Some(&r::Value::Null));
206+
}
207+
_ => panic!("expected object"),
208+
}
209+
}
210+
211+
#[test]
212+
fn subgraph_error_block_contains_data_when_present() {
213+
let deployment = DeploymentHash::new("QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco").unwrap();
214+
let ptr = BlockPtr::new(H256::zero().into(), 42);
215+
let value = subgraph_error_to_value(SubgraphError {
216+
subgraph_id: deployment,
217+
message: "boom".to_string(),
218+
block_ptr: Some(ptr),
219+
handler: None,
220+
deterministic: true,
221+
});
222+
223+
match value {
224+
r::Value::Object(map) => {
225+
match map.get("block").expect("block field present") {
226+
r::Value::Object(block) => {
227+
assert_eq!(block.get("number"), Some(&r::Value::Int(42.into())));
228+
}
229+
other => panic!("unexpected block value {other:?}"),
230+
}
231+
}
232+
_ => panic!("expected object"),
233+
}
234+
}
235+
}

0 commit comments

Comments
 (0)