mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-06 19:38:05 +00:00
Support fragments in GQL queries for subgraph watchers (#510)
* Avoid updating latest block metrics on RPC errors * Handle fragments in subgraph GQL queries * Upgrade package versions * Move private method in util graph database --------- Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
This commit is contained in:
parent
1ca74548ff
commit
b57aa76d9f
@ -2,7 +2,7 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"command": {
|
"command": {
|
||||||
|
2
packages/cache/package.json
vendored
2
packages/cache/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/cache",
|
"name": "@cerc-io/cache",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "Generic object cache",
|
"description": "Generic object cache",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/cli",
|
"name": "@cerc-io/cli",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -15,13 +15,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.7.1",
|
"@apollo/client": "^3.7.1",
|
||||||
"@cerc-io/cache": "^0.2.88",
|
"@cerc-io/cache": "^0.2.89",
|
||||||
"@cerc-io/ipld-eth-client": "^0.2.88",
|
"@cerc-io/ipld-eth-client": "^0.2.89",
|
||||||
"@cerc-io/libp2p": "^0.42.2-laconic-0.1.4",
|
"@cerc-io/libp2p": "^0.42.2-laconic-0.1.4",
|
||||||
"@cerc-io/nitro-node": "^0.1.15",
|
"@cerc-io/nitro-node": "^0.1.15",
|
||||||
"@cerc-io/peer": "^0.2.88",
|
"@cerc-io/peer": "^0.2.89",
|
||||||
"@cerc-io/rpc-eth-client": "^0.2.88",
|
"@cerc-io/rpc-eth-client": "^0.2.89",
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
"@ethersproject/providers": "^5.4.4",
|
"@ethersproject/providers": "^5.4.4",
|
||||||
"@graphql-tools/utils": "^9.1.1",
|
"@graphql-tools/utils": "^9.1.1",
|
||||||
"@ipld/dag-cbor": "^8.0.0",
|
"@ipld/dag-cbor": "^8.0.0",
|
||||||
|
@ -8,8 +8,6 @@ import debug from 'debug';
|
|||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
import JsonRpcProvider = ethers.providers.JsonRpcProvider;
|
import JsonRpcProvider = ethers.providers.JsonRpcProvider;
|
||||||
|
|
||||||
import { fetchLatestBlockNumber } from '@cerc-io/util';
|
|
||||||
|
|
||||||
const log = debug('laconic:chain-head-exporter');
|
const log = debug('laconic:chain-head-exporter');
|
||||||
|
|
||||||
// Env overrides:
|
// Env overrides:
|
||||||
@ -57,16 +55,20 @@ async function main (): Promise<void> {
|
|||||||
registers: [metricsRegister],
|
registers: [metricsRegister],
|
||||||
labelNames: ['chain'] as const,
|
labelNames: ['chain'] as const,
|
||||||
async collect () {
|
async collect () {
|
||||||
const [
|
try {
|
||||||
latestEthBlockNumber,
|
const [
|
||||||
latestFilBlockNumber
|
latestEthBlockNumber,
|
||||||
] = await Promise.all([
|
latestFilBlockNumber
|
||||||
fetchLatestBlockNumber(ethProvider),
|
] = await Promise.all([
|
||||||
fetchLatestBlockNumber(filProvider)
|
ethProvider.getBlockNumber(),
|
||||||
]);
|
filProvider.getBlockNumber()
|
||||||
|
]);
|
||||||
|
|
||||||
this.set({ chain: 'ethereum' }, latestEthBlockNumber);
|
this.set({ chain: 'ethereum' }, latestEthBlockNumber);
|
||||||
this.set({ chain: 'filecoin' }, latestFilBlockNumber);
|
this.set({ chain: 'filecoin' }, latestFilBlockNumber);
|
||||||
|
} catch (err) {
|
||||||
|
log('Error fetching latest block number', err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/codegen",
|
"name": "@cerc-io/codegen",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "Code generator",
|
"description": "Code generator",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
"@graphql-tools/load-files": "^6.5.2",
|
"@graphql-tools/load-files": "^6.5.2",
|
||||||
"@npmcli/package-json": "^5.0.0",
|
"@npmcli/package-json": "^5.0.0",
|
||||||
"@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git",
|
"@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git",
|
||||||
|
@ -10,7 +10,7 @@ import JSONbig from 'json-bigint';
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
import { ethers, constants } from 'ethers';
|
import { ethers, constants } from 'ethers';
|
||||||
{{#if (subgraphPath)}}
|
{{#if (subgraphPath)}}
|
||||||
import { SelectionNode } from 'graphql';
|
import { GraphQLResolveInfo } from 'graphql';
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
import { JsonFragment } from '@ethersproject/abi';
|
import { JsonFragment } from '@ethersproject/abi';
|
||||||
@ -458,9 +458,9 @@ export class Indexer implements IndexerInterface {
|
|||||||
entity: new () => Entity,
|
entity: new () => Entity,
|
||||||
id: string,
|
id: string,
|
||||||
block: BlockHeight,
|
block: BlockHeight,
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const data = await this._graphWatcher.getEntity(entity, id, this._relationsMap, block, selections);
|
const data = await this._graphWatcher.getEntity(entity, id, this._relationsMap, block, queryInfo);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -470,9 +470,9 @@ export class Indexer implements IndexerInterface {
|
|||||||
block: BlockHeight,
|
block: BlockHeight,
|
||||||
where: { [key: string]: any } = {},
|
where: { [key: string]: any } = {},
|
||||||
queryOptions: QueryOptions = {},
|
queryOptions: QueryOptions = {},
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<any[]> {
|
): Promise<any[]> {
|
||||||
return this._graphWatcher.getEntities(entity, this._relationsMap, block, where, queryOptions, selections);
|
return this._graphWatcher.getEntities(entity, this._relationsMap, block, where, queryOptions, queryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -41,12 +41,12 @@
|
|||||||
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.3.19",
|
"@apollo/client": "^3.3.19",
|
||||||
"@cerc-io/cli": "^0.2.88",
|
"@cerc-io/cli": "^0.2.89",
|
||||||
"@cerc-io/ipld-eth-client": "^0.2.88",
|
"@cerc-io/ipld-eth-client": "^0.2.89",
|
||||||
"@cerc-io/solidity-mapper": "^0.2.88",
|
"@cerc-io/solidity-mapper": "^0.2.89",
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
{{#if (subgraphPath)}}
|
{{#if (subgraphPath)}}
|
||||||
"@cerc-io/graph-node": "^0.2.88",
|
"@cerc-io/graph-node": "^0.2.89",
|
||||||
{{/if}}
|
{{/if}}
|
||||||
"@ethersproject/providers": "^5.4.4",
|
"@ethersproject/providers": "^5.4.4",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
|
@ -106,12 +106,11 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
|
|||||||
log('{{this.queryName}}', id, JSON.stringify(block, jsonBigIntStringReplacer));
|
log('{{this.queryName}}', id, JSON.stringify(block, jsonBigIntStringReplacer));
|
||||||
gqlTotalQueryCount.inc(1);
|
gqlTotalQueryCount.inc(1);
|
||||||
gqlQueryCount.labels('{{this.queryName}}').inc(1);
|
gqlQueryCount.labels('{{this.queryName}}').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
|
||||||
|
|
||||||
// Set cache-control hints
|
// Set cache-control hints
|
||||||
// setGQLCacheHints(info, block, gqlCacheConfig);
|
// setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity({{this.entityName}}, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity({{this.entityName}}, id, block, info);
|
||||||
},
|
},
|
||||||
|
|
||||||
{{this.pluralQueryName}}: async (
|
{{this.pluralQueryName}}: async (
|
||||||
@ -123,7 +122,6 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
|
|||||||
log('{{this.pluralQueryName}}', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);
|
log('{{this.pluralQueryName}}', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);
|
||||||
gqlTotalQueryCount.inc(1);
|
gqlTotalQueryCount.inc(1);
|
||||||
gqlQueryCount.labels('{{this.pluralQueryName}}').inc(1);
|
gqlQueryCount.labels('{{this.pluralQueryName}}').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
|
||||||
|
|
||||||
// Set cache-control hints
|
// Set cache-control hints
|
||||||
// setGQLCacheHints(info, block, gqlCacheConfig);
|
// setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
@ -133,7 +131,7 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{ limit: first, skip, orderBy, orderDirection },
|
{ limit: first, skip, orderBy, orderDirection },
|
||||||
info.fieldNodes[0].selectionSet.selections
|
info
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/graph-node",
|
"name": "@cerc-io/graph-node",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cerc-io/solidity-mapper": "^0.2.88",
|
"@cerc-io/solidity-mapper": "^0.2.89",
|
||||||
"@ethersproject/providers": "^5.4.4",
|
"@ethersproject/providers": "^5.4.4",
|
||||||
"@graphprotocol/graph-ts": "^0.22.0",
|
"@graphprotocol/graph-ts": "^0.22.0",
|
||||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
@ -51,9 +51,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.3.19",
|
"@apollo/client": "^3.3.19",
|
||||||
"@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2",
|
"@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2",
|
||||||
"@cerc-io/cache": "^0.2.88",
|
"@cerc-io/cache": "^0.2.89",
|
||||||
"@cerc-io/ipld-eth-client": "^0.2.88",
|
"@cerc-io/ipld-eth-client": "^0.2.89",
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
"@types/json-diff": "^0.5.2",
|
"@types/json-diff": "^0.5.2",
|
||||||
"@types/yargs": "^17.0.0",
|
"@types/yargs": "^17.0.0",
|
||||||
"bn.js": "^4.11.9",
|
"bn.js": "^4.11.9",
|
||||||
|
@ -8,7 +8,7 @@ import debug from 'debug';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { ContractInterface, utils, providers } from 'ethers';
|
import { ContractInterface, utils, providers } from 'ethers';
|
||||||
import { SelectionNode } from 'graphql';
|
import { GraphQLResolveInfo, SelectionNode } from 'graphql';
|
||||||
|
|
||||||
import { ResultObject } from '@cerc-io/assemblyscript/lib/loader';
|
import { ResultObject } from '@cerc-io/assemblyscript/lib/loader';
|
||||||
import {
|
import {
|
||||||
@ -321,13 +321,15 @@ export class GraphWatcher {
|
|||||||
id: string,
|
id: string,
|
||||||
relationsMap: Map<any, { [key: string]: any }>,
|
relationsMap: Map<any, { [key: string]: any }>,
|
||||||
block: BlockHeight,
|
block: BlockHeight,
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const dbTx = await this._database.createTransactionRunner();
|
const dbTx = await this._database.createTransactionRunner();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const selections = this._getSelectionsFromGQLInfo(queryInfo);
|
||||||
|
|
||||||
// Get entity from the database.
|
// Get entity from the database.
|
||||||
const result = await this._database.getEntityWithRelations(dbTx, entity, id, relationsMap, block, selections);
|
const result = await this._database.getEntityWithRelations(dbTx, entity, id, relationsMap, block, selections, queryInfo);
|
||||||
await dbTx.commitTransaction();
|
await dbTx.commitTransaction();
|
||||||
|
|
||||||
// Resolve any field name conflicts in the entity result.
|
// Resolve any field name conflicts in the entity result.
|
||||||
@ -346,7 +348,7 @@ export class GraphWatcher {
|
|||||||
block: BlockHeight,
|
block: BlockHeight,
|
||||||
where: { [key: string]: any } = {},
|
where: { [key: string]: any } = {},
|
||||||
queryOptions: QueryOptions,
|
queryOptions: QueryOptions,
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const dbTx = await this._database.createTransactionRunner();
|
const dbTx = await this._database.createTransactionRunner();
|
||||||
|
|
||||||
@ -357,8 +359,10 @@ export class GraphWatcher {
|
|||||||
queryOptions.limit = DEFAULT_LIMIT;
|
queryOptions.limit = DEFAULT_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selections = this._getSelectionsFromGQLInfo(queryInfo);
|
||||||
|
|
||||||
// Get entities from the database.
|
// Get entities from the database.
|
||||||
const entities = await this._database.getEntities(dbTx, entity, relationsMap, block, where, queryOptions, selections);
|
const entities = await this._database.getEntities(dbTx, entity, relationsMap, block, where, queryOptions, selections, queryInfo);
|
||||||
await dbTx.commitTransaction();
|
await dbTx.commitTransaction();
|
||||||
|
|
||||||
return entities;
|
return entities;
|
||||||
@ -553,6 +557,14 @@ export class GraphWatcher {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getSelectionsFromGQLInfo (queryInfo: GraphQLResolveInfo): readonly SelectionNode[] {
|
||||||
|
const [fieldNode] = queryInfo.fieldNodes;
|
||||||
|
const selectionSet = fieldNode.selectionSet;
|
||||||
|
assert(selectionSet, `selectionSet not present in GQL fieldNode ${fieldNode.name}`);
|
||||||
|
|
||||||
|
return selectionSet.selections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGraphDbAndWatcher = async (
|
export const getGraphDbAndWatcher = async (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/ipld-eth-client",
|
"name": "@cerc-io/ipld-eth-client",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "IPLD ETH Client",
|
"description": "IPLD ETH Client",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -20,8 +20,8 @@
|
|||||||
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.7.1",
|
"@apollo/client": "^3.7.1",
|
||||||
"@cerc-io/cache": "^0.2.88",
|
"@cerc-io/cache": "^0.2.89",
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
"cross-fetch": "^3.1.4",
|
"cross-fetch": "^3.1.4",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"ethers": "^5.4.4",
|
"ethers": "^5.4.4",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/peer",
|
"name": "@cerc-io/peer",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "libp2p module",
|
"description": "libp2p module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/rpc-eth-client",
|
"name": "@cerc-io/rpc-eth-client",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "RPC ETH Client",
|
"description": "RPC ETH Client",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -19,9 +19,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cerc-io/cache": "^0.2.88",
|
"@cerc-io/cache": "^0.2.89",
|
||||||
"@cerc-io/ipld-eth-client": "^0.2.88",
|
"@cerc-io/ipld-eth-client": "^0.2.89",
|
||||||
"@cerc-io/util": "^0.2.88",
|
"@cerc-io/util": "^0.2.89",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"ethers": "^5.4.4",
|
"ethers": "^5.4.4",
|
||||||
"left-pad": "^1.3.0",
|
"left-pad": "^1.3.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/solidity-mapper",
|
"name": "@cerc-io/solidity-mapper",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/test",
|
"name": "@cerc-io/test",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/tracing-client",
|
"name": "@cerc-io/tracing-client",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "ETH VM tracing client",
|
"description": "ETH VM tracing client",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@cerc-io/util",
|
"name": "@cerc-io/util",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/utils.keyvaluecache": "^1.0.1",
|
"@apollo/utils.keyvaluecache": "^1.0.1",
|
||||||
"@cerc-io/nitro-node": "^0.1.15",
|
"@cerc-io/nitro-node": "^0.1.15",
|
||||||
"@cerc-io/peer": "^0.2.88",
|
"@cerc-io/peer": "^0.2.89",
|
||||||
"@cerc-io/solidity-mapper": "^0.2.88",
|
"@cerc-io/solidity-mapper": "^0.2.89",
|
||||||
"@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1",
|
"@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1",
|
||||||
"@ethersproject/properties": "^5.7.0",
|
"@ethersproject/properties": "^5.7.0",
|
||||||
"@ethersproject/providers": "^5.4.4",
|
"@ethersproject/providers": "^5.4.4",
|
||||||
@ -52,7 +52,7 @@
|
|||||||
"yargs": "^17.0.1"
|
"yargs": "^17.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cerc-io/cache": "^0.2.88",
|
"@cerc-io/cache": "^0.2.89",
|
||||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||||
"@types/bunyan": "^1.8.8",
|
"@types/bunyan": "^1.8.8",
|
||||||
"@types/express": "^4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
|
import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
|
||||||
import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer';
|
import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer';
|
||||||
import { SelectionNode } from 'graphql';
|
import { GraphQLResolveInfo, SelectionNode } from 'graphql';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
|
||||||
@ -221,7 +221,8 @@ export class GraphDatabase {
|
|||||||
id: string,
|
id: string,
|
||||||
relationsMap: Map<any, { [key: string]: any }>,
|
relationsMap: Map<any, { [key: string]: any }>,
|
||||||
block: CanonicalBlockHeight = {},
|
block: CanonicalBlockHeight = {},
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
selections: ReadonlyArray<SelectionNode> = [],
|
||||||
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<Entity | undefined> {
|
): Promise<Entity | undefined> {
|
||||||
const { hash: blockHash, number: blockNumber } = block;
|
const { hash: blockHash, number: blockNumber } = block;
|
||||||
const repo = queryRunner.manager.getRepository<Entity>(entityType);
|
const repo = queryRunner.manager.getRepository<Entity>(entityType);
|
||||||
@ -248,7 +249,7 @@ export class GraphDatabase {
|
|||||||
|
|
||||||
// Get relational fields
|
// Get relational fields
|
||||||
if (entityData) {
|
if (entityData) {
|
||||||
entityData = await this.loadEntityRelations(queryRunner, block, relationsMap, entityType, entityData, selections);
|
entityData = await this.loadEntityRelations(queryRunner, block, relationsMap, entityType, entityData, selections, queryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entityData;
|
return entityData;
|
||||||
@ -259,7 +260,8 @@ export class GraphDatabase {
|
|||||||
block: CanonicalBlockHeight,
|
block: CanonicalBlockHeight,
|
||||||
relationsMap: Map<any, { [key: string]: any }>,
|
relationsMap: Map<any, { [key: string]: any }>,
|
||||||
entityType: new () => Entity, entityData: any,
|
entityType: new () => Entity, entityData: any,
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
selections: ReadonlyArray<SelectionNode> = [],
|
||||||
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<Entity> {
|
): Promise<Entity> {
|
||||||
const relations = relationsMap.get(entityType);
|
const relations = relationsMap.get(entityType);
|
||||||
if (relations === undefined) {
|
if (relations === undefined) {
|
||||||
@ -292,7 +294,8 @@ export class GraphDatabase {
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{ limit: DEFAULT_LIMIT },
|
{ limit: DEFAULT_LIMIT },
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
entityData[field] = relatedEntities;
|
entityData[field] = relatedEntities;
|
||||||
@ -316,7 +319,8 @@ export class GraphDatabase {
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{ limit: DEFAULT_LIMIT },
|
{ limit: DEFAULT_LIMIT },
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
entityData[field] = relatedEntities;
|
entityData[field] = relatedEntities;
|
||||||
@ -331,7 +335,8 @@ export class GraphDatabase {
|
|||||||
entityData[field],
|
entityData[field],
|
||||||
relationsMap,
|
relationsMap,
|
||||||
block,
|
block,
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
entityData[field] = relatedEntity;
|
entityData[field] = relatedEntity;
|
||||||
@ -349,11 +354,14 @@ export class GraphDatabase {
|
|||||||
block: CanonicalBlockHeight = {},
|
block: CanonicalBlockHeight = {},
|
||||||
where: Where = {},
|
where: Where = {},
|
||||||
queryOptions: QueryOptions = {},
|
queryOptions: QueryOptions = {},
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
selections: ReadonlyArray<SelectionNode> = [],
|
||||||
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<Entity[]> {
|
): Promise<Entity[]> {
|
||||||
let entities: Entity[] = [];
|
let entities: Entity[] = [];
|
||||||
const latestEntityType = this._entityToLatestEntityMap.get(entityType);
|
const latestEntityType = this._entityToLatestEntityMap.get(entityType);
|
||||||
|
|
||||||
|
const defragmentedSelections = this._defragmentGQLQuerySelections(selections, queryInfo);
|
||||||
|
|
||||||
if (latestEntityType) {
|
if (latestEntityType) {
|
||||||
if (Object.keys(block).length) {
|
if (Object.keys(block).length) {
|
||||||
// Use lateral query for entities with latest entity table.
|
// Use lateral query for entities with latest entity table.
|
||||||
@ -375,7 +383,7 @@ export class GraphDatabase {
|
|||||||
relationsMap,
|
relationsMap,
|
||||||
where,
|
where,
|
||||||
queryOptions,
|
queryOptions,
|
||||||
selections
|
defragmentedSelections
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -405,7 +413,7 @@ export class GraphDatabase {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
entities = await this.loadEntitiesRelations(queryRunner, block, relationsMap, entityType, entities, selections);
|
entities = await this.loadEntitiesRelations(queryRunner, block, relationsMap, entityType, entities, defragmentedSelections, queryInfo);
|
||||||
// Resolve any field name conflicts in the entity result.
|
// Resolve any field name conflicts in the entity result.
|
||||||
entities = entities.map(entity => resolveEntityFieldConflicts(entity));
|
entities = entities.map(entity => resolveEntityFieldConflicts(entity));
|
||||||
|
|
||||||
@ -744,7 +752,8 @@ export class GraphDatabase {
|
|||||||
relationsMap: Map<any, { [key: string]: any }>,
|
relationsMap: Map<any, { [key: string]: any }>,
|
||||||
entity: new () => Entity,
|
entity: new () => Entity,
|
||||||
entities: Entity[],
|
entities: Entity[],
|
||||||
selections: ReadonlyArray<SelectionNode> = []
|
selections: ReadonlyArray<SelectionNode> = [],
|
||||||
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<Entity[]> {
|
): Promise<Entity[]> {
|
||||||
const relations = relationsMap.get(entity);
|
const relations = relationsMap.get(entity);
|
||||||
if (relations === undefined) {
|
if (relations === undefined) {
|
||||||
@ -755,11 +764,11 @@ export class GraphDatabase {
|
|||||||
|
|
||||||
if (this._serverConfig.loadRelationsSequential) {
|
if (this._serverConfig.loadRelationsSequential) {
|
||||||
for (const selection of relationSelections) {
|
for (const selection of relationSelections) {
|
||||||
await this.loadRelation(queryRunner, block, relationsMap, relations, entities, selection);
|
await this.loadRelation(queryRunner, block, relationsMap, relations, entities, selection, queryInfo);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const loadRelationPromises = relationSelections.map(async selection => {
|
const loadRelationPromises = relationSelections.map(async selection => {
|
||||||
await this.loadRelation(queryRunner, block, relationsMap, relations, entities, selection);
|
await this.loadRelation(queryRunner, block, relationsMap, relations, entities, selection, queryInfo);
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(loadRelationPromises);
|
await Promise.all(loadRelationPromises);
|
||||||
@ -774,7 +783,8 @@ export class GraphDatabase {
|
|||||||
relationsMap: Map<any, { [key: string]: any }>,
|
relationsMap: Map<any, { [key: string]: any }>,
|
||||||
relations: { [key: string]: any },
|
relations: { [key: string]: any },
|
||||||
entities: Entity[],
|
entities: Entity[],
|
||||||
selection: SelectionNode
|
selection: SelectionNode,
|
||||||
|
queryInfo: GraphQLResolveInfo
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
assert(selection.kind === 'Field');
|
assert(selection.kind === 'Field');
|
||||||
const field = selection.name.value;
|
const field = selection.name.value;
|
||||||
@ -800,7 +810,8 @@ export class GraphDatabase {
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{},
|
{},
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
const relatedEntitiesMap = relatedEntities.reduce((acc: {[key:string]: any[]}, entity: any) => {
|
const relatedEntitiesMap = relatedEntities.reduce((acc: {[key:string]: any[]}, entity: any) => {
|
||||||
@ -851,7 +862,8 @@ export class GraphDatabase {
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{},
|
{},
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
entities.forEach((entity: any) => {
|
entities.forEach((entity: any) => {
|
||||||
@ -902,7 +914,8 @@ export class GraphDatabase {
|
|||||||
block,
|
block,
|
||||||
where,
|
where,
|
||||||
{},
|
{},
|
||||||
childSelections
|
childSelections,
|
||||||
|
queryInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
const relatedEntitiesMap = relatedEntities.reduce((acc: {[key:string]: any}, entity: any) => {
|
const relatedEntitiesMap = relatedEntities.reduce((acc: {[key:string]: any}, entity: any) => {
|
||||||
@ -1321,4 +1334,16 @@ export class GraphDatabase {
|
|||||||
log(`Total entities in cachedEntities.latestPrunedEntities map: ${totalEntities}`);
|
log(`Total entities in cachedEntities.latestPrunedEntities map: ${totalEntities}`);
|
||||||
cachePrunedEntitiesCount.set(totalEntities);
|
cachePrunedEntitiesCount.set(totalEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_defragmentGQLQuerySelections (selections: ReadonlyArray<SelectionNode>, queryInfo: GraphQLResolveInfo): SelectionNode[] {
|
||||||
|
return selections.reduce((acc: SelectionNode[], selection) => {
|
||||||
|
if (selection.kind === 'FragmentSpread') {
|
||||||
|
const fragmentSelections = queryInfo.fragments[selection.name.value].selectionSet.selections;
|
||||||
|
|
||||||
|
return [...acc, ...fragmentSelections];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...acc, selection];
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,15 +18,6 @@ const DB_SIZE_QUERY = 'SELECT pg_database_size(current_database())';
|
|||||||
|
|
||||||
const log = debug('vulcanize:metrics');
|
const log = debug('vulcanize:metrics');
|
||||||
|
|
||||||
export async function fetchLatestBlockNumber (provider: JsonRpcProvider): Promise<number> {
|
|
||||||
try {
|
|
||||||
return await provider.getBlockNumber();
|
|
||||||
} catch (err) {
|
|
||||||
log('Error fetching latest block number', err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create custom metrics
|
// Create custom metrics
|
||||||
|
|
||||||
export const lastJobCompletedOn = new client.Gauge({
|
export const lastJobCompletedOn = new client.Gauge({
|
||||||
@ -212,8 +203,12 @@ const registerUpstreamChainHeadMetrics = async ({ upstream }: Config, rpcProvide
|
|||||||
name: 'latest_upstream_block_number',
|
name: 'latest_upstream_block_number',
|
||||||
help: 'Latest upstream block number',
|
help: 'Latest upstream block number',
|
||||||
async collect () {
|
async collect () {
|
||||||
const latestBlockNumber = await fetchLatestBlockNumber(ethRpcProvider);
|
try {
|
||||||
this.set(latestBlockNumber);
|
const blockNumber = await ethRpcProvider.getBlockNumber();
|
||||||
|
this.set(blockNumber);
|
||||||
|
} catch (err) {
|
||||||
|
log('Error fetching latest block number', err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user