Commit eb1c9b30 authored by refcell's avatar refcell Committed by GitHub

feat(op-challenger): Parallelize Agent Actions (#9804)

* feat(op-challenger): Place agent actions behind a synced wait group

* op-challenger: Split out individual action into a separate method to reduce nesting.

---------
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
parent 47a1478a
......@@ -67,49 +67,56 @@ func (a *Agent) Act(ctx context.Context) error {
if a.tryResolve(ctx) {
return nil
}
game, err := a.newGameFromContracts(ctx)
if err != nil {
return fmt.Errorf("create game from contracts: %w", err)
}
// Calculate the actions to take
actions, err := a.solver.CalculateNextActions(ctx, game)
if err != nil {
a.log.Error("Failed to calculate all required moves", "err", err)
}
// Perform the actions
var wg sync.WaitGroup
wg.Add(len(actions))
for _, action := range actions {
actionLog := a.log.New("action", action.Type, "is_attack", action.IsAttack, "parent", action.ParentIdx)
if action.Type == types.ActionTypeStep {
containsOracleData := action.OracleData != nil
isLocal := containsOracleData && action.OracleData.IsLocal
actionLog = actionLog.New(
"prestate", common.Bytes2Hex(action.PreState),
"proof", common.Bytes2Hex(action.ProofData),
"containsOracleData", containsOracleData,
"isLocalPreimage", isLocal,
)
if action.OracleData != nil {
actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey))
}
} else {
actionLog = actionLog.New("value", action.Value)
}
go a.performAction(ctx, &wg, action)
}
wg.Wait()
return nil
}
switch action.Type {
case types.ActionTypeMove:
a.metrics.RecordGameMove()
case types.ActionTypeStep:
a.metrics.RecordGameStep()
}
actionLog.Info("Performing action")
err := a.responder.PerformAction(ctx, action)
if err != nil {
actionLog.Error("Action failed", "err", err)
func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action types.Action) {
defer wg.Done()
actionLog := a.log.New("action", action.Type, "is_attack", action.IsAttack, "parent", action.ParentIdx)
if action.Type == types.ActionTypeStep {
containsOracleData := action.OracleData != nil
isLocal := containsOracleData && action.OracleData.IsLocal
actionLog = actionLog.New(
"prestate", common.Bytes2Hex(action.PreState),
"proof", common.Bytes2Hex(action.ProofData),
"containsOracleData", containsOracleData,
"isLocalPreimage", isLocal,
)
if action.OracleData != nil {
actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey))
}
} else {
actionLog = actionLog.New("value", action.Value)
}
switch action.Type {
case types.ActionTypeMove:
a.metrics.RecordGameMove()
case types.ActionTypeStep:
a.metrics.RecordGameStep()
}
actionLog.Info("Performing action")
err := a.responder.PerformAction(ctx, action)
if err != nil {
actionLog.Error("Action failed", "err", err)
}
return nil
}
// tryResolve resolves the game if it is in a winning state
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment