Commit aec0e03f authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into dependabot/npm_and_yarn/markdownlint-0.30.0

parents 42a0d0af 0677bc6c
docker-compose.dev.yml docker-compose.dev.yml
.env .env
indexer /indexer
package api package api
import ( import (
"context"
"fmt" "fmt"
"net/http" "net/http"
"github.com/ethereum-optimism/optimism/indexer/api/routes" "github.com/ethereum-optimism/optimism/indexer/api/routes"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-service/httputil"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
) )
...@@ -13,25 +15,29 @@ import ( ...@@ -13,25 +15,29 @@ import (
const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$`
type Api struct { type Api struct {
log log.Logger
Router *chi.Mux Router *chi.Mux
} }
func NewApi(bv database.BridgeTransfersView, logger log.Logger) *Api { func NewApi(logger log.Logger, bv database.BridgeTransfersView) *Api {
logger.Info("Initializing API...")
r := chi.NewRouter() r := chi.NewRouter()
h := routes.NewRoutes(logger, bv, r) h := routes.NewRoutes(logger, bv, r)
api := &Api{Router: r}
r.Get("/healthz", h.HealthzHandler) r.Get("/healthz", h.HealthzHandler)
r.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) r.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler)
r.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) r.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler)
return &Api{log: logger, Router: r}
return api
} }
func (a *Api) Listen(port string) error { func (a *Api) Listen(ctx context.Context, port int) error {
return http.ListenAndServe(port, a.Router) a.log.Info("starting api server", "port", port)
server := http.Server{Addr: fmt.Sprintf(":%d", port), Handler: a.Router}
err := httputil.ListenAndServeContext(ctx, &server)
if err != nil {
a.log.Error("api server shutdown", "err", err)
} else {
a.log.Info("api server shutdown")
}
return err
} }
...@@ -77,7 +77,7 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common. ...@@ -77,7 +77,7 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.
} }
func TestHealthz(t *testing.T) { func TestHealthz(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo) logger := testlog.Logger(t, log.LvlInfo)
api := NewApi(&MockBridgeTransfersView{}, logger) api := NewApi(logger, &MockBridgeTransfersView{})
request, err := http.NewRequest("GET", "/healthz", nil) request, err := http.NewRequest("GET", "/healthz", nil)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -89,7 +89,7 @@ func TestHealthz(t *testing.T) { ...@@ -89,7 +89,7 @@ func TestHealthz(t *testing.T) {
func TestL1BridgeDepositsHandler(t *testing.T) { func TestL1BridgeDepositsHandler(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo) logger := testlog.Logger(t, log.LvlInfo)
api := NewApi(&MockBridgeTransfersView{}, logger) api := NewApi(logger, &MockBridgeTransfersView{})
request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/deposits/%s", mockAddress), nil) request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/deposits/%s", mockAddress), nil)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -101,7 +101,7 @@ func TestL1BridgeDepositsHandler(t *testing.T) { ...@@ -101,7 +101,7 @@ func TestL1BridgeDepositsHandler(t *testing.T) {
func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo) logger := testlog.Logger(t, log.LvlInfo)
api := NewApi(&MockBridgeTransfersView{}, logger) api := NewApi(logger, &MockBridgeTransfersView{})
request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/withdrawals/%s", mockAddress), nil) request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/withdrawals/%s", mockAddress), nil)
assert.Nil(t, err) assert.Nil(t, err)
......
package cli package main
import ( import (
"context" "context"
"fmt"
"strconv"
"github.com/ethereum-optimism/optimism/indexer" "github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer/api" "github.com/ethereum-optimism/optimism/indexer/api"
...@@ -16,26 +14,25 @@ import ( ...@@ -16,26 +14,25 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
type Cli struct { var (
GitVersion string ConfigFlag = &cli.StringFlag{
GitCommit string Name: "config",
GitDate string Value: "./indexer.toml",
app *cli.App Aliases: []string{"c"},
Flags []cli.Flag Usage: "path to config file",
} EnvVars: []string{"INDEXER_CONFIG"},
}
)
func runIndexer(ctx *cli.Context) error { func runIndexer(ctx *cli.Context) error {
logger := log.NewLogger(log.ReadCLIConfig(ctx)) logger := log.NewLogger(log.ReadCLIConfig(ctx))
cfg, err := config.LoadConfig(logger, ctx.String(ConfigFlag.Name))
configPath := ctx.String(ConfigFlag.Name)
cfg, err := config.LoadConfig(logger, configPath)
if err != nil { if err != nil {
logger.Error("failed to load config", "err", err) logger.Error("failed to load config", "err", err)
return err return err
} }
db, err := database.NewDB(cfg.DB) db, err := database.NewDB(cfg.DB)
if err != nil { if err != nil {
return err return err
} }
...@@ -48,6 +45,7 @@ func runIndexer(ctx *cli.Context) error { ...@@ -48,6 +45,7 @@ func runIndexer(ctx *cli.Context) error {
indexerCtx, indexerCancel := context.WithCancel(context.Background()) indexerCtx, indexerCancel := context.WithCancel(context.Background())
go func() { go func() {
opio.BlockOnInterrupts() opio.BlockOnInterrupts()
logger.Error("caught interrupt, shutting down...")
indexerCancel() indexerCancel()
}() }()
...@@ -56,47 +54,35 @@ func runIndexer(ctx *cli.Context) error { ...@@ -56,47 +54,35 @@ func runIndexer(ctx *cli.Context) error {
func runApi(ctx *cli.Context) error { func runApi(ctx *cli.Context) error {
logger := log.NewLogger(log.ReadCLIConfig(ctx)) logger := log.NewLogger(log.ReadCLIConfig(ctx))
cfg, err := config.LoadConfig(logger, ctx.String(ConfigFlag.Name))
configPath := ctx.String(ConfigFlag.Name)
cfg, err := config.LoadConfig(logger, configPath)
if err != nil { if err != nil {
logger.Error("failed to load config", "err", err) logger.Error("failed to load config", "err", err)
return err return err
} }
db, err := database.NewDB(cfg.DB) db, err := database.NewDB(cfg.DB)
if err != nil { if err != nil {
logger.Crit("Failed to connect to database", "err", err) logger.Crit("Failed to connect to database", "err", err)
} }
server := api.NewApi(db.BridgeTransfers, logger) apiCtx, apiCancel := context.WithCancel(context.Background())
api := api.NewApi(logger, db.BridgeTransfers)
return server.Listen(strconv.Itoa(cfg.API.Port)) go func() {
} opio.BlockOnInterrupts()
logger.Error("caught interrupt, shutting down...")
var ( apiCancel()
ConfigFlag = &cli.StringFlag{ }()
Name: "config",
Value: "./indexer.toml",
Aliases: []string{"c"},
Usage: "path to config file",
EnvVars: []string{"INDEXER_CONFIG"},
}
)
// make a instance method on Cli called Run that runs cli return api.Listen(apiCtx, cfg.API.Port)
// and returns an error
func (c *Cli) Run(args []string) error {
return c.app.Run(args)
} }
func NewCli(GitVersion string, GitCommit string, GitDate string) *Cli { func newCli(GitCommit string, GitDate string) *cli.App {
flags := []cli.Flag{ConfigFlag} flags := []cli.Flag{ConfigFlag}
flags = append(flags, log.CLIFlags("INDEXER")...) flags = append(flags, log.CLIFlags("INDEXER")...)
app := &cli.App{ return &cli.App{
Version: fmt.Sprintf("%s-%s", GitVersion, params.VersionWithCommit(GitCommit, GitDate)), Version: params.VersionWithCommit(GitCommit, GitDate),
Description: "An indexer of all optimism events with a serving api layer", Description: "An indexer of all optimism events with a serving api layer",
EnableBashCompletion: true,
Commands: []*cli.Command{ Commands: []*cli.Command{
{ {
Name: "api", Name: "api",
...@@ -110,11 +96,14 @@ func NewCli(GitVersion string, GitCommit string, GitDate string) *Cli { ...@@ -110,11 +96,14 @@ func NewCli(GitVersion string, GitCommit string, GitDate string) *Cli {
Description: "Runs the indexing service", Description: "Runs the indexing service",
Action: runIndexer, Action: runIndexer,
}, },
{
Name: "version",
Description: "print version",
Action: func(ctx *cli.Context) error {
cli.ShowVersion(ctx)
return nil
},
},
}, },
} }
return &Cli{
app: app,
Flags: flags,
}
} }
...@@ -3,20 +3,17 @@ package main ...@@ -3,20 +3,17 @@ package main
import ( import (
"os" "os"
"github.com/ethereum-optimism/optimism/indexer/cli"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
var ( var (
GitVersion = "" GitCommit = ""
GitCommit = "" GitDate = ""
GitDate = ""
) )
func main() { func main() {
app := cli.NewCli(GitVersion, GitCommit, GitDate) app := newCli(GitCommit, GitDate)
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
log.Crit("Application failed", "message", err) log.Crit("application failed", "err", err)
} }
} }
...@@ -99,20 +99,18 @@ type MetricsConfig struct { ...@@ -99,20 +99,18 @@ type MetricsConfig struct {
// LoadConfig loads the `indexer.toml` config file from a given path // LoadConfig loads the `indexer.toml` config file from a given path
func LoadConfig(logger geth_log.Logger, path string) (Config, error) { func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
logger.Info("Loading config file", "path", path) logger.Debug("loading config", "path", path)
var conf Config
var conf Config
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return conf, err return conf, err
} }
data = []byte(os.ExpandEnv(string(data))) data = []byte(os.ExpandEnv(string(data)))
logger.Debug("parsed config file", "data", string(data))
logger.Debug("Decoding config file", "data", string(data))
if _, err := toml.Decode(string(data), &conf); err != nil { if _, err := toml.Decode(string(data), &conf); err != nil {
logger.Info("Failed to decode config file", "message", err) logger.Info("failed to decode config file", "err", err)
return conf, err return conf, err
} }
...@@ -125,7 +123,6 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) { ...@@ -125,7 +123,6 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
} }
} }
logger.Debug("Loaded config file", conf) logger.Info("loaded config")
return conf, nil return conf, nil
} }
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
const gameDirPrefix = "game-" const gameDirPrefix = "game-"
// diskManager coordinates // diskManager coordinates the storage of game data on disk.
type diskManager struct { type diskManager struct {
datadir string datadir string
} }
...@@ -42,11 +42,11 @@ func (d *diskManager) RemoveAllExcept(keep []common.Address) error { ...@@ -42,11 +42,11 @@ func (d *diskManager) RemoveAllExcept(keep []common.Address) error {
name := entry.Name()[len(gameDirPrefix):] name := entry.Name()[len(gameDirPrefix):]
addr := common.HexToAddress(name) addr := common.HexToAddress(name)
if addr == (common.Address{}) { if addr == (common.Address{}) {
// Couldn't parse the directory name to an address so mustn't be a game directory // Ignore directories with non-address names.
continue continue
} }
if slices.Contains(keep, addr) { if slices.Contains(keep, addr) {
// We need to preserve this data // Preserve data for games we should keep.
continue continue
} }
if err := os.RemoveAll(filepath.Join(d.datadir, entry.Name())); err != nil { if err := os.RemoveAll(filepath.Join(d.datadir, entry.Name())); err != nil {
......
...@@ -13,7 +13,7 @@ importers: ...@@ -13,7 +13,7 @@ importers:
version: 2.26.0 version: 2.26.0
'@codechecks/client': '@codechecks/client':
specifier: ^0.1.11 specifier: ^0.1.11
version: 0.1.11(typescript@5.1.6) version: 0.1.12(typescript@5.1.6)
devDependencies: devDependencies:
'@babel/eslint-parser': '@babel/eslint-parser':
specifier: ^7.18.2 specifier: ^7.18.2
...@@ -1204,8 +1204,8 @@ packages: ...@@ -1204,8 +1204,8 @@ packages:
prettier: 2.8.8 prettier: 2.8.8
dev: false dev: false
/@codechecks/client@0.1.11(typescript@5.1.6): /@codechecks/client@0.1.12(typescript@5.1.6):
resolution: {integrity: sha512-dSIzHnGNcXxDZtnVQEXWQHXH2v9KrpnK4mDGDxdwSu3l00rOIVwJcttj0wzx0bC0Q6gs65VsQdZH4gkanLdXOA==} resolution: {integrity: sha512-2GHHvhO3kaOyxFXxOaiznlY8ARmz33/p+WQdhc2y6wzWw5eOl2wSwg1eZxx3LsWlAnB963Y4bd1YjZcGIhKRzA==}
engines: {node: '>=6'} engines: {node: '>=6'}
hasBin: true hasBin: true
dependencies: dependencies:
...@@ -1221,7 +1221,7 @@ packages: ...@@ -1221,7 +1221,7 @@ packages:
lodash: 4.17.21 lodash: 4.17.21
marked: 0.7.0 marked: 0.7.0
marked-terminal: 3.3.0(marked@0.7.0) marked-terminal: 3.3.0(marked@0.7.0)
mkdirp: 0.5.5 mkdirp: 0.5.6
ms: 2.1.3 ms: 2.1.3
promise: 8.1.0 promise: 8.1.0
request: 2.88.2 request: 2.88.2
...@@ -11916,19 +11916,11 @@ packages: ...@@ -11916,19 +11916,11 @@ packages:
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
dev: false dev: false
/mkdirp@0.5.5:
resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==}
hasBin: true
dependencies:
minimist: 1.2.8
dev: false
/mkdirp@0.5.6: /mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true hasBin: true
dependencies: dependencies:
minimist: 1.2.8 minimist: 1.2.8
dev: true
/mkdirp@1.0.4: /mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
......
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