From 6a0bccb3318515716f4511a295253c33e7177627 Mon Sep 17 00:00:00 2001 From: Evgenii Baidakov Date: Tue, 22 Oct 2024 12:53:43 +0400 Subject: [PATCH] *: Cache network settings Closes #247. Caching data for the half epoch duration time. Signed-off-by: Evgenii Baidakov --- cmd/neofs-rest-gw/config.go | 1 + handlers/api.go | 9 ++++++ handlers/containers.go | 13 +++++++-- internal/cache/networkinfo.go | 54 +++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 internal/cache/networkinfo.go diff --git a/cmd/neofs-rest-gw/config.go b/cmd/neofs-rest-gw/config.go index aba4b6e..1cf4dcd 100644 --- a/cmd/neofs-rest-gw/config.go +++ b/cmd/neofs-rest-gw/config.go @@ -596,6 +596,7 @@ func newNeofsAPI(ctx context.Context, logger *zap.Logger, v *viper.Viper) (*hand } apiPrm.DefaultTimestamp = v.GetBool(cfgPoolDefaultTimestamp) + apiPrm.EpochUpdateInterval = time.Duration(int64(ni.EpochDuration())/2*ni.MsPerBlock()) * time.Millisecond return handlers.NewAPI(&apiPrm) } diff --git a/handlers/api.go b/handlers/api.go index 64c5771..cba5149 100644 --- a/handlers/api.go +++ b/handlers/api.go @@ -11,8 +11,10 @@ import ( "github.com/labstack/echo/v4" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-rest-gw/handlers/apiserver" + "github.com/nspcc-dev/neofs-rest-gw/internal/cache" "github.com/nspcc-dev/neofs-rest-gw/internal/util" "github.com/nspcc-dev/neofs-rest-gw/metrics" + "github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/pool" "github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/user" @@ -32,6 +34,7 @@ type PrmAPI struct { PrometheusService *metrics.Service PprofService *metrics.Service ServiceShutdownTimeout time.Duration + EpochUpdateInterval time.Duration } type BearerToken struct { @@ -45,6 +48,10 @@ type SessionToken struct { Verb session.ContainerVerb } +type networkInfoGetter interface { + NetworkInfo(ctx context.Context) (netmap.NetworkInfo, error) +} + const ( // bearerCookieName is the name of the bearer cookie. bearerCookieName = "Bearer" @@ -75,6 +82,7 @@ func NewAPI(prm *PrmAPI) (*RestAPI, error) { pprofService: prm.PprofService, gateMetric: prm.GateMetric, serviceShutdownTimeout: prm.ServiceShutdownTimeout, + networkInfoGetter: cache.NewNetworkInfoCache(prm.Pool, prm.EpochUpdateInterval), }, nil } @@ -141,6 +149,7 @@ type RestAPI struct { prometheusService *metrics.Service pprofService *metrics.Service serviceShutdownTimeout time.Duration + networkInfoGetter networkInfoGetter } func (a *RestAPI) StartCallback() { diff --git a/handlers/containers.go b/handlers/containers.go index 53c552d..72b6322 100644 --- a/handlers/containers.go +++ b/handlers/containers.go @@ -64,7 +64,7 @@ func (a *RestAPI) PutContainer(ctx echo.Context, params apiserver.PutContainerPa return ctx.JSON(http.StatusBadRequest, resp) } - cnrID, err := createContainer(ctx.Request().Context(), a.pool, stoken, body, params, a.signer) + cnrID, err := createContainer(ctx.Request().Context(), a.pool, stoken, body, params, a.signer, a.networkInfoGetter) if err != nil { resp := a.logAndGetErrorResponse("create container", err) return ctx.JSON(http.StatusBadRequest, resp) @@ -381,7 +381,7 @@ func getContainerEACL(ctx context.Context, p *pool.Pool, cnrID cid.ID) (*apiserv return tableResp, nil } -func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container, request apiserver.ContainerPutInfo, params apiserver.PutContainerParams, signer user.Signer) (cid.ID, error) { +func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container, request apiserver.ContainerPutInfo, params apiserver.PutContainerParams, signer user.Signer, networkInfoGetter networkInfoGetter) (cid.ID, error) { if request.PlacementPolicy == "" { request.PlacementPolicy = defaultPlacementPolicy } @@ -406,6 +406,15 @@ func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container cnr.SetBasicACL(basicACL) cnr.SetOwner(stoken.Issuer()) + ni, err := networkInfoGetter.NetworkInfo(ctx) + if err != nil { + return cid.ID{}, fmt.Errorf("couldn't get network info: %w", err) + } + + if ni.HomomorphicHashingDisabled() { + cnr.DisableHomomorphicHashing() + } + cnr.SetCreationTime(time.Now()) if request.ContainerName != "" { diff --git a/internal/cache/networkinfo.go b/internal/cache/networkinfo.go new file mode 100644 index 0000000..6375346 --- /dev/null +++ b/internal/cache/networkinfo.go @@ -0,0 +1,54 @@ +package cache + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/nspcc-dev/neofs-sdk-go/client" + "github.com/nspcc-dev/neofs-sdk-go/netmap" + "github.com/nspcc-dev/neofs-sdk-go/pool" +) + +type ( + // NetworkInfo is cache wrapper for the network info. + NetworkInfo struct { + p *pool.Pool + ttl time.Duration + + mu *sync.RWMutex + validUntil time.Time + ni netmap.NetworkInfo + } +) + +func NewNetworkInfoCache(p *pool.Pool, ttl time.Duration) *NetworkInfo { + return &NetworkInfo{ + p: p, + ttl: ttl, + mu: &sync.RWMutex{}, + } +} + +func (n *NetworkInfo) NetworkInfo(ctx context.Context) (netmap.NetworkInfo, error) { + n.mu.RLock() + if n.validUntil.After(time.Now()) { + defer n.mu.RUnlock() + + return n.ni, nil + } + n.mu.RUnlock() + + ni, err := n.p.NetworkInfo(ctx, client.PrmNetworkInfo{}) + if err != nil { + return netmap.NetworkInfo{}, fmt.Errorf("get network info: %w", err) + } + + n.mu.Lock() + n.validUntil = time.Now().Add(n.ttl) + n.ni = ni + n.mu.Unlock() + + return ni, nil +}