Skip to content

Commit f2cbb6f

Browse files
committed
refactor: use graph client in subgraph health api
1 parent d836123 commit f2cbb6f

File tree

3 files changed

+211
-18
lines changed

3 files changed

+211
-18
lines changed

common/src/indexer_service/http/health.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use crate::subgraph_client::Query;
54
use axum::{
65
extract::Path,
76
response::{IntoResponse, Response as AxumResponse},
87
Extension, Json,
98
};
9+
use graphql_client::GraphQLQuery;
1010
use indexer_config::GraphNodeConfig;
1111
use reqwest::StatusCode;
1212
use serde::{Deserialize, Serialize};
@@ -37,6 +37,15 @@ struct Message {
3737
message: String,
3838
}
3939

40+
#[derive(GraphQLQuery)]
41+
#[graphql(
42+
schema_path = "../graphql/indexing_status.schema.graphql",
43+
query_path = "../graphql/subgraph_health.query.graphql",
44+
response_derives = "Debug",
45+
variables_derives = "Clone"
46+
)]
47+
pub struct HealthQuery;
48+
4049
#[derive(Deserialize, Debug)]
4150
#[allow(non_camel_case_types)]
4251
enum Health {
@@ -84,25 +93,16 @@ pub async fn health(
8493
Path(deployment_id): Path<String>,
8594
Extension(graph_node): Extension<GraphNodeConfig>,
8695
) -> Result<impl IntoResponse, CheckHealthError> {
87-
let body = Query::new_with_variables(
88-
r#"
89-
query indexingStatuses($ids: [String!]!) {
90-
indexingStatuses(subgraphs: $ids) {
91-
health
92-
fatalError {
93-
message
94-
}
95-
nonFatalErrors {
96-
message
97-
}
98-
}
99-
}
100-
"#,
101-
[("ids", json!([deployment_id]))],
102-
);
96+
let req_body = HealthQuery::build_query(health_query::Variables {
97+
ids: vec![deployment_id],
98+
});
10399

104100
let client = reqwest::Client::new();
105-
let response = client.post(graph_node.status_url).json(&body).send().await;
101+
let response = client
102+
.post(graph_node.status_url)
103+
.json(&req_body)
104+
.send()
105+
.await;
106106
let res = response.expect("Failed to get response");
107107
let response_json: Result<Response, reqwest::Error> = res.json().await;
108108

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
schema {
2+
query: Query
3+
}
4+
5+
type ApiVersion {
6+
"""
7+
Version number in SemVer format
8+
9+
"""
10+
version: String!
11+
}
12+
13+
scalar BigInt
14+
15+
type Block {
16+
hash: Bytes!
17+
number: BigInt!
18+
}
19+
20+
input BlockInput {
21+
hash: Bytes!
22+
number: BigInt!
23+
}
24+
25+
scalar Bytes
26+
27+
type CachedEthereumCall {
28+
idHash: Bytes!
29+
block: Block!
30+
contractAddress: Bytes!
31+
returnValue: Bytes!
32+
}
33+
34+
interface ChainIndexingStatus {
35+
network: String!
36+
chainHeadBlock: Block
37+
earliestBlock: EarliestBlock
38+
latestBlock: Block
39+
lastHealthyBlock: Block
40+
}
41+
42+
scalar Date
43+
44+
type EarliestBlock {
45+
hash: Bytes!
46+
number: BigInt!
47+
}
48+
49+
type EntityChanges {
50+
updates: [EntityTypeUpdates!]!
51+
deletions: [EntityTypeDeletions!]!
52+
}
53+
54+
type EntityTypeDeletions {
55+
type: String!
56+
entities: [ID!]!
57+
}
58+
59+
type EntityTypeUpdates {
60+
type: String!
61+
entities: [JSONObject!]!
62+
}
63+
64+
type EthereumIndexingStatus implements ChainIndexingStatus {
65+
network: String!
66+
chainHeadBlock: Block
67+
earliestBlock: EarliestBlock
68+
latestBlock: Block
69+
lastHealthyBlock: Block
70+
}
71+
72+
enum Feature {
73+
nonFatalErrors
74+
grafting
75+
fullTextSearch
76+
ipfsOnEthereumContracts
77+
aggregations
78+
declaredEthCalls
79+
immutableEntities
80+
bytesAsIds
81+
}
82+
83+
enum Health {
84+
"""Subgraph syncing normally"""
85+
healthy
86+
"""Subgraph syncing but with errors"""
87+
unhealthy
88+
"""Subgraph halted due to errors"""
89+
failed
90+
}
91+
92+
scalar JSONObject
93+
94+
type PartialBlock {
95+
hash: Bytes
96+
number: BigInt!
97+
}
98+
99+
input ProofOfIndexingRequest {
100+
deployment: String!
101+
block: BlockInput!
102+
}
103+
104+
type ProofOfIndexingResult {
105+
deployment: String!
106+
block: Block!
107+
"""
108+
There may not be a proof of indexing available for the deployment and block
109+
"""
110+
proofOfIndexing: Bytes
111+
}
112+
113+
input PublicProofOfIndexingRequest {
114+
deployment: String!
115+
blockNumber: BigInt!
116+
}
117+
118+
type PublicProofOfIndexingResult {
119+
deployment: String!
120+
block: PartialBlock!
121+
proofOfIndexing: Bytes!
122+
}
123+
124+
type Query {
125+
indexingStatusForCurrentVersion(subgraphName: String!): SubgraphIndexingStatus
126+
indexingStatusForPendingVersion(subgraphName: String!): SubgraphIndexingStatus
127+
indexingStatusesForSubgraphName(subgraphName: String!): [SubgraphIndexingStatus!]!
128+
indexingStatuses(subgraphs: [String!]): [SubgraphIndexingStatus!]!
129+
proofOfIndexing(subgraph: String!, blockNumber: Int!, blockHash: Bytes!, indexer: Bytes): Bytes
130+
"""
131+
Proofs of indexing for several deployments and blocks that can be shared and
132+
compared in public without revealing the _actual_ proof of indexing that every
133+
indexer has in their database
134+
135+
"""
136+
publicProofsOfIndexing(requests: [PublicProofOfIndexingRequest!]!): [PublicProofOfIndexingResult!]!
137+
subgraphFeatures(subgraphId: String!): SubgraphFeatures!
138+
entityChangesInBlock(subgraphId: String!, blockNumber: Int!): EntityChanges!
139+
blockData(network: String!, blockHash: Bytes!): JSONObject
140+
blockHashFromNumber(network: String!, blockNumber: Int!): Bytes
141+
version: Version!
142+
cachedEthereumCalls(network: String!, blockHash: Bytes!): [CachedEthereumCall!]
143+
apiVersions(subgraphId: String!): [ApiVersion!]!
144+
}
145+
146+
type SubgraphError {
147+
message: String!
148+
block: Block
149+
handler: String
150+
deterministic: Boolean!
151+
}
152+
153+
type SubgraphFeatures {
154+
apiVersion: String
155+
specVersion: String!
156+
features: [Feature!]!
157+
dataSources: [String!]!
158+
handlers: [String!]!
159+
network: String
160+
}
161+
162+
type SubgraphIndexingStatus {
163+
subgraph: String!
164+
synced: Boolean!
165+
health: Health!
166+
"""If the subgraph has failed, this is the error caused it"""
167+
fatalError: SubgraphError
168+
"""Sorted from first to last, limited to first 1000"""
169+
nonFatalErrors: [SubgraphError!]!
170+
chains: [ChainIndexingStatus!]!
171+
entityCount: BigInt!
172+
"""null if deployment is not assigned to an indexing node"""
173+
node: String
174+
"""null if deployment is not assigned to an indexing node"""
175+
paused: Boolean
176+
historyBlocks: Int!
177+
}
178+
179+
type Version {
180+
version: String!
181+
commit: String!
182+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
query HealthQuery($ids: [String!]!) {
2+
indexingStatuses(subgraphs: $ids) {
3+
health
4+
fatalError {
5+
message
6+
}
7+
nonFatalErrors {
8+
message
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)