Skip to content

Commit

Permalink
common: implement resolveGraftedSubgraphDeployment function
Browse files Browse the repository at this point in the history
  • Loading branch information
tilacog committed Oct 24, 2023
1 parent 1867f41 commit 302db9b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 12 deletions.
87 changes: 75 additions & 12 deletions packages/indexer-common/src/grafting.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import { SubgraphDeploymentID } from '@graphprotocol/common-ts'
import { GraphNodeInterface } from './graph-node'
import { BlockPointer, SubgraphManifest } from './types'
import {
BlockPointer,
SubgraphDeploymentDecision,
SubgraphDeploymentDecisionKind,
SubgraphManifest,
} from './types'
import { indexerError, IndexerErrorCode } from './errors'

type SubgraphManifestResolver = (
subgraphID: SubgraphDeploymentID,
) => Promise<SubgraphManifest>

interface IndexingStatus {
latestBlock: BlockPointer | null
health: string
synced: boolean
}

export interface GraftBase {
block: number
base: SubgraphDeploymentID
Expand All @@ -13,18 +28,17 @@ export interface GraftableSubgraph {
graft: GraftBase | null // Root subgraph does not have a graft base
}

type SubgraphManifestResolver = (
subgraphID: SubgraphDeploymentID,
) => Promise<SubgraphManifest>

interface IndexingStatus {
latestBlock: BlockPointer | null
health: string
synced: boolean
interface GraftableSubgraphStatus extends GraftableSubgraph {
indexingStatus: IndexingStatus | null
}

interface SubgraphGraftStatus extends GraftableSubgraph {
indexingStatus: IndexingStatus | null
// TODO: use this type instead of a plain list.
// Benefits: No need to check for graft base block on the adjacent sibling.
interface SubgraphGraftLineage {
target: SubgraphDeploymentID
root: GraftBase
// list of descending graft bases, except the root.
bases: GraftBase[]
}

// Discovers all graft dependencies for a given subgraph
Expand Down Expand Up @@ -64,7 +78,7 @@ export async function discoverGraftBases(
export async function getIndexingStatusOfGraftableSubgraph(
subgraph: GraftableSubgraph,
graphNode: GraphNodeInterface,
): Promise<SubgraphGraftStatus> {
): Promise<GraftableSubgraphStatus> {
let response
try {
response = await graphNode.indexingStatus([subgraph.deployment])
Expand All @@ -88,3 +102,52 @@ export async function getIndexingStatusOfGraftableSubgraph(
}
return { ...subgraph, indexingStatus }
}

export function resolveGraftedSubgraphDeployment(
subgraphLineage: GraftableSubgraphStatus[],
): SubgraphDeploymentDecision[] {
const deploymentDecisions: SubgraphDeploymentDecision[] = []

// Check lineage size before making any assumptions.
if (subgraphLineage.length < 2) {
throw new Error(
`Invalid input: Expected at least two members in graft lineage but got ${subgraphLineage.length}`,
)
}
// Check for any unsynced base.
// Iterate backwards while ignoring the target deployment (first element).
for (let i = subgraphLineage.length - 1; i > 1; i--) {
const graft = subgraphLineage[i]

// Block height is stored in the previous element in the lineage list.
// Since we are skipping the root (last element), the graft info is expected to be present.
const desiredBlockHeight = subgraphLineage[i - 1].graft!.block

if (!graft.indexingStatus || !graft.indexingStatus.latestBlock) {
// Graph Node is not aware of this subgraph deployment. We must deploy it and look no further.
deploymentDecisions.push({
deployment: graft.deployment,
deploymentDecision: SubgraphDeploymentDecisionKind.DEPLOY,
})
break
} else {
// Deployment exists.

// Is it sufficiently synced?
if (graft.indexingStatus.latestBlock.number >= desiredBlockHeight) {
// If so, we can stop syncing it.
deploymentDecisions.push({
deployment: graft.deployment,
deploymentDecision: SubgraphDeploymentDecisionKind.REMOVE,
})
continue
}

// Is it healthy?
if (graft.indexingStatus.health !== 'healthy') {
throw new Error(`Unhealthy graft base: ${graft.deployment}`)
}
}
}
return deploymentDecisions
}
12 changes: 12 additions & 0 deletions packages/indexer-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,15 @@ export const SubgraphManifestSchema = z.object({
})

export type SubgraphManifest = z.infer<typeof SubgraphManifestSchema>

export enum SubgraphDeploymentDecisionKind {
CREATE = 'create',
DEPLOY = 'deploy',
REMOVE = 'remove',
// Possible new members: PAUSE, DROP, NOOP
}

export interface SubgraphDeploymentDecision {
deployment: SubgraphDeploymentID
deploymentDecision: SubgraphDeploymentDecisionKind
}

0 comments on commit 302db9b

Please sign in to comment.