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.
|
||||
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]
|
||||
host = "127.0.0.1"
|
||||
port = 9000
|
||||
|
@ -8,7 +8,7 @@ import debug from 'debug';
|
||||
import Decimal from 'decimal.js';
|
||||
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 { EventWatcher } from './events';
|
||||
@ -37,6 +37,8 @@ const log = debug('vulcanize:resolver');
|
||||
export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatcher): Promise<any> => {
|
||||
assert(indexer);
|
||||
|
||||
const gqlCacheConfig = indexer.serverConfig.gqlCache;
|
||||
|
||||
return {
|
||||
BigInt: new BigInt('bigInt'),
|
||||
|
||||
@ -88,6 +90,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
||||
gqlQueryCount.labels('producer').inc(1);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
return indexer.getSubgraphEntities(
|
||||
Producer,
|
||||
block,
|
||||
@ -122,6 +130,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
||||
gqlQueryCount.labels('producerSet').inc(1);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
return indexer.getSubgraphEntities(
|
||||
Block,
|
||||
block,
|
||||
@ -240,6 +272,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
||||
gqlQueryCount.labels('epoch').inc(1);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
return indexer.getSubgraphEntities(
|
||||
Epoch,
|
||||
block,
|
||||
@ -274,6 +312,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
||||
gqlQueryCount.labels('slotClaim').inc(1);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
return indexer.getSubgraphEntities(
|
||||
Staker,
|
||||
block,
|
||||
@ -336,6 +386,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
||||
gqlQueryCount.labels('network').inc(1);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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);
|
||||
assert(info.fieldNodes[0].selectionSet);
|
||||
|
||||
// Set cache-control hints
|
||||
setGQLCacheHints(info, block, gqlCacheConfig);
|
||||
|
||||
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 Bytes
|
||||
@ -264,14 +275,14 @@ type Producer {
|
||||
|
||||
type ProducerSet {
|
||||
id: ID!
|
||||
producers: [Producer!]!
|
||||
producers: [Producer!]! @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
type ProducerSetChange {
|
||||
id: ID!
|
||||
blockNumber: BigInt!
|
||||
producer: Bytes!
|
||||
changeType: ProducerSetChangeType!
|
||||
changeType: ProducerSetChangeType! @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
enum ProducerSetChangeType {
|
||||
@ -295,10 +306,10 @@ type RewardScheduleEntry {
|
||||
|
||||
type RewardSchedule {
|
||||
id: ID!
|
||||
rewardScheduleEntries: [RewardScheduleEntry!]!
|
||||
lastEpoch: Epoch
|
||||
pendingEpoch: Epoch
|
||||
activeRewardScheduleEntry: RewardScheduleEntry
|
||||
rewardScheduleEntries: [RewardScheduleEntry!]! @cacheControl(inheritMaxAge: true)
|
||||
lastEpoch: Epoch @cacheControl(inheritMaxAge: true)
|
||||
pendingEpoch: Epoch @cacheControl(inheritMaxAge: true)
|
||||
activeRewardScheduleEntry: RewardScheduleEntry @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
type Block {
|
||||
@ -336,12 +347,12 @@ type Epoch {
|
||||
id: ID!
|
||||
finalized: Boolean!
|
||||
epochNumber: BigInt!
|
||||
startBlock: Block
|
||||
endBlock: Block
|
||||
startBlock: Block @cacheControl(inheritMaxAge: true)
|
||||
endBlock: Block @cacheControl(inheritMaxAge: true)
|
||||
producerBlocks: BigInt!
|
||||
allBlocks: BigInt!
|
||||
producerBlocksRatio: BigDecimal!
|
||||
producerRewards: [ProducerEpoch!]!
|
||||
producerRewards: [ProducerEpoch!]! @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
input Epoch_filter {
|
||||
@ -352,7 +363,7 @@ input Epoch_filter {
|
||||
type ProducerEpoch {
|
||||
id: ID!
|
||||
address: Bytes!
|
||||
epoch: Epoch!
|
||||
epoch: Epoch! @cacheControl(inheritMaxAge: true)
|
||||
totalRewards: BigInt!
|
||||
blocksProduced: BigInt!
|
||||
blocksProducedRatio: BigDecimal!
|
||||
@ -360,7 +371,7 @@ type ProducerEpoch {
|
||||
|
||||
type SlotClaim {
|
||||
id: ID!
|
||||
slot: Slot!
|
||||
slot: Slot! @cacheControl(inheritMaxAge: true)
|
||||
owner: Bytes!
|
||||
winningBid: BigInt!
|
||||
oldBid: BigInt!
|
||||
@ -378,7 +389,7 @@ type Slot {
|
||||
startTime: BigInt!
|
||||
expirationTime: BigInt!
|
||||
taxRatePerDay: BigDecimal!
|
||||
claims: [SlotClaim!]!
|
||||
claims: [SlotClaim!]! @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
type Staker {
|
||||
@ -397,10 +408,10 @@ enum Staker_orderBy {
|
||||
|
||||
type Network {
|
||||
id: ID!
|
||||
slot0: Slot
|
||||
slot1: Slot
|
||||
slot2: Slot
|
||||
stakers: [Staker!]!
|
||||
slot0: Slot @cacheControl(inheritMaxAge: true)
|
||||
slot1: Slot @cacheControl(inheritMaxAge: true)
|
||||
slot2: Slot @cacheControl(inheritMaxAge: true)
|
||||
stakers: [Staker!]! @cacheControl(inheritMaxAge: true)
|
||||
numStakers: BigInt
|
||||
totalStaked: BigInt!
|
||||
stakedPercentiles: [BigInt!]!
|
||||
@ -408,12 +419,12 @@ type Network {
|
||||
|
||||
type Distributor {
|
||||
id: ID!
|
||||
currentDistribution: Distribution
|
||||
currentDistribution: Distribution @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
type Distribution {
|
||||
id: ID!
|
||||
distributor: Distributor!
|
||||
distributor: Distributor! @cacheControl(inheritMaxAge: true)
|
||||
timestamp: BigInt!
|
||||
distributionNumber: BigInt!
|
||||
merkleRoot: Bytes!
|
||||
@ -424,7 +435,7 @@ type Claim {
|
||||
id: ID!
|
||||
timestamp: BigInt!
|
||||
index: BigInt!
|
||||
account: Account!
|
||||
account: Account! @cacheControl(inheritMaxAge: true)
|
||||
totalEarned: BigInt!
|
||||
claimed: BigInt!
|
||||
}
|
||||
@ -433,14 +444,14 @@ type Account {
|
||||
id: ID!
|
||||
totalClaimed: BigInt!
|
||||
totalSlashed: BigInt!
|
||||
claims: [Claim!]!
|
||||
slashes: [Slash!]!
|
||||
claims: [Claim!]! @cacheControl(inheritMaxAge: true)
|
||||
slashes: [Slash!]! @cacheControl(inheritMaxAge: true)
|
||||
}
|
||||
|
||||
type Slash {
|
||||
id: ID!
|
||||
timestamp: BigInt!
|
||||
account: Account!
|
||||
account: Account! @cacheControl(inheritMaxAge: true)
|
||||
slashed: BigInt!
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import { hideBin } from 'yargs/helpers';
|
||||
import debug from 'debug';
|
||||
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 { createResolvers } from './resolvers';
|
||||
@ -37,7 +37,7 @@ export const main = async (): Promise<any> => {
|
||||
const config: Config = await getConfig(argv.f);
|
||||
const { ethClient, ethProvider } = await initClients(config);
|
||||
|
||||
const { host, port, kind: watcherKind } = config.server;
|
||||
const { kind: watcherKind } = config.server;
|
||||
|
||||
const db = new Database(config.database);
|
||||
await db.init();
|
||||
@ -79,7 +79,7 @@ export const main = async (): Promise<any> => {
|
||||
|
||||
// Create an Express app
|
||||
const app: Application = express();
|
||||
const server = createAndStartServer(app, typeDefs, resolvers, { host, port });
|
||||
const server = createAndStartServerWithCache(app, typeDefs, resolvers, config.server);
|
||||
|
||||
startGQLMetricsServer(config);
|
||||
|
||||
|
@ -4,11 +4,13 @@
|
||||
"main": "dist/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@apollo/utils.keyvaluecache": "^1.0.1",
|
||||
"@cerc-io/solidity-mapper": "^0.2.13",
|
||||
"@graphql-tools/schema": "^9.0.10",
|
||||
"@graphql-tools/utils": "^9.1.1",
|
||||
"apollo-server-core": "^3.11.1",
|
||||
"apollo-server-express": "^3.11.1",
|
||||
"apollo-server-plugin-response-cache": "^3.8.1",
|
||||
"debug": "^4.3.1",
|
||||
"decimal.js": "^10.3.1",
|
||||
"ethers": "^5.4.4",
|
||||
|
@ -5,12 +5,78 @@ import { WebSocketServer } from 'ws';
|
||||
import { useServer } from 'graphql-ws/lib/use/ws';
|
||||
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
|
||||
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 { makeExecutableSchema } from '@graphql-tools/schema';
|
||||
|
||||
import { DEFAULT_MAX_GQL_CACHE_SIZE } from './constants';
|
||||
import { ServerConfig } from './config';
|
||||
|
||||
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 (
|
||||
app: Application,
|
||||
typeDefs: TypeSource,
|
||||
|
@ -3502,6 +3502,15 @@ apollo-server-plugin-base@^3.7.1:
|
||||
dependencies:
|
||||
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:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.7.1.tgz#87adfcb52ec0893999a9cfafd5474bfda7ab0798"
|
||||
|
Loading…
Reference in New Issue
Block a user