Skip to content

Commit

Permalink
Refactoring: use fx library (#86)
Browse files Browse the repository at this point in the history
* Refactoring: use fx library

* Fix: security issue #23

* Fix: add websocket endpoint

* Remove unused notificator

* Refactoring: api server creation
  • Loading branch information
aopoltorzhicky authored Feb 18, 2025
1 parent f524581 commit 5185129
Show file tree
Hide file tree
Showing 81 changed files with 1,298 additions and 858 deletions.
104 changes: 104 additions & 0 deletions cmd/api/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package main

import (
"context"
"net/http"

"github.com/celenium-io/astria-indexer/cmd/api/bus"
"github.com/celenium-io/astria-indexer/cmd/api/cache"
"github.com/celenium-io/astria-indexer/cmd/api/handler/websocket"
"github.com/celenium-io/astria-indexer/internal/storage"
"github.com/dipdup-net/indexer-sdk/pkg/storage/postgres"
"github.com/grafana/pyroscope-go"
"github.com/labstack/echo/v4"
"github.com/pkg/errors"
"go.uber.org/fx"
)

type App struct {
e *echo.Echo
db *postgres.Storage
wsManager *websocket.Manager
dispatcher *bus.Dispatcher
constantCache *cache.ConstantsCache
endpointCache *cache.Cache
prscp *pyroscope.Profiler
constants storage.IConstant
}

func newApp(
lc fx.Lifecycle,
cfg *Config,
e *echo.Echo,
db *postgres.Storage,
wsManager *websocket.Manager,
dispatcher *bus.Dispatcher,
constantCache *cache.ConstantsCache,
endpointCache *cache.Cache,
prscp *pyroscope.Profiler,
constants storage.IConstant,
) *App {
app := &App{
e: e,
db: db,
wsManager: wsManager,
dispatcher: dispatcher,
constantCache: constantCache,
endpointCache: endpointCache,
prscp: prscp,
constants: constants,
}

lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
dispatcher.Start(ctx)
wsManager.Start(ctx)
endpointCache.Start(ctx)
if err := constantCache.Start(ctx, app.constants); err != nil {
return errors.Wrap(err, "start constant cache")
}

if err := app.e.Start(cfg.ApiConfig.Bind); err != nil && errors.Is(err, http.ErrServerClosed) {
return errors.Wrap(err, "shutting down the server")
}
return nil
},
OnStop: func(ctx context.Context) error {
if app.wsManager != nil {
if err := app.wsManager.Close(); err != nil {
return errors.Wrap(err, "closing websocket manager")
}
}
if app.endpointCache != nil {
if err := app.endpointCache.Close(); err != nil {
return errors.Wrap(err, "closing cache")
}
}
if app.constantCache != nil {
if err := app.constantCache.Close(); err != nil {
return errors.Wrap(err, "closing constant cache")
}
}
if app.dispatcher != nil {
if err := app.dispatcher.Close(); err != nil {
return errors.Wrap(err, "closing bus dispatcher")
}
}

if err := app.e.Shutdown(ctx); err != nil {
return errors.Wrap(err, "closing server")
}

if app.prscp != nil {
if err := app.prscp.Stop(); err != nil {
return errors.Wrap(err, "closing profler")
}
}
if err := app.db.Close(); err != nil {
return errors.Wrap(err, "closing database")
}
return nil
},
})
return app
}
8 changes: 8 additions & 0 deletions cmd/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,11 @@ type ApiConfig struct {
SentryDsn string `validate:"omitempty" yaml:"sentry_dsn"`
Websocket bool `validate:"omitempty" yaml:"websocket"`
}

func indexerName(cfg *Config) string {
return cfg.Indexer.Name
}

func databaseConfig(cfg *Config) config.Database {
return cfg.Database
}
20 changes: 20 additions & 0 deletions cmd/api/handler/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ func NewAddressHandler(
}
}

var _ Handler = (*AddressHandler)(nil)

func (handler *AddressHandler) InitRoutes(srvr *echo.Group) {
addressesGroup := srvr.Group("/address")
{
addressesGroup.GET("", handler.List)
addressesGroup.GET("/count", handler.Count)
addressGroup := addressesGroup.Group("/:hash")
{
addressGroup.GET("", handler.Get)
addressGroup.GET("/txs", handler.Transactions)
addressGroup.GET("/actions", handler.Actions)
addressGroup.GET("/rollups", handler.Rollups)
addressGroup.GET("/roles", handler.Roles)
addressGroup.GET("/fees", handler.Fees)
addressGroup.GET("/deposits", handler.Deposits)
}
}
}

type getAddressRequest struct {
Hash string `param:"hash" validate:"required,address"`
}
Expand Down
13 changes: 13 additions & 0 deletions cmd/api/handler/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ func NewAppHandler(
}
}

