Skip to content

Commit 34ef522

Browse files
committed
chore: force executing DIPs actions in manual and oversight mode
1 parent 99d1a15 commit 34ef522

File tree

3 files changed

+87
-43
lines changed

3 files changed

+87
-43
lines changed

docs/action-queue.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ The action execution worker will only grab items from the action queue to execut
88

99
## Allocation management modes:
1010
- `auto`: The indexer-agent will act similarly to the legacy paradigm. When it identifies allocation actions it will add them to the queue with ActionStatus = `approved`; the execution worker process will pick up the approved actions within 30 seconds and execute them.
11-
- `manual`: The indexer-agent will not add any items to the action queue in this mode. It will spin up an indexer-management server which can be interacted with manually or integrated with 3rd party tools to add actions to the action queue and execute them.
12-
- `oversight`: The indexer-agent will add run its reconciliation loop to make allocation decisions and when actions are identified it will queue them. These actions will then require approval before they can be executed.
11+
- `manual`: The indexer-agent will not add any items to the action queue in this mode. It will spin up an indexer-management server which can be interacted with manually or integrated with 3rd party tools to add actions to the action queue and execute them. An exception to this is indexing agreements (DIPs), for which actions will be queued and executed even in this mode.
12+
- `oversight`: The indexer-agent will add run its reconciliation loop to make allocation decisions and when actions are identified it will queue them. These actions will then require approval before they can be executed. An exception to this is indexing agreements (DIPs), for which actions will be queued as approved and executed even in this mode.
1313

1414
## Actions CLI
1515
The indexer-cli provides an `actions` module for manually working with the action queue. It uses the #Graphql API hosted by the indexer management server to interact with the actions queue.

packages/indexer-agent/src/agent.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,7 @@ export class Agent {
852852
maxAllocationEpochs: number,
853853
network: Network,
854854
operator: Operator,
855+
forceAction: boolean = false,
855856
): Promise<void> {
856857
const logger = this.logger.child({
857858
deployment: deploymentAllocationDecision.deployment.ipfsHash,
@@ -873,6 +874,7 @@ export class Agent {
873874
logger,
874875
deploymentAllocationDecision,
875876
activeDeploymentAllocations,
877+
forceAction,
876878
)
877879
case true: {
878880
// If no active allocations and subgraph health passes safety check, create one
@@ -909,6 +911,7 @@ export class Agent {
909911
logger,
910912
deploymentAllocationDecision,
911913
mostRecentlyClosedAllocation,
914+
forceAction,
912915
)
913916
}
914917
} else if (activeDeploymentAllocations.length > 0) {
@@ -917,6 +920,7 @@ export class Agent {
917920
logger,
918921
deploymentAllocationDecision,
919922
activeDeploymentAllocations,
923+
forceAction,
920924
)
921925
} else {
922926
// Refresh any expiring allocations
@@ -933,6 +937,7 @@ export class Agent {
933937
logger,
934938
deploymentAllocationDecision,
935939
expiringAllocations,
940+
forceAction,
936941
)
937942
}
938943
}
@@ -952,21 +957,37 @@ export class Agent {
952957
// --------------------------------------------------------------------------------
953958
const { network, operator } = this.networkAndOperator
954959
let validatedAllocationDecisions = [...allocationDecisions]
960+
let dipsDeployments: SubgraphDeploymentID[] = []
961+
if (network.specification.indexerOptions.enableDips) {
962+
if (!operator.dipsManager) {
963+
throw new Error('DipsManager is not available')
964+
}
965+
dipsDeployments = await operator.dipsManager.getActiveDipsDeployments()
966+
}
955967

956968
if (
957969
network.specification.indexerOptions.allocationManagementMode ===
958970
AllocationManagementMode.MANUAL
959971
) {
960-
this.logger.trace(
961-
`Skipping allocation reconciliation since AllocationManagementMode = 'manual'`,
962-
{
963-
protocolNetwork: network.specification.networkIdentifier,
964-
targetDeployments: allocationDecisions
965-
.filter(decision => decision.toAllocate)
966-
.map(decision => decision.deployment.ipfsHash),
967-
},
968-
)
969-
validatedAllocationDecisions = [] as AllocationDecision[]
972+
if (network.specification.indexerOptions.enableDips) {
973+
this.logger.warn(
974+
`Allocation management is manual, but DIPs is enabled. Reconciling DIPs allocations anyways.`,
975+
)
976+
validatedAllocationDecisions = validatedAllocationDecisions.filter(
977+
decision => dipsDeployments.includes(decision.deployment),
978+
)
979+
} else {
980+
this.logger.trace(
981+
`Skipping allocation reconciliation since AllocationManagementMode = 'manual'`,
982+
{
983+
protocolNetwork: network.specification.networkIdentifier,
984+
targetDeployments: allocationDecisions
985+
.filter(decision => decision.toAllocate)
986+
.map(decision => decision.deployment.ipfsHash),
987+
},
988+
)
989+
validatedAllocationDecisions = [] as AllocationDecision[]
990+
}
970991
} else {
971992
const networkSubgraphDeployment = network.networkSubgraph.deployment
972993
if (
@@ -1028,6 +1049,7 @@ export class Agent {
10281049
maxAllocationEpochs,
10291050
network,
10301051
operator,
1052+
dipsDeployments.includes(decision.deployment), // Force actions if this is a DIPs deployment
10311053
),
10321054
)
10331055
return

packages/indexer-common/src/operator.ts

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,26 @@ export class Operator {
263263
return result.data.actions
264264
}
265265

266-
async queueAction(action: ActionItem): Promise<Action[]> {
266+
async queueAction(action: ActionItem, forceAction: boolean = false): Promise<Action[]> {
267267
let status = ActionStatus.QUEUED
268268
switch (this.specification.indexerOptions.allocationManagementMode) {
269269
case AllocationManagementMode.MANUAL:
270-
throw Error(`Cannot queue actions when AllocationManagementMode = 'MANUAL'`)
270+
if (forceAction) {
271+
status = ActionStatus.APPROVED
272+
} else {
273+
throw Error(`Cannot queue actions when AllocationManagementMode = 'MANUAL'`)
274+
}
275+
break
271276
case AllocationManagementMode.AUTO:
272277
status = ActionStatus.APPROVED
273278
break
274279
case AllocationManagementMode.OVERSIGHT:
275-
status = ActionStatus.QUEUED
280+
if (forceAction) {
281+
status = ActionStatus.APPROVED
282+
} else {
283+
status = ActionStatus.QUEUED
284+
}
285+
break
276286
}
277287

278288
const actionInput = {
@@ -341,6 +351,7 @@ export class Operator {
341351
logger: Logger,
342352
deploymentAllocationDecision: AllocationDecision,
343353
mostRecentlyClosedAllocation: Allocation | undefined,
354+
forceAction: boolean = false,
344355
): Promise<void> {
345356
const desiredAllocationAmount = deploymentAllocationDecision.ruleMatch.rule
346357
?.allocationAmount
@@ -369,15 +380,18 @@ export class Operator {
369380
}
370381

371382
// Send AllocateAction to the queue
372-
await this.queueAction({
373-
params: {
374-
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
375-
amount: formatGRT(desiredAllocationAmount),
383+
await this.queueAction(
384+
{
385+
params: {
386+
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
387+
amount: formatGRT(desiredAllocationAmount),
388+
},
389+
type: ActionType.ALLOCATE,
390+
reason: deploymentAllocationDecision.reasonString(),
391+
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
376392
},
377-
type: ActionType.ALLOCATE,
378-
reason: deploymentAllocationDecision.reasonString(),
379-
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
380-
})
393+
forceAction,
394+
)
381395

382396
return
383397
}
@@ -386,6 +400,7 @@ export class Operator {
386400
logger: Logger,
387401
deploymentAllocationDecision: AllocationDecision,
388402
activeDeploymentAllocations: Allocation[],
403+
forceAction: boolean = false,
389404
): Promise<void> {
390405
const activeDeploymentAllocationsEligibleForClose = activeDeploymentAllocations.map(
391406
(allocation) => allocation.id,
@@ -405,17 +420,20 @@ export class Operator {
405420
activeDeploymentAllocationsEligibleForClose,
406421
async (allocation) => {
407422
// Send unallocate action to the queue
408-
await this.queueAction({
409-
params: {
410-
allocationID: allocation,
411-
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
412-
poi: undefined,
413-
force: false,
414-
},
415-
type: ActionType.UNALLOCATE,
416-
reason: deploymentAllocationDecision.reasonString(),
417-
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
418-
} as ActionItem)
423+
await this.queueAction(
424+
{
425+
params: {
426+
allocationID: allocation,
427+
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
428+
poi: undefined,
429+
force: false,
430+
},
431+
type: ActionType.UNALLOCATE,
432+
reason: deploymentAllocationDecision.reasonString(),
433+
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
434+
} as ActionItem,
435+
forceAction,
436+
)
419437
},
420438
{ concurrency: 1 },
421439
)
@@ -426,6 +444,7 @@ export class Operator {
426444
logger: Logger,
427445
deploymentAllocationDecision: AllocationDecision,
428446
expiredAllocations: Allocation[],
447+
forceAction: boolean = false,
429448
): Promise<void> {
430449
if (deploymentAllocationDecision.ruleMatch.rule?.autoRenewal) {
431450
logger.info(`Reallocating expired allocations`, {
@@ -442,16 +461,19 @@ export class Operator {
442461
await pMap(
443462
expiredAllocations,
444463
async (allocation) => {
445-
await this.queueAction({
446-
params: {
447-
allocationID: allocation.id,
448-
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
449-
amount: formatGRT(desiredAllocationAmount),
464+
await this.queueAction(
465+
{
466+
params: {
467+
allocationID: allocation.id,
468+
deploymentID: deploymentAllocationDecision.deployment.ipfsHash,
469+
amount: formatGRT(desiredAllocationAmount),
470+
},
471+
type: ActionType.REALLOCATE,
472+
reason: `${deploymentAllocationDecision.reasonString()}:allocationExpiring`, // Need to update to include 'ExpiringSoon'
473+
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
450474
},
451-
type: ActionType.REALLOCATE,
452-
reason: `${deploymentAllocationDecision.reasonString()}:allocationExpiring`, // Need to update to include 'ExpiringSoon'
453-
protocolNetwork: deploymentAllocationDecision.protocolNetwork,
454-
})
475+
forceAction,
476+
)
455477
},
456478
{
457479
stopOnError: false,

0 commit comments

Comments
 (0)