Add caching

This commit is contained in:
Andrey Chervyakov 2021-03-15 23:13:41 +06:00
parent f166ffab3c
commit fe9b4b5f5f
4 changed files with 36 additions and 21 deletions

1
go.mod
View file

@ -13,6 +13,7 @@ require (
github.com/knadh/koanf v0.15.0 github.com/knadh/koanf v0.15.0
github.com/labstack/echo/v4 v4.2.1 github.com/labstack/echo/v4 v4.2.1
github.com/mitchellh/copystructure v1.1.1 // indirect github.com/mitchellh/copystructure v1.1.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/rs/zerolog v1.20.0 github.com/rs/zerolog v1.20.0
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 // indirect golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 // indirect
golang.org/x/text v0.3.5 // indirect golang.org/x/text v0.3.5 // indirect

2
go.sum
View file

@ -212,6 +212,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=

View file

@ -8,11 +8,9 @@ import (
"strconv" "strconv"
) )
func redirectHandler(c echo.Context, pool *pgxpool.Pool) error { func redirectHandler(c echo.Context, serv *PgService) error {
linkId := c.Param("id") linkId := c.Param("id")
serv := PgService{rep: PgRepository{pool: pool}}
link, err := serv.GetById(linkId) link, err := serv.GetById(linkId)
if err != nil { if err != nil {
return err return err
@ -21,7 +19,7 @@ func redirectHandler(c echo.Context, pool *pgxpool.Pool) error {
return c.Redirect(http.StatusSeeOther, link.RedirectURL.String()) return c.Redirect(http.StatusSeeOther, link.RedirectURL.String())
} }
func creationHandler(c echo.Context, pool *pgxpool.Pool) error { func creationHandler(c echo.Context, serv *PgService) error {
var model CreationModel var model CreationModel
if err := json.NewDecoder(c.Request().Body).Decode(&model); err != nil { if err := json.NewDecoder(c.Request().Body).Decode(&model); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid data format.") return echo.NewHTTPError(http.StatusBadRequest, "Invalid data format.")
@ -32,8 +30,6 @@ func creationHandler(c echo.Context, pool *pgxpool.Pool) error {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid URL.") return echo.NewHTTPError(http.StatusBadRequest, "Invalid URL.")
} }
serv := PgService{rep: PgRepository{pool: pool}}
if err = serv.Create(entity); err != nil { if err = serv.Create(entity); err != nil {
return err return err
} }
@ -41,11 +37,9 @@ func creationHandler(c echo.Context, pool *pgxpool.Pool) error {
return c.NoContent(http.StatusCreated) return c.NoContent(http.StatusCreated)
} }
func retrievalByIdHandler(c echo.Context, pool *pgxpool.Pool) error { func retrievalByIdHandler(c echo.Context, serv *PgService) error {
linkId := c.Param("id") linkId := c.Param("id")
serv := PgService{rep: PgRepository{pool: pool}}
l, err := serv.GetById(linkId) l, err := serv.GetById(linkId)
if err != nil { if err != nil {
return err return err
@ -54,7 +48,7 @@ func retrievalByIdHandler(c echo.Context, pool *pgxpool.Pool) error {
return c.JSON(http.StatusOK, MapEntityToModel(l)) return c.JSON(http.StatusOK, MapEntityToModel(l))
} }
func allRetrievalHandler(c echo.Context, pool *pgxpool.Pool) error { func allRetrievalHandler(c echo.Context, serv *PgService) error {
limit := 20 limit := 20
if v := c.QueryParam("limit"); v != "" { if v := c.QueryParam("limit"); v != "" {
num, err := strconv.Atoi(v) num, err := strconv.Atoi(v)
@ -75,8 +69,6 @@ func allRetrievalHandler(c echo.Context, pool *pgxpool.Pool) error {
offset = num offset = num
} }
serv := PgService{rep: PgRepository{pool: pool}}
links, err := serv.GetAll(limit, offset) links, err := serv.GetAll(limit, offset)
if err != nil { if err != nil {
return err return err
@ -90,11 +82,9 @@ func allRetrievalHandler(c echo.Context, pool *pgxpool.Pool) error {
return c.JSON(http.StatusOK, models) return c.JSON(http.StatusOK, models)
} }
func removalHandler(c echo.Context, pool *pgxpool.Pool) error { func removalHandler(c echo.Context, serv *PgService) error {
linkId := c.Param("id") linkId := c.Param("id")
serv := PgService{rep: PgRepository{pool: pool}}
if err := serv.DeleteById(linkId); err != nil { if err := serv.DeleteById(linkId); err != nil {
return err return err
} }
@ -103,25 +93,27 @@ func removalHandler(c echo.Context, pool *pgxpool.Pool) error {
} }
func AddHandlers(s *echo.Echo, pool *pgxpool.Pool) { func AddHandlers(s *echo.Echo, pool *pgxpool.Pool) {
serv := NewPgService(PgRepository{pool: pool})
gr := s.Group("/links") gr := s.Group("/links")
gr.POST("", func(ctx echo.Context) error { gr.POST("", func(ctx echo.Context) error {
return creationHandler(ctx, pool) return creationHandler(ctx, &serv)
}) })
gr.GET("", func(ctx echo.Context) error { gr.GET("", func(ctx echo.Context) error {
return allRetrievalHandler(ctx, pool) return allRetrievalHandler(ctx, &serv)
}) })
gr.GET("/:id", func(ctx echo.Context) error { gr.GET("/:id", func(ctx echo.Context) error {
return retrievalByIdHandler(ctx, pool) return retrievalByIdHandler(ctx, &serv)
}) })
gr.DELETE("/:id", func(ctx echo.Context) error { gr.DELETE("/:id", func(ctx echo.Context) error {
return removalHandler(ctx, pool) return removalHandler(ctx, &serv)
}) })
s.GET("/:id", func(ctx echo.Context) error { s.GET("/:id", func(ctx echo.Context) error {
return redirectHandler(ctx, pool) return redirectHandler(ctx, &serv)
}) })
} }

View file

@ -2,6 +2,8 @@ package link
import ( import (
apperrors "cgnolink/errors" apperrors "cgnolink/errors"
"github.com/patrickmn/go-cache"
"time"
) )
type Service interface { type Service interface {
@ -12,7 +14,15 @@ type Service interface {
} }
type PgService struct { type PgService struct {
rep PgRepository rep PgRepository
cache *cache.Cache
}
func NewPgService(rep PgRepository) PgService {
return PgService{
rep: rep,
cache: cache.New(1*time.Hour, 90*time.Minute),
}
} }
func (s *PgService) Create(link *Link) error { func (s *PgService) Create(link *Link) error {
@ -33,6 +43,12 @@ func (s *PgService) Create(link *Link) error {
} }
func (s *PgService) GetById(id string) (*Link, error) { func (s *PgService) GetById(id string) (*Link, error) {
if v, found := s.cache.Get(id); found {
if link, ok := v.(*Link); ok {
return link, nil
}
}
link, err := s.rep.FindById(id) link, err := s.rep.FindById(id)
if err != nil { if err != nil {
return nil, apperrors.UnknownError{Err: err} return nil, apperrors.UnknownError{Err: err}
@ -42,6 +58,8 @@ func (s *PgService) GetById(id string) (*Link, error) {
return nil, apperrors.NotFoundError{Message: "Link with given ID was not found."} return nil, apperrors.NotFoundError{Message: "Link with given ID was not found."}
} }
s.cache.Set(id, link, 0)
return link, nil return link, nil
} }
@ -55,6 +73,8 @@ func (s *PgService) GetAll(limit int, offset int) (Links, error) {
} }
func (s *PgService) DeleteById(id string) error { func (s *PgService) DeleteById(id string) error {
s.cache.Delete(id)
if err := s.rep.DeleteById(id); err != nil { if err := s.rep.DeleteById(id); err != nil {
return apperrors.UnknownError{Err: err} return apperrors.UnknownError{Err: err}
} }