var _ Handler = (*AppHandler)(nil)

func (handler *AppHandler) InitRoutes(srvr *echo.Group) {
apps := srvr.Group("/app")
{
apps.GET("", handler.Leaderboard)
app := apps.Group("/:slug")
{
app.GET("", handler.Get)
}
}
}

type leaderboardRequest struct {
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
Offset int `query:"offset" validate:"omitempty,min=0"`
Expand Down
9 changes: 9 additions & 0 deletions cmd/api/handler/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ func NewAssetHandler(
}
}

var _ Handler = (*AssetHandler)(nil)

func (handler *AssetHandler) InitRoutes(srvr *echo.Group) {
assets := srvr.Group("/asset")
{
assets.GET("", handler.List)
}
}

type assetListRequest struct {
Limit uint64 `query:"limit" validate:"omitempty,min=1,max=100"`
Offset uint64 `query:"offset" validate:"omitempty,min=0"`
Expand Down
19 changes: 19 additions & 0 deletions cmd/api/handler/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ func NewBlockHandler(
}
}

var _ Handler = (*BlockHandler)(nil)

func (handler *BlockHandler) InitRoutes(srvr *echo.Group) {
blockGroup := srvr.Group("/block")
{
blockGroup.GET("", handler.List)
blockGroup.GET("/count", handler.Count)
heightGroup := blockGroup.Group("/:height")
{
heightGroup.GET("", handler.Get)
heightGroup.GET("/actions", handler.GetActions)
heightGroup.GET("/txs", handler.GetTransactions)
heightGroup.GET("/stats", handler.GetStats)
heightGroup.GET("/rollup_actions", handler.GetRollupActions)
heightGroup.GET("/rollup_actions/count", handler.GetRollupsActionsCount)
}
}
}

type getBlockByHeightRequest struct {
Height types.Level `param:"height" validate:"min=0"`
}
Expand Down
7 changes: 7 additions & 0 deletions cmd/api/handler/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ func NewConstantHandler(constants storage.IConstant) *ConstantHandler {
}
}

var _ Handler = (*ConstantHandler)(nil)

func (handler *ConstantHandler) InitRoutes(srvr *echo.Group) {
srvr.GET("/constants", handler.Get)
srvr.GET("/enums", handler.Enums)
}

// Get godoc
//
// @Summary Get network constants
Expand Down
7 changes: 7 additions & 0 deletions cmd/api/handler/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package handler

import "github.com/labstack/echo/v4"

type Handler interface {
InitRoutes(srvr *echo.Group)
}
20 changes: 20 additions & 0 deletions cmd/api/handler/rollup.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,26 @@ func NewRollupHandler(
}
}

var _ Handler = (*RollupHandler)(nil)

func (handler *RollupHandler) InitRoutes(srvr *echo.Group) {
rollupsGroup := srvr.Group("/rollup")
{
rollupsGroup.GET("", handler.List)
rollupsGroup.GET("/count", handler.Count)

rollupGroup := rollupsGroup.Group("/:hash")
{
rollupGroup.GET("", handler.Get)
rollupGroup.GET("/actions", handler.Actions)
rollupGroup.GET("/all_actions", handler.AllActions)
rollupGroup.GET("/addresses", handler.Addresses)
rollupGroup.GET("/bridges", handler.Bridges)
rollupGroup.GET("/deposits", handler.Deposits)
}
}
}

type getRollupRequest struct {
Hash string `param:"hash" validate:"required,base64url"`
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/api/handler/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ func NewSearchHandler(
}
}

var _ Handler = (*SearchHandler)(nil)

func (s *SearchHandler) InitRoutes(srvr *echo.Group) {
srvr.GET("/search", s.Search)
}

type searchRequest struct {
Search string `query:"query" validate:"required"`
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/api/handler/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ func NewStateHandler(state storage.IState) *StateHandler {
}
}

var _ Handler = (*StateHandler)(nil)

func (sh *StateHandler) InitRoutes(srvr *echo.Group) {
srvr.GET("/head", sh.Head)
}

// Head godoc
//
// @Summary Get current indexer head
Expand Down
45 changes: 36 additions & 9 deletions cmd/api/handler/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,40 @@ type StatsHandler struct {
rollups storage.IRollup
}

func NewStatsHandler(repo storage.IStats, rollups storage.IRollup) StatsHandler {
return StatsHandler{
func NewStatsHandler(repo storage.IStats, rollups storage.IRollup) *StatsHandler {
return &StatsHandler{
repo: repo,
rollups: rollups,
}
}

var _ Handler = (*StatsHandler)(nil)

func (sh *StatsHandler) InitRoutes(srvr *echo.Group) {
stats := srvr.Group("/stats")
{
stats.GET("/summary", sh.Summary)
stats.GET("/summary/:timeframe", sh.SummaryTimeframe)
stats.GET("/summary/active_addresses_count", sh.ActiveAddressesCount)
stats.GET("/series/:name/:timeframe", sh.Series)

rollup := stats.Group("/rollup")
{
rollup.GET("/series/:hash/:name/:timeframe", sh.RollupSeries)
}

fee := stats.Group("/fee")
{
fee.GET("/summary", sh.FeeSummary)
}

token := stats.Group("/token")
{
token.GET("/transfer_distribution", sh.TokenTransferDistribution)
}
}
}

// Summary godoc
//
// @Summary Get network summary
Expand All @@ -34,7 +61,7 @@ func NewStatsHandler(repo storage.IStats, rollups storage.IRollup) StatsHandler
// @Success 200 {array} responses.NetworkSummary
// @Failure 500 {object} Error
// @Router /v1/stats/summary [get]
func (sh StatsHandler) Summary(c echo.Context) error {
func (sh *StatsHandler) Summary(c echo.Context) error {
summary, err := sh.repo.Summary(c.Request().Context())
if err != nil {
return handleError(c, err, sh.rollups)
Expand All @@ -58,7 +85,7 @@ type summaryTimeframeRequest struct {
// @Failure 400 {object} Error
// @Failure 500 {object} Error
// @Router /v1/stats/summary/{timeframe} [get]
func (sh StatsHandler) SummaryTimeframe(c echo.Context) error {
func (sh *StatsHandler) SummaryTimeframe(c echo.Context) error {
req, err := bindAndValidate[summaryTimeframeRequest](c)
if err != nil {
return badRequestError(c, err)
Expand Down Expand Up @@ -93,7 +120,7 @@ type seriesRequest struct {
// @Failure 400 {object} Error
// @Failure 500 {object} Error
// @Router /v1/stats/series/{name}/{timeframe} [get]
func (sh StatsHandler) Series(c echo.Context) error {
func (sh *StatsHandler) Series(c echo.Context) error {
req, err := bindAndValidate[seriesRequest](c)
if err != nil {
return badRequestError(c, err)
Expand Down Expand Up @@ -140,7 +167,7 @@ type rollupSeriesRequest struct {
// @Failure 400 {object} Error
// @Failure 500 {object} Error
// @Router /v1/stats/rollup/series/{hash}/{name}/{timeframe} [get]
func (sh StatsHandler) RollupSeries(c echo.Context) error {
func (sh *StatsHandler) RollupSeries(c echo.Context) error {
req, err := bindAndValidate[rollupSeriesRequest](c)
if err != nil {
return badRequestError(c, err)
Expand Down Expand Up @@ -184,7 +211,7 @@ func (sh StatsHandler) RollupSeries(c echo.Context) error {
// @Success 200 {array} responses.FeeSummary
// @Failure 500 {object} Error
// @Router /v1/stats/fee/summary [get]
func (sh StatsHandler) FeeSummary(c echo.Context) error {
func (sh *StatsHandler) FeeSummary(c echo.Context) error {
summary, err := sh.repo.FeeSummary(c.Request().Context())
if err != nil {
return handleError(c, err, sh.rollups)
Expand Down Expand Up @@ -217,7 +244,7 @@ func (p *tokenTransferDistributionRequest) SetDefault() {
// @Success 200 {array} responses.TokenTransferDistributionItem
// @Failure 500 {object} Error
// @Router /v1/stats/token/transfer_distribution [get]
func (sh StatsHandler) TokenTransferDistribution(c echo.Context) error {
func (sh *StatsHandler) TokenTransferDistribution(c echo.Context) error {
req, err := bindAndValidate[tokenTransferDistributionRequest](c)
if err != nil {
return badRequestError(c, err)
Expand Down Expand Up @@ -245,7 +272,7 @@ func (sh StatsHandler) TokenTransferDistribution(c echo.Context) error {
// @Success 200 {integer} int64
// @Failure 500 {object} Error
// @Router /v1/stats/summary/active_addresses_count [get]
func (sh StatsHandler) ActiveAddressesCount(c echo.Context) error {
func (sh *StatsHandler) ActiveAddressesCount(c echo.Context) error {
count, err := sh.repo.ActiveAddressesCount(c.Request().Context())
if err != nil {
return handleError(c, err, sh.rollups)
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/handler/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type StatsTestSuite struct {
stats *mock.MockIStats
rollups *mock.MockIRollup
echo *echo.Echo
handler StatsHandler
handler *StatsHandler
ctrl *gomock.Controller
}

Expand Down
Loading

0 comments on commit 5185129

Please sign in to comment.