Skip to content

Commit d3f4974

Browse files
committed
indexer-service: Fix tests and improve readability
1 parent 62effa0 commit d3f4974

File tree

3 files changed

+130
-103
lines changed

3 files changed

+130
-103
lines changed

packages/indexer-service/jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ module.exports = {
2424
process.env.POSTGRES_TEST_DATABASE ||
2525
bail('POSTGRES_TEST_DATABASE is not defined'),
2626
},
27+
__LOG_LEVEL__: process.env.LOG_LEVEL || 'info'
2728
},
2829
}

packages/indexer-service/src/server/__tests__/server.test.ts

Lines changed: 126 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
* Assumes a graph-node is running
33
*/
44

5+
import http from 'http'
56
import supertest from 'supertest'
6-
import express from 'express'
77
import { BigNumber, ethers, Wallet } from 'ethers'
8+
import { Sequelize } from 'sequelize'
9+
import { Socket } from 'net'
810

911
import {
1012
connectContracts,
1113
connectDatabase,
1214
createLogger,
1315
createMetrics,
16+
Logger,
1417
NetworkContracts,
1518
toAddress,
1619
} from '@graphprotocol/common-ts'
@@ -29,13 +32,15 @@ import {
2932
NetworkSubgraph,
3033
QueryFeeModels,
3134
} from '@graphprotocol/indexer-common'
32-
import { Sequelize } from 'sequelize'
3335

3436
// Make global Jest variable available
3537
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3638
declare const __DATABASE__: any
39+
declare const __LOG_LEVEL__: never
3740

38-
let app: express.Express
41+
let logger: Logger
42+
let server: http.Server
43+
let sockets: Socket[] = []
3944
let sequelize: Sequelize
4045
let models: IndexerManagementModels
4146
let queryFeeModels: QueryFeeModels
@@ -46,111 +51,133 @@ let networkSubgraph: NetworkSubgraph
4651
let client: IndexerManagementClient
4752
let receiptManager: AllocationReceiptManager
4853

49-
describe('Server', () => {
50-
beforeAll(async () => {
51-
const logger = createLogger({ name: 'server.test.ts', level: 'trace' })
52-
const metrics = createMetrics()
53-
54-
sequelize = await connectDatabase(__DATABASE__)
55-
56-
queryFeeModels = defineQueryFeeModels(sequelize)
57-
models = defineIndexerManagementModels(sequelize)
58-
address = '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1'
59-
contracts = await connectContracts(ethers.getDefaultProvider('rinkeby'), 4)
60-
await sequelize.sync({ force: true })
61-
indexingStatusResolver = new IndexingStatusResolver({
62-
logger: logger,
63-
statusEndpoint: 'http://localhost:8030/graphql',
64-
})
65-
networkSubgraph = await NetworkSubgraph.create({
66-
logger,
67-
endpoint: 'https://gateway.testnet.thegraph.com/network',
68-
deployment: undefined,
69-
})
54+
const setup = async () => {
55+
logger = createLogger({ name: 'server.test.ts', async: false, level: __LOG_LEVEL__ })
56+
const metrics = createMetrics()
7057

71-
client = await createIndexerManagementClient({
72-
models,
73-
address,
74-
contracts,
75-
indexingStatusResolver,
76-
networkSubgraph,
77-
logger,
78-
defaults: {
79-
// This is just a dummy, since we're never writing to the management
80-
// client from the indexer service.
81-
globalIndexingRule: {
82-
allocationAmount: BigNumber.from('0'),
83-
},
84-
},
85-
features: {
86-
injectDai: true,
87-
},
88-
})
58+
sequelize = await connectDatabase(__DATABASE__)
59+
60+
queryFeeModels = defineQueryFeeModels(sequelize)
61+
models = defineIndexerManagementModels(sequelize)
62+
address = '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1'
63+
contracts = await connectContracts(ethers.getDefaultProvider('rinkeby'), 4)
64+
await sequelize.sync({ force: true })
65+
indexingStatusResolver = new IndexingStatusResolver({
66+
logger: logger,
67+
statusEndpoint: 'http://localhost:8030/graphql',
68+
})
69+
networkSubgraph = await NetworkSubgraph.create({
70+
logger,
71+
endpoint: 'https://gateway.testnet.thegraph.com/network',
72+
deployment: undefined,
73+
})
8974

90-
receiptManager = new AllocationReceiptManager(
91-
sequelize,
92-
queryFeeModels,
93-
logger,
94-
toAddress(address), //update maybe
95-
)
96-
97-
const release = {
98-
version: '0.0.1',
99-
dependencies: {
100-
'@graphprotocol/common-ts': '1.8.0',
75+
client = await createIndexerManagementClient({
76+
models,
77+
address,
78+
contracts,
79+
indexingStatusResolver,
80+
networkSubgraph,
81+
logger,
82+
defaults: {
83+
// This is just a dummy, since we're never writing to the management
84+
// client from the indexer service.
85+
globalIndexingRule: {
86+
allocationAmount: BigNumber.from('0'),
10187
},
102-
}
103-
104-
// Monitor indexer allocations that we may receive traffic for
105-
const allocations = monitorEligibleAllocations({
106-
indexer: toAddress(address),
107-
logger,
108-
networkSubgraph,
109-
interval: 120_000,
110-
})
111-
const wallet = Wallet.fromMnemonic(
112-
'myth like bonus scare over problem client lizard pioneer submit female collect',
113-
)
114-
115-
// Ensure there is an attestation signer for every allocation
116-
const signers = ensureAttestationSigners({
117-
logger,
118-
allocations,
119-
wallet,
120-
chainId: 4,
121-
disputeManagerAddress: contracts.disputeManager.address,
122-
})
88+
},
89+
features: {
90+
injectDai: true,
91+
},
92+
})
12393

124-
const queryProcessor = new QueryProcessor({
125-
logger: logger.child({ component: 'QueryProcessor' }),
126-
graphNode: 'http://localhost:8000/',
127-
metrics,
128-
receiptManager,
129-
signers,
130-
})
94+
receiptManager = new AllocationReceiptManager(
95+
sequelize,
96+
queryFeeModels,
97+
logger,
98+
toAddress(address), //update maybe
99+
)
100+
101+
const release = {
102+
version: '0.0.1',
103+
dependencies: {
104+
'@graphprotocol/common-ts': '1.8.0',
105+
},
106+
}
107+
108+
// Monitor indexer allocations that we may receive traffic for
109+
const allocations = monitorEligibleAllocations({
110+
indexer: toAddress(address),
111+
logger,
112+
networkSubgraph,
113+
interval: 120_000,
114+
})
115+
const wallet = Wallet.fromMnemonic(
116+
'myth like bonus scare over problem client lizard pioneer submit female collect',
117+
)
118+
119+
// Ensure there is an attestation signer for every allocation
120+
const signers = ensureAttestationSigners({
121+
logger,
122+
allocations,
123+
wallet,
124+
chainId: 4,
125+
disputeManagerAddress: contracts.disputeManager.address,
126+
})
131127

132-
app = await createServer({
133-
logger,
134-
port: 9600,
135-
queryProcessor,
136-
graphNodeStatusEndpoint: 'http://localhost:8030/graphql',
137-
metrics,
138-
freeQueryAuthToken: '',
139-
indexerManagementClient: client,
140-
release,
141-
operatorPublicKey: wallet.publicKey,
142-
networkSubgraph,
143-
networkSubgraphAuthToken: 'superdupersecrettoken',
144-
serveNetworkSubgraph: false,
145-
})
128+
const queryProcessor = new QueryProcessor({
129+
logger: logger.child({ component: 'QueryProcessor' }),
130+
graphNode: 'http://localhost:8000/',
131+
metrics,
132+
receiptManager,
133+
signers,
146134
})
147135

148-
afterAll(async () => {
149-
await sequelize.drop({})
136+
server = await createServer({
137+
logger,
138+
port: 9600,
139+
queryProcessor,
140+
graphNodeStatusEndpoint: 'http://localhost:8030/graphql',
141+
metrics,
142+
freeQueryAuthToken: '',
143+
indexerManagementClient: client,
144+
release,
145+
operatorPublicKey: wallet.publicKey,
146+
networkSubgraph,
147+
networkSubgraphAuthToken: 'superdupersecrettoken',
148+
serveNetworkSubgraph: false,
150149
})
150+
server.on('connection', socket => {
151+
logger.debug('Connection established', { socket })
152+
sockets.push(socket)
153+
socket.on('close', () => (sockets = sockets.filter(curr => curr !== socket)))
154+
})
155+
process.on('SIGTERM', await shutdownServer)
156+
process.on('SIGINT', await shutdownServer)
157+
}
158+
159+
const shutdownServer = async () => {
160+
logger.debug('Received kill signal, shutting down gracefully')
161+
if(server) {
162+
server.close(() => {
163+
logger.debug('Closed out remaining connections')
164+
})
165+
}
166+
if(sockets.length > 0) {
167+
sockets.forEach(socket => socket.destroy())
168+
}
169+
}
170+
171+
const teardown = async () => {
172+
await shutdownServer()
173+
await sequelize.drop({})
174+
}
175+
176+
describe('Server', () => {
177+
beforeAll(setup)
178+
afterAll(teardown)
151179

152180
it('is ready to roll', done => {
153-
supertest(app).get('/').expect(200, done)
154-
//expect(response.body.message).toBe('ready to roll!')
181+
supertest(server).get('/').expect(200, done)
155182
})
156183
})

packages/indexer-service/src/server/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import { createCostServer } from './cost'
2222
import { createOperatorServer } from './operator'
2323
import rateLimit from 'express-rate-limit'
24+
import http from 'http'
2425

2526
export interface ServerOptions {
2627
logger: Logger
@@ -362,7 +363,7 @@ export const createServer = async ({
362363
networkSubgraph,
363364
networkSubgraphAuthToken,
364365
serveNetworkSubgraph,
365-
}: ServerOptions): Promise<express.Express> => {
366+
}: ServerOptions): Promise<http.Server> => {
366367
const app = await createApp({
367368
logger,
368369
queryProcessor,
@@ -377,9 +378,7 @@ export const createServer = async ({
377378
serveNetworkSubgraph,
378379
})
379380

380-
app.listen(port, () => {
381+
return app.listen(port, () => {
381382
logger.debug(`Listening on port ${port}`)
382383
})
383-
384-
return app
385384
}

0 commit comments

Comments
 (0)