Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op-supervisor: Add Routine to run Maintenence #11552

Merged
merged 1 commit into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions op-supervisor/supervisor/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,14 @@ func (su *SupervisorBackend) Start(ctx context.Context) error {
if !su.started.CompareAndSwap(false, true) {
return errors.New("already started")
}
// start chain monitors
for _, monitor := range su.chainMonitors {
if err := monitor.Start(); err != nil {
return fmt.Errorf("failed to start chain monitor: %w", err)
}
}
// start db maintenance loop
su.db.StartCrossHeadMaintenance(ctx)
return nil
}

Expand Down
34 changes: 33 additions & 1 deletion op-supervisor/supervisor/backend/db/db.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package db

import (
"context"
"errors"
"fmt"
"io"
"time"

"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs"
backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
"github.com/ethereum/go-ethereum/log"
)

var (
Expand Down Expand Up @@ -59,6 +62,35 @@ func (db *ChainsDB) Resume() error {
return nil
}

// StartCrossHeadMaintenance starts a background process that maintains the cross-heads of the chains
// for now it does not prevent multiple instances of this process from running
func (db *ChainsDB) StartCrossHeadMaintenance(ctx context.Context) {
go func() {
// create three safety checkers, one for each safety level
unsafeChecker := NewSafetyChecker(Unsafe, *db)
safeChecker := NewSafetyChecker(Safe, *db)
finalizedChecker := NewSafetyChecker(Finalized, *db)
// run the maintenance loop every 10 seconds for now
ticker := time.NewTicker(time.Second * 10)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
for _, checker := range []SafetyChecker{
unsafeChecker,
safeChecker,
finalizedChecker} {
if err := db.UpdateCrossHeads(checker); err != nil {
log.Error("failed to update cross-heads", "err", err, "safety", checker.Name())
// we should consider exiting if an error is encountered, as the path forward is unclear
}
}
}
}
}()
}

// UpdateCrossSafeHeads updates the cross-heads of all chains
// this is an example of how to use the SafetyChecker to update the cross-heads
func (db *ChainsDB) UpdateCrossSafeHeads() error {
Expand Down Expand Up @@ -117,7 +149,7 @@ func (db *ChainsDB) UpdateCrossHeadsForChain(chainID types.ChainID, checker Safe
return nil
}

// UpdateCrossSafeHeads updates the cross-heads of all chains
// UpdateCrossHeads updates the cross-heads of all chains
// based on the provided SafetyChecker. The SafetyChecker is used to determine
// the safety of each log entry in the database, and the cross-head associated with it.
func (db *ChainsDB) UpdateCrossHeads(checker SafetyChecker) error {
Expand Down
4 changes: 4 additions & 0 deletions op-supervisor/supervisor/backend/db/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ func (s *stubChecker) LocalHeadForChain(chainID types.ChainID) entrydb.EntryIdx
return s.localHeadForChain
}

func (s *stubChecker) Name() string {
return "stubChecker"
}

func (s *stubChecker) CrossHeadForChain(chainID types.ChainID) entrydb.EntryIdx {
return s.crossHeadForChain
}
Expand Down
14 changes: 14 additions & 0 deletions op-supervisor/supervisor/backend/db/safety_checkers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type SafetyChecker interface {
CrossHeadForChain(chainID types.ChainID) entrydb.EntryIdx
Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool
Update(chain types.ChainID, index entrydb.EntryIdx) heads.OperationFn
Name() string
}

// unsafeChecker is a SafetyChecker that uses the unsafe head as the view into the database
Expand Down Expand Up @@ -57,6 +58,19 @@ func NewSafetyChecker(t string, chainsDB ChainsDB) SafetyChecker {
}
}

// Name returns the safety checker type, using the same strings as the constants used in construction
func (c *unsafeChecker) Name() string {
return Unsafe
}

func (c *safeChecker) Name() string {
return Safe
}

func (c *finalizedChecker) Name() string {
return Finalized
}

// LocalHeadForChain returns the local head for the given chain
// based on the type of SafetyChecker
func (c *unsafeChecker) LocalHeadForChain(chainID types.ChainID) entrydb.EntryIdx {
Expand Down