mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Add GQL requests caching in eden-watcher (#234)
This commit is contained in:
parent
74741184ee
commit
1ad223db4d
@ -28,6 +28,17 @@
|
|||||||
# Interval in number of blocks at which to clear entities cache.
|
# Interval in number of blocks at which to clear entities cache.
|
||||||
clearEntitiesCacheInterval = 1000
|
clearEntitiesCacheInterval = 1000
|
||||||
|
|
||||||
|
# GQL cache settings
|
||||||
|
[server.gqlCache]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Max in-memory cache size (in bytes) (default 8 MB)
|
||||||
|
# maxCacheSize
|
||||||
|
|
||||||
|
# GQL cache-control max-age settings (in seconds)
|
||||||
|
maxAge = 15
|
||||||
|
timeTravelMaxAge = 86400 # 1 day
|
||||||
|
|
||||||
[metrics]
|
[metrics]
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
port = 9000
|
port = 9000
|
||||||
|
@ -8,7 +8,7 @@ import debug from 'debug';
|
|||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
import { GraphQLResolveInfo, GraphQLScalarType } from 'graphql';
|
import { GraphQLResolveInfo, GraphQLScalarType } from 'graphql';
|
||||||
|
|
||||||
import { BlockHeight, OrderDirection, gqlTotalQueryCount, gqlQueryCount, jsonBigIntStringReplacer, getResultState } from '@cerc-io/util';
|
import { BlockHeight, OrderDirection, gqlTotalQueryCount, gqlQueryCount, jsonBigIntStringReplacer, getResultState, setGQLCacheHints } from '@cerc-io/util';
|
||||||
|
|
||||||
import { Indexer } from './indexer';
|
import { Indexer } from './indexer';
|
||||||
import { EventWatcher } from './events';
|
import { EventWatcher } from './events';
|
||||||
@ -37,6 +37,8 @@ const log = debug('vulcanize:resolver');
|
|||||||
export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatcher): Promise<any> => {
|
export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatcher): Promise<any> => {
|
||||||
assert(indexer);
|
assert(indexer);
|
||||||
|
|
||||||
|
const gqlCacheConfig = indexer.serverConfig.gqlCache;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
BigInt: new BigInt('bigInt'),
|
BigInt: new BigInt('bigInt'),
|
||||||
|
|
||||||
@ -88,6 +90,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producer').inc(1);
|
gqlQueryCount.labels('producer').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Producer, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Producer, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -102,6 +107,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producers').inc(1);
|
gqlQueryCount.labels('producers').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntities(
|
return indexer.getSubgraphEntities(
|
||||||
Producer,
|
Producer,
|
||||||
block,
|
block,
|
||||||
@ -122,6 +130,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producerSet').inc(1);
|
gqlQueryCount.labels('producerSet').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(ProducerSet, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(ProducerSet, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -136,6 +147,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producerSetChange').inc(1);
|
gqlQueryCount.labels('producerSetChange').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(ProducerSetChange, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(ProducerSetChange, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -150,6 +164,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producerRewardCollectorChange').inc(1);
|
gqlQueryCount.labels('producerRewardCollectorChange').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(ProducerRewardCollectorChange, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(ProducerRewardCollectorChange, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -164,6 +181,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('rewardScheduleEntry').inc(1);
|
gqlQueryCount.labels('rewardScheduleEntry').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(RewardScheduleEntry, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(RewardScheduleEntry, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -178,6 +198,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('rewardSchedule').inc(1);
|
gqlQueryCount.labels('rewardSchedule').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(RewardSchedule, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(RewardSchedule, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -192,6 +215,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('producerEpoch').inc(1);
|
gqlQueryCount.labels('producerEpoch').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(ProducerEpoch, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(ProducerEpoch, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -206,6 +232,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('block').inc(1);
|
gqlQueryCount.labels('block').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Block, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Block, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -220,6 +249,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('blocks').inc(1);
|
gqlQueryCount.labels('blocks').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntities(
|
return indexer.getSubgraphEntities(
|
||||||
Block,
|
Block,
|
||||||
block,
|
block,
|
||||||
@ -240,6 +272,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('epoch').inc(1);
|
gqlQueryCount.labels('epoch').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Epoch, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Epoch, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -254,6 +289,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('epoches').inc(1);
|
gqlQueryCount.labels('epoches').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntities(
|
return indexer.getSubgraphEntities(
|
||||||
Epoch,
|
Epoch,
|
||||||
block,
|
block,
|
||||||
@ -274,6 +312,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('slotClaim').inc(1);
|
gqlQueryCount.labels('slotClaim').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(SlotClaim, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(SlotClaim, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -288,6 +329,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('slot').inc(1);
|
gqlQueryCount.labels('slot').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Slot, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Slot, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -302,6 +346,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('staker').inc(1);
|
gqlQueryCount.labels('staker').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Staker, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Staker, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -316,6 +363,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('stakers').inc(1);
|
gqlQueryCount.labels('stakers').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntities(
|
return indexer.getSubgraphEntities(
|
||||||
Staker,
|
Staker,
|
||||||
block,
|
block,
|
||||||
@ -336,6 +386,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('network').inc(1);
|
gqlQueryCount.labels('network').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Network, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Network, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -364,6 +417,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('distribution').inc(1);
|
gqlQueryCount.labels('distribution').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Distribution, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Distribution, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -378,6 +434,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('claim').inc(1);
|
gqlQueryCount.labels('claim').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Claim, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Claim, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -392,6 +451,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('slash').inc(1);
|
gqlQueryCount.labels('slash').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Slash, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Slash, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -406,6 +468,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
gqlQueryCount.labels('account').inc(1);
|
gqlQueryCount.labels('account').inc(1);
|
||||||
assert(info.fieldNodes[0].selectionSet);
|
assert(info.fieldNodes[0].selectionSet);
|
||||||
|
|
||||||
|
// Set cache-control hints
|
||||||
|
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||||
|
|
||||||
return indexer.getSubgraphEntity(Account, id, block, info.fieldNodes[0].selectionSet.selections);
|
return indexer.getSubgraphEntity(Account, id, block, info.fieldNodes[0].selectionSet.selections);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
enum CacheControlScope {
|
||||||
|
PUBLIC
|
||||||
|
PRIVATE
|
||||||
|
}
|
||||||
|
|
||||||
|
directive @cacheControl(
|
||||||
|
maxAge: Int
|
||||||
|
scope: CacheControlScope
|
||||||
|
inheritMaxAge: Boolean
|
||||||
|
) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
|
||||||
|
|
||||||
scalar BigInt
|
scalar BigInt
|
||||||
|
|
||||||
scalar Bytes
|
scalar Bytes
|
||||||
@ -264,14 +275,14 @@ type Producer {
|
|||||||
|
|
||||||
type ProducerSet {
|
type ProducerSet {
|
||||||
id: ID!
|
id: ID!
|
||||||
producers: [Producer!]!
|
producers: [Producer!]! @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProducerSetChange {
|
type ProducerSetChange {
|
||||||
id: ID!
|
id: ID!
|
||||||
blockNumber: BigInt!
|
blockNumber: BigInt!
|
||||||
producer: Bytes!
|
producer: Bytes!
|
||||||
changeType: ProducerSetChangeType!
|
changeType: ProducerSetChangeType! @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ProducerSetChangeType {
|
enum ProducerSetChangeType {
|
||||||
@ -295,10 +306,10 @@ type RewardScheduleEntry {
|
|||||||
|
|
||||||
type RewardSchedule {
|
type RewardSchedule {
|
||||||
id: ID!
|
id: ID!
|
||||||
rewardScheduleEntries: [RewardScheduleEntry!]!
|
rewardScheduleEntries: [RewardScheduleEntry!]! @cacheControl(inheritMaxAge: true)
|
||||||
lastEpoch: Epoch
|
lastEpoch: Epoch @cacheControl(inheritMaxAge: true)
|
||||||
pendingEpoch: Epoch
|
pendingEpoch: Epoch @cacheControl(inheritMaxAge: true)
|
||||||
activeRewardScheduleEntry: RewardScheduleEntry
|
activeRewardScheduleEntry: RewardScheduleEntry @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Block {
|
type Block {
|
||||||
@ -336,12 +347,12 @@ type Epoch {
|
|||||||
id: ID!
|
id: ID!
|
||||||
finalized: Boolean!
|
finalized: Boolean!
|
||||||
epochNumber: BigInt!
|
epochNumber: BigInt!
|
||||||
startBlock: Block
|
startBlock: Block @cacheControl(inheritMaxAge: true)
|
||||||
endBlock: Block
|
endBlock: Block @cacheControl(inheritMaxAge: true)
|
||||||
producerBlocks: BigInt!
|
producerBlocks: BigInt!
|
||||||
allBlocks: BigInt!
|
allBlocks: BigInt!
|
||||||
producerBlocksRatio: BigDecimal!
|
producerBlocksRatio: BigDecimal!
|
||||||
producerRewards: [ProducerEpoch!]!
|
producerRewards: [ProducerEpoch!]! @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
input Epoch_filter {
|
input Epoch_filter {
|
||||||
@ -352,7 +363,7 @@ input Epoch_filter {
|
|||||||
type ProducerEpoch {
|
type ProducerEpoch {
|
||||||
id: ID!
|
id: ID!
|
||||||
address: Bytes!
|
address: Bytes!
|
||||||
epoch: Epoch!
|
epoch: Epoch! @cacheControl(inheritMaxAge: true)
|
||||||
totalRewards: BigInt!
|
totalRewards: BigInt!
|
||||||
blocksProduced: BigInt!
|
blocksProduced: BigInt!
|
||||||
blocksProducedRatio: BigDecimal!
|
blocksProducedRatio: BigDecimal!
|
||||||
@ -360,7 +371,7 @@ type ProducerEpoch {
|
|||||||
|
|
||||||
type SlotClaim {
|
type SlotClaim {
|
||||||
id: ID!
|
id: ID!
|
||||||
slot: Slot!
|
slot: Slot! @cacheControl(inheritMaxAge: true)
|
||||||
owner: Bytes!
|
owner: Bytes!
|
||||||
winningBid: BigInt!
|
winningBid: BigInt!
|
||||||
oldBid: BigInt!
|
oldBid: BigInt!
|
||||||
@ -378,7 +389,7 @@ type Slot {
|
|||||||
startTime: BigInt!
|
startTime: BigInt!
|
||||||
expirationTime: BigInt!
|
expirationTime: BigInt!
|
||||||
taxRatePerDay: BigDecimal!
|
taxRatePerDay: BigDecimal!
|
||||||
claims: [SlotClaim!]!
|
claims: [SlotClaim!]! @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Staker {
|
type Staker {
|
||||||
@ -397,10 +408,10 @@ enum Staker_orderBy {
|
|||||||
|
|
||||||
type Network {
|
type Network {
|
||||||
id: ID!
|
id: ID!
|
||||||
slot0: Slot
|
slot0: Slot @cacheControl(inheritMaxAge: true)
|
||||||
slot1: Slot
|
slot1: Slot @cacheControl(inheritMaxAge: true)
|
||||||
slot2: Slot
|
slot2: Slot @cacheControl(inheritMaxAge: true)
|
||||||
stakers: [Staker!]!
|
stakers: [Staker!]! @cacheControl(inheritMaxAge: true)
|
||||||
numStakers: BigInt
|
numStakers: BigInt
|
||||||
totalStaked: BigInt!
|
totalStaked: BigInt!
|
||||||
stakedPercentiles: [BigInt!]!
|
stakedPercentiles: [BigInt!]!
|
||||||
@ -408,12 +419,12 @@ type Network {
|
|||||||
|
|
||||||
type Distributor {
|
type Distributor {
|
||||||
id: ID!
|
id: ID!
|
||||||
currentDistribution: Distribution
|
currentDistribution: Distribution @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Distribution {
|
type Distribution {
|
||||||
id: ID!
|
id: ID!
|
||||||
distributor: Distributor!
|
distributor: Distributor! @cacheControl(inheritMaxAge: true)
|
||||||
timestamp: BigInt!
|
timestamp: BigInt!
|
||||||
distributionNumber: BigInt!
|
distributionNumber: BigInt!
|
||||||
merkleRoot: Bytes!
|
merkleRoot: Bytes!
|
||||||
@ -424,7 +435,7 @@ type Claim {
|
|||||||
id: ID!
|
id: ID!
|
||||||
timestamp: BigInt!
|
timestamp: BigInt!
|
||||||
index: BigInt!
|
index: BigInt!
|
||||||
account: Account!
|
account: Account! @cacheControl(inheritMaxAge: true)
|
||||||
totalEarned: BigInt!
|
totalEarned: BigInt!
|
||||||
claimed: BigInt!
|
claimed: BigInt!
|
||||||
}
|
}
|
||||||
@ -433,14 +444,14 @@ type Account {
|
|||||||
id: ID!
|
id: ID!
|
||||||
totalClaimed: BigInt!
|
totalClaimed: BigInt!
|
||||||
totalSlashed: BigInt!
|
totalSlashed: BigInt!
|
||||||
claims: [Claim!]!
|
claims: [Claim!]! @cacheControl(inheritMaxAge: true)
|
||||||
slashes: [Slash!]!
|
slashes: [Slash!]! @cacheControl(inheritMaxAge: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Slash {
|
type Slash {
|
||||||
id: ID!
|
id: ID!
|
||||||
timestamp: BigInt!
|
timestamp: BigInt!
|
||||||
account: Account!
|
account: Account! @cacheControl(inheritMaxAge: true)
|
||||||
slashed: BigInt!
|
slashed: BigInt!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import { hideBin } from 'yargs/helpers';
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import 'graphql-import-node';
|
import 'graphql-import-node';
|
||||||
|
|
||||||
import { DEFAULT_CONFIG_PATH, getConfig, Config, JobQueue, KIND_ACTIVE, initClients, startGQLMetricsServer, createAndStartServer } from '@cerc-io/util';
|
import { DEFAULT_CONFIG_PATH, getConfig, Config, JobQueue, KIND_ACTIVE, initClients, startGQLMetricsServer, createAndStartServerWithCache } from '@cerc-io/util';
|
||||||
import { GraphWatcher, Database as GraphDatabase } from '@cerc-io/graph-node';
|
import { GraphWatcher, Database as GraphDatabase } from '@cerc-io/graph-node';
|
||||||
|
|
||||||
import { createResolvers } from './resolvers';
|
import { createResolvers } from './resolvers';
|
||||||
@ -37,7 +37,7 @@ export const main = async (): Promise<any> => {
|
|||||||
const config: Config = await getConfig(argv.f);
|
const config: Config = await getConfig(argv.f);
|
||||||
const { ethClient, ethProvider } = await initClients(config);
|
const { ethClient, ethProvider } = await initClients(config);
|
||||||
|
|
||||||
const { host, port, kind: watcherKind } = config.server;
|
const { kind: watcherKind } = config.server;
|
||||||
|
|
||||||
const db = new Database(config.database);
|
const db = new Database(config.database);
|
||||||
await db.init();
|
await db.init();
|
||||||
@ -79,7 +79,7 @@ export const main = async (): Promise<any> => {
|
|||||||
|
|
||||||
// Create an Express app
|
// Create an Express app
|
||||||
const app: Application = express();
|
const app: Application = express();
|
||||||
const server = createAndStartServer(app, typeDefs, resolvers, { host, port });
|
const server = createAndStartServerWithCache(app, typeDefs, resolvers, config.server);
|
||||||
|
|
||||||
startGQLMetricsServer(config);
|
startGQLMetricsServer(config);
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apollo/utils.keyvaluecache": "^1.0.1",
|
||||||
"@cerc-io/solidity-mapper": "^0.2.13",
|
"@cerc-io/solidity-mapper": "^0.2.13",
|
||||||
"@graphql-tools/schema": "^9.0.10",
|
"@graphql-tools/schema": "^9.0.10",
|
||||||
"@graphql-tools/utils": "^9.1.1",
|
"@graphql-tools/utils": "^9.1.1",
|
||||||
"apollo-server-core": "^3.11.1",
|
"apollo-server-core": "^3.11.1",
|
||||||
"apollo-server-express": "^3.11.1",
|
"apollo-server-express": "^3.11.1",
|
||||||
|
"apollo-server-plugin-response-cache": "^3.8.1",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"decimal.js": "^10.3.1",
|
"decimal.js": "^10.3.1",
|
||||||
"ethers": "^5.4.4",
|
"ethers": "^5.4.4",
|
||||||
|
@ -5,12 +5,78 @@ import { WebSocketServer } from 'ws';
|
|||||||
import { useServer } from 'graphql-ws/lib/use/ws';
|
import { useServer } from 'graphql-ws/lib/use/ws';
|
||||||
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
|
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import responseCachePlugin from 'apollo-server-plugin-response-cache';
|
||||||
|
import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
|
||||||
|
|
||||||
import { TypeSource } from '@graphql-tools/utils';
|
import { TypeSource } from '@graphql-tools/utils';
|
||||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||||
|
|
||||||
|
import { DEFAULT_MAX_GQL_CACHE_SIZE } from './constants';
|
||||||
|
import { ServerConfig } from './config';
|
||||||
|
|
||||||
const log = debug('vulcanize:server');
|
const log = debug('vulcanize:server');
|
||||||
|
|
||||||
|
export const createAndStartServerWithCache = async (
|
||||||
|
app: Application,
|
||||||
|
typeDefs: TypeSource,
|
||||||
|
resolvers: any,
|
||||||
|
serverConfig: ServerConfig
|
||||||
|
): Promise<ApolloServer> => {
|
||||||
|
const host = serverConfig.host;
|
||||||
|
const port = serverConfig.port;
|
||||||
|
const gqlCacheConfig = serverConfig.gqlCache;
|
||||||
|
|
||||||
|
// Create HTTP server
|
||||||
|
const httpServer = createServer(app);
|
||||||
|
|
||||||
|
// Create the schema
|
||||||
|
const schema = makeExecutableSchema({ typeDefs, resolvers });
|
||||||
|
|
||||||
|
// Create our WebSocket server using the HTTP server we just set up.
|
||||||
|
const wsServer = new WebSocketServer({
|
||||||
|
server: httpServer,
|
||||||
|
path: '/graphql'
|
||||||
|
});
|
||||||
|
const serverCleanup = useServer({ schema }, wsServer);
|
||||||
|
|
||||||
|
// Setup in-memory GQL cache
|
||||||
|
let gqlCache;
|
||||||
|
if (gqlCacheConfig && gqlCacheConfig.enabled) {
|
||||||
|
const maxSize = gqlCacheConfig.maxCacheSize ? gqlCacheConfig.maxCacheSize : DEFAULT_MAX_GQL_CACHE_SIZE;
|
||||||
|
gqlCache = new InMemoryLRUCache({ maxSize });
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = new ApolloServer({
|
||||||
|
schema,
|
||||||
|
csrfPrevention: true,
|
||||||
|
cache: gqlCache,
|
||||||
|
plugins: [
|
||||||
|
// Proper shutdown for the HTTP server
|
||||||
|
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||||
|
// Proper shutdown for the WebSocket server
|
||||||
|
{
|
||||||
|
async serverWillStart () {
|
||||||
|
return {
|
||||||
|
async drainServer () {
|
||||||
|
await serverCleanup.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// GQL response cache plugin
|
||||||
|
responseCachePlugin()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
await server.start();
|
||||||
|
server.applyMiddleware({ app });
|
||||||
|
|
||||||
|
httpServer.listen(port, host, () => {
|
||||||
|
log(`Server is listening on ${host}:${port}${server.graphqlPath}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
return server;
|
||||||
|
};
|
||||||
|
|
||||||
export const createAndStartServer = async (
|
export const createAndStartServer = async (
|
||||||
app: Application,
|
app: Application,
|
||||||
typeDefs: TypeSource,
|
typeDefs: TypeSource,
|
||||||
|
@ -3502,6 +3502,15 @@ apollo-server-plugin-base@^3.7.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-types "^3.7.1"
|
apollo-server-types "^3.7.1"
|
||||||
|
|
||||||
|
apollo-server-plugin-response-cache@^3.8.1:
|
||||||
|
version "3.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/apollo-server-plugin-response-cache/-/apollo-server-plugin-response-cache-3.8.1.tgz#2d9559fe9951812dcda77fc2658422028f060af8"
|
||||||
|
integrity sha512-c6bkrZjzX8Ac44CF7a4m9ans2QFV2C0XVUUDnuSWAX3G9ZWbs55NC+H3YtcFhAPoX7gv92RAu88ipMahd8NiUQ==
|
||||||
|
dependencies:
|
||||||
|
"@apollo/utils.keyvaluecache" "^1.0.1"
|
||||||
|
apollo-server-plugin-base "^3.7.1"
|
||||||
|
apollo-server-types "^3.7.1"
|
||||||
|
|
||||||
apollo-server-types@^3.7.1:
|
apollo-server-types@^3.7.1:
|
||||||
version "3.7.1"
|
version "3.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.7.1.tgz#87adfcb52ec0893999a9cfafd5474bfda7ab0798"
|
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.7.1.tgz#87adfcb52ec0893999a9cfafd5474bfda7ab0798"
|
||||||
|
Loading…
Reference in New Issue
Block a user