Skip to content
This repository has been archived by the owner on Jan 25, 2025. It is now read-only.

Commit

Permalink
Refactor database and server code
Browse files Browse the repository at this point in the history
- Added Vote method to DbService for updating visitor model
- Updated routes.go to handle /vote endpoint
- Added VoteHandler to handle vote requests
- Updated sqlc models and queries for visitor model updates
- Updated schema.sql to add models table and foreign key constraint
  • Loading branch information
tahirmurata committed Sep 20, 2024
1 parent 87cc933 commit 3354533
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 34 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/labstack/echo/v4 v4.12.0
github.com/sqids/sqids-go v0.4.1
github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d
golang.org/x/time v0.6.0
)

require (
Expand All @@ -29,5 +30,4 @@ require (
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.6.0 // indirect
)
31 changes: 31 additions & 0 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
type Service interface {
Password(key string) (sqlc.Node, bool, error)

Vote(modelID int64, visitorID int64, visitorRandom int32) error

GetVisitor(ip netip.Addr, sqid *sqids.Sqids) (string, error)

CreateVisitor(ip netip.Addr, rand int32, sqid *sqids.Sqids) (string, error)
Expand Down Expand Up @@ -114,6 +116,35 @@ func (s *DbService) Password(key string) (sqlc.Node, bool, error) {
return nodeByKey, true, nil
}

func (s *DbService) Vote(modelID int64, visitorID int64, visitorRandom int32) error {
ctx := context.Background()

q, err := s.DB.Begin(ctx)
defer func(q pgx.Tx, ctx context.Context) {
_ = q.Rollback(ctx)
}(q, ctx)
if err != nil {
return err
}
queries := sqlc.New(q)

err = queries.UpdateVisitorModel(ctx, sqlc.UpdateVisitorModelParams{
ModelID: pgtype.Int8{Int64: modelID, Valid: true},
ID: visitorID,
Random: visitorRandom,
})
if err != nil {
return err
}

err = q.Commit(ctx)
if err != nil {
return err
}

return nil
}

func (s *DbService) GetVisitor(ip netip.Addr, sqid *sqids.Sqids) (string, error) {
ctx := context.Background()

Expand Down
54 changes: 45 additions & 9 deletions internal/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/sqids/sqids-go"
"golang.org/x/time/rate"
)

func Sqids() (*sqids.Sqids, error) {
Expand All @@ -34,16 +35,13 @@ type (
}
)

func RealIP(c echo.Context) string {
ip := c.Request().Header.Get("Fly-Client-IP")

return ip
}

func (s *Server) RegisterRoutes() http.Handler {
hosts := map[string]*Host{}

api := echo.New()
api.IPExtractor = func(r *http.Request) string {
return r.Header.Get("Fly-Client-IP")
}
api.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogURI: true,
LogMethod: true,
Expand All @@ -66,13 +64,16 @@ func (s *Server) RegisterRoutes() http.Handler {
api.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowMethods: []string{http.MethodGet, http.MethodPatch, http.MethodPost},
}))
api.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(rate.Limit(20))))

api.GET("/ip", s.PingHandler)

api.GET("/visitor", s.VisitorHandler)

api.POST("/node", s.NodeIpHandler)

api.POST("/vote", s.VoteHandler)

protected := api.Group("/protected", middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
node, ok, err := s.DB.Password(key)
if err != nil {
Expand Down Expand Up @@ -129,7 +130,7 @@ func (s *Server) RegisterRoutes() http.Handler {
}

func (s *Server) PingHandler(c echo.Context) error {
ip := RealIP(c)
ip := c.RealIP()
addr, err := netip.ParseAddr(ip)
if err != nil {
slog.Default().Error("ParseAddr", "error", err)
Expand All @@ -139,7 +140,7 @@ func (s *Server) PingHandler(c echo.Context) error {
}

func (s *Server) VisitorHandler(c echo.Context) error {
ip := RealIP(c)
ip := c.RealIP()

sqid, err := Sqids()
if err != nil {
Expand Down Expand Up @@ -177,6 +178,41 @@ func (s *Server) VisitorHandler(c echo.Context) error {
})
}

type Vote struct {
ModelID int `json:"model_id"`
VisitorF3SiD string `json:"f3sid"`
}

func (s *Server) VoteHandler(c echo.Context) error {
var vote Vote

err := c.Bind(&vote)
if err != nil {
slog.Default().Error("bind", "error", err)
return echo.ErrBadRequest
}

sqid, err := Sqids()
if err != nil {
slog.Default().Error("sqids initialization", "error", err)
return echo.ErrInternalServerError
}

voteVisitorID := sqid.Decode(vote.VisitorF3SiD)
if len(voteVisitorID) != 2 {
slog.Default().Error("sqids decode", "error", "invalid sqids")
return echo.ErrBadRequest
}

err = s.DB.Vote(int64(vote.ModelID), int64(voteVisitorID[0]), int32(voteVisitorID[1]))
if err != nil {
slog.Default().Error("vote", "error", err)
return echo.ErrBadRequest
}

return c.NoContent(http.StatusOK)
}

type PushEntry struct {
VisitorF3SiD string `json:"f3sid"`
}
Expand Down Expand Up @@ -478,7 +514,7 @@ func (s *Server) NodeUpdatePushHandler(c echo.Context) error {
}

func (s *Server) NodeIpHandler(c echo.Context) error {
ip := RealIP(c)
ip := c.RealIP()

addr, err := netip.ParseAddr(ip)
if err != nil {
Expand Down
10 changes: 9 additions & 1 deletion internal/sqlc/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 31 additions & 8 deletions internal/sqlc/query.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions sql/query.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ LIMIT 1;
INSERT INTO visitors (ip, random)
VALUES ($1, $2)
RETURNING *;
-- name: UpdateVisitorModel :exec
UPDATE visitors
SET model_id = $1,
updated_at = now()
WHERE id = $2
AND random = $3;
-- name: CreateBattery :exec
INSERT INTO batteries (
node_id,
Expand Down
Loading

0 comments on commit 3354533

Please sign in to comment.