Skip to content

Commit fb8271a

Browse files
chriswesselshopeyen
authored andcommitted
indexer-agent, indexer-cli, indexer-common: add allocation lifetimes
1 parent 7015498 commit fb8271a

22 files changed

+213
-46
lines changed

packages/indexer-agent/src/__tests__/indexer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ let sequelize: Sequelize
105105
let models: IndexerManagementModels
106106
let wallet: Wallet
107107
let address: string
108+
let maxLifetime: number
108109
let contracts: NetworkContracts
109110
let logger: Logger
110111
let indexerManagementClient: IndexerManagementClient
@@ -120,6 +121,7 @@ const setup = async () => {
120121
sequelize = await connectDatabase(__DATABASE__)
121122
models = defineIndexerManagementModels(sequelize)
122123
address = '0x3C17A4c7cD8929B83e4705e04020fA2B1bca2E55'
124+
maxLifetime = 1
123125
contracts = await connectContracts(wallet, 4)
124126
await sequelize.sync({ force: true })
125127

@@ -162,6 +164,7 @@ const setup = async () => {
162164
['test'],
163165
parseGRT('1000'),
164166
address,
167+
maxLifetime,
165168
)
166169
}
167170

packages/indexer-agent/src/agent.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,11 @@ class Agent {
202202
)
203203

204204
const maxAllocationEpochs = timer(600_000).tryMap(
205-
() => this.network.contracts.staking.maxAllocationEpochs(),
205+
() =>
206+
// can i pass these 2 numbers into rule creation?
207+
this.indexer.maxLifetime
208+
? this.indexer.maxLifetime
209+
: this.network.contracts.staking.maxAllocationEpochs(),
206210
{
207211
onError: err =>
208212
this.logger.warn(`Failed to fetch max allocation epochs`, { err }),
@@ -697,7 +701,6 @@ class Agent {
697701

698702
this.logger.info(`Reconcile allocations`, {
699703
currentEpoch,
700-
maxAllocationEpochs,
701704
allocationLifetime,
702705
targetAllocations: targetAllocations.map(
703706
deployment => deployment.display,
@@ -715,7 +718,7 @@ class Agent {
715718
...activeAllocations.map(allocation => allocation.subgraphDeployment.id),
716719
])
717720

718-
// Ensure the network subgraph is never allocated towards
721+
// Ensure the network subgraph is never allocated towards unless explicitly allowed
719722
if (
720723
!this.allocateOnNetworkSubgraph &&
721724
this.networkSubgraph.deployment?.id.bytes32
@@ -757,7 +760,7 @@ class Agent {
757760

758761
currentEpoch,
759762
currentEpochStartBlock,
760-
maxAllocationEpochs,
763+
allocationLifetime,
761764
)
762765
},
763766
{ concurrency: 1 },
@@ -782,6 +785,9 @@ class Agent {
782785
? BigNumber.from(rule.allocationAmount)
783786
: this.indexer.defaultAllocationAmount
784787
const desiredNumberOfAllocations = 1
788+
const desiredAllocationLifetime = rule?.allocationLifetime
789+
? Math.max(1, rule.allocationLifetime)
790+
: maxAllocationEpochs
785791
const activeAllocationAmount = activeAllocations.reduce(
786792
(sum, allocation) => sum.add(allocation.allocatedTokens),
787793
BigNumber.from('0'),
@@ -795,6 +801,7 @@ class Agent {
795801
`Reconcile deployment allocations for deployment '${deployment.ipfsHash}'`,
796802
{
797803
desiredAllocationAmount: formatGRT(desiredAllocationAmount),
804+
desiredAllocationLifetime,
798805

799806
totalActiveAllocationAmount: formatGRT(activeAllocationAmount),
800807

@@ -881,11 +888,10 @@ class Agent {
881888
)
882889
}
883890

884-
const lifetime = Math.max(1, maxAllocationEpochs - 1)
885-
886891
// For allocations that have expired, let's reallocate in one transaction (closeAndAllocate)
887892
let expiredAllocations = activeAllocations.filter(
888-
allocation => epoch >= allocation.createdAtEpoch + lifetime,
893+
allocation =>
894+
epoch >= allocation.createdAtEpoch + desiredAllocationLifetime,
889895
)
890896
// The allocations come from the network subgraph; due to short indexing
891897
// latencies, this data may be slightly outdated. Cross-check with the

packages/indexer-agent/src/commands/start.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ export default {
308308
default: false,
309309
group: 'Disputes',
310310
})
311+
.option('max-lifetime', {
312+
description:
313+
'Maximum epoches agent keep each allocation open (default 28) ',
314+
type: 'number',
315+
coerce: arg => Math.max(arg, 1),
316+
})
311317
.check(argv => {
312318
if (
313319
!argv['network-subgraph-endpoint'] &&
@@ -420,6 +426,12 @@ export default {
420426
)
421427
}
422428

429+
if (argv.maxLifetime < 7) {
430+
logger.warn(
431+
`Maximum lifetime for allocations is less than a week. This might be expensive to maintain`,
432+
)
433+
}
434+
423435
process.on('unhandledRejection', err => {
424436
logger.warn(`Unhandled promise rejection`, {
425437
err: indexerError(IndexerErrorCode.IE035, err),
@@ -661,6 +673,7 @@ export default {
661673
argv.indexNodeIds,
662674
parseGRT(argv.defaultAllocationAmount),
663675
indexerAddress,
676+
argv.maxLifetime,
664677
)
665678
const networkSubgraphDeployment = argv.networkSubgraphDeployment
666679
? new SubgraphDeploymentID(argv.networkSubgraphDeployment)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Logger } from '@graphprotocol/common-ts'
2+
import { DataTypes, QueryInterface } from 'sequelize'
3+
4+
interface MigrationContext {
5+
queryInterface: QueryInterface
6+
logger: Logger
7+
}
8+
9+
interface Context {
10+
context: MigrationContext
11+
}
12+
13+
export async function up({ context }: Context): Promise<void> {
14+
const { queryInterface, logger } = context
15+
16+
logger.debug(`Checking if indexing rules table exists`)
17+
const tables = await queryInterface.showAllTables()
18+
if (!tables.includes('IndexingRules')) {
19+
logger.info(`Indexing rules table does not exist, migration not necessary`)
20+
return
21+
}
22+
23+
logger.debug(`Checking if 'IndexingRules' table needs to be migrated`)
24+
const table = await queryInterface.describeTable('IndexingRules')
25+
const allocationLifetime = table.allocationLifetime
26+
if (allocationLifetime) {
27+
logger.info(
28+
`'allocationLifetime' columns already exist, migration not necessary`,
29+
)
30+
return
31+
}
32+
33+
logger.info(`Add 'allocationLifetime' column to 'IndexingRules' table`)
34+
await queryInterface.addColumn('IndexingRules', 'allocationLifetime', {
35+
type: DataTypes.INTEGER,
36+
allowNull: false,
37+
defaultValue: 27,
38+
})
39+
}
40+
41+
export async function down({ context }: Context): Promise<void> {
42+
const { queryInterface, logger } = context
43+
44+
return await queryInterface.sequelize.transaction({}, async transaction => {
45+
const tables = await queryInterface.showAllTables()
46+
47+
if (tables.includes('IndexingRules')) {
48+
logger.info(`Remove 'allocationLifetime' column`)
49+
await context.queryInterface.removeColumn(
50+
'IndexingRules',
51+
'allocationLifetime',
52+
{ transaction },
53+
)
54+
55+
logger.info(`Remove 'int_IndexingRules_allocationLifetime' custom type`)
56+
await queryInterface.sequelize.query(
57+
`delete from pg_type where typname = 'int_IndexingRules_allocationLifetime'`,
58+
)
59+
}
60+
})
61+
}

packages/indexer-agent/src/indexer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export class Indexer {
6262
indexNodeIDs: string[]
6363
defaultAllocationAmount: BigNumber
6464
indexerAddress: string
65+
maxLifetime: number | null | undefined
6566

6667
constructor(
6768
logger: Logger,
@@ -71,11 +72,13 @@ export class Indexer {
7172
indexNodeIDs: string[],
7273
defaultAllocationAmount: BigNumber,
7374
indexerAddress: string,
75+
maxLifetime: number | null | undefined,
7476
) {
7577
this.indexerManagement = indexerManagement
7678
this.statusResolver = statusResolver
7779
this.logger = logger
7880
this.indexerAddress = indexerAddress
81+
this.maxLifetime = maxLifetime
7982

8083
if (adminEndpoint.startsWith('https')) {
8184
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -219,6 +222,7 @@ export class Indexer {
219222
identifier
220223
identifierType
221224
allocationAmount
225+
allocationLifetime
222226
parallelAllocations
223227
maxAllocationPercentage
224228
minSignal
@@ -292,6 +296,7 @@ export class Indexer {
292296
identifier
293297
identifierType
294298
allocationAmount
299+
allocationLifetime
295300
parallelAllocations
296301
maxAllocationPercentage
297302
minSignal

packages/indexer-cli/src/__tests__/indexer/rules.test.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ describe('Indexer rules tests', () => {
267267
},
268268
)
269269
cliTest(
270-
'Indexer rules set subgraph id - success - offchain',
270+
'Indexer rules set subgraph options - success',
271271
[
272272
'indexer',
273273
'rules',
@@ -277,6 +277,8 @@ describe('Indexer rules tests', () => {
277277
'1000',
278278
'decisionBasis',
279279
'offchain',
280+
'allocationLifetime',
281+
'12',
280282
],
281283
'references/indexer-rule-subgraph-offchain',
282284
{
@@ -296,16 +298,18 @@ describe('Indexer rules tests', () => {
296298
},
297299
)
298300
cliTest(
299-
'Indexer rules set deployment id - success - offchain',
301+
'Indexer rules set deployment lifetime - success',
300302
[
301303
'indexer',
302304
'rules',
303305
'set',
304306
'QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK',
305307
'decisionBasis',
306308
'offchain',
309+
'allocationLifetime',
310+
'21',
307311
],
308-
'references/indexer-rule-deployment-offchain',
312+
'references/indexer-rule-deployment-lifetime',
309313
{
310314
expectedExitCode: 0,
311315
cwd: baseDir,
@@ -384,6 +388,16 @@ describe('Indexer rules tests', () => {
384388
timeout: 10000,
385389
},
386390
)
391+
cliTest(
392+
'Indexer rules get subgraph - success - options',
393+
['indexer', 'rules', 'get', '0x0000000000000000000000000000000000000000-2'],
394+
'references/indexer-rule-subgraph-options',
395+
{
396+
expectedExitCode: 0,
397+
cwd: baseDir,
398+
timeout: 10000,
399+
},
400+
)
387401
cliTest(
388402
'Indexer rules get global - success',
389403
['indexer', 'rules', 'get', 'global'],
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
┌────────────────────────────────────────────────┬────────────────┬──────────────────┬─────────────────────┬─────────────────────────┬───────────┬───────────┬──────────┬─────────────────────┬────────┬───────────────┐
2-
│ identifier │ identifierType │ allocationAmount │ parallelAllocations │ maxAllocationPercentage │ minSignal │ maxSignal │ minStake │ minAverageQueryFees │ custom │ decisionBasis │
3-
├────────────────────────────────────────────────┼────────────────┼──────────────────┼─────────────────────┼─────────────────────────┼───────────┼───────────┼──────────┼─────────────────────┼────────┼───────────────┤
4-
│ QmZZtzZkfzCWMNrajxBf22q7BC9HzoT5iJUK3S8qA6zNZr │ deployment │ null │ null │ null │ null │ null │ null │ null │ null │ always │
5-
└────────────────────────────────────────────────┴────────────────┴──────────────────┴─────────────────────┴─────────────────────────┴───────────┴───────────┴──────────┴─────────────────────┴────────┴───────────────┘
1+
┌────────────────────────────────────────────────┬────────────────┬──────────────────┬───────────────────────┬─────────────────────┬─────────────────────────┬───────────┬───────────┬──────────┬─────────────────────┬────────┬───────────────┐
2+
│ identifier │ identifierType │ allocationAmount │ allocationLifetime │ parallelAllocations │ maxAllocationPercentage │ minSignal │ maxSignal │ minStake │ minAverageQueryFees │ custom │ decisionBasis │
3+
├────────────────────────────────────────────────┼────────────────┼──────────────────┼───────────────────────┼─────────────────────┼─────────────────────────┼───────────┼───────────┼──────────┼─────────────────────┼────────┼───────────────┤
4+
│ QmZZtzZkfzCWMNrajxBf22q7BC9HzoT5iJUK3S8qA6zNZr │ deployment │ null │ null │ null │ null │ null │ null │ null │ null │ null │ always │
5+
└────────────────────────────────────────────────┴────────────────┴──────────────────┴───────────────────────┴─────────────────────┴─────────────────────────┴───────────┴───────────┴──────────┴─────────────────────┴────────┴───────────────┘
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
┌────────────────────────────────────────────────┬────────────────┬──────────────────┬───────────────────────┬─────────────────────┬─────────────────────────┬───────────┬───────────┬──────────┬─────────────────────┬────────┬───────────────┐
2+
│ identifier │ identifierType │ allocationAmount │ allocationLifetime │ parallelAllocations │ maxAllocationPercentage │ minSignal │ maxSignal │ minStake │ minAverageQueryFees │ custom │ decisionBasis │
3+
├────────────────────────────────────────────────┼────────────────┼──────────────────┼───────────────────────┼─────────────────────┼─────────────────────────┼───────────┼───────────┼──────────┼─────────────────────┼────────┼───────────────┤
4+
│ QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK │ deployment │ null │ 21 │ null │ null │ null │ null │ null │ null │ null │ offchain │
5+
└────────────────────────────────────────────────┴────────────────┴──────────────────┴───────────────────────┴─────────────────────┴─────────────────────────┴───────────┴───────────┴──────────┴─────────────────────┴────────┴───────────────┘

0 commit comments

Comments
 (0)