Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ func TestAccuracy(t *testing.T) {
upperLimit := int(maxAllowed * 1.2)
lowerLimit := int(math.Min(maxAllowed*0.95, float64(total)))

t.Logf("total: %d, passed: %d, acceptable: [%d - %d]", total, passed, lowerLimit, upperLimit)
t.Logf("windows: %d, total: %d, passed: %d, acceptable: [%d - %d]", int(windows), total, passed, lowerLimit, upperLimit)
// Verify results
require.GreaterOrEqual(t, passed, lowerLimit,
"Success count should be >= lower limit")
"Passed count should be >= lower limit")
require.LessOrEqual(t, passed, upperLimit,
"Success count should be <= upper limit")
"Passed count should be <= upper limit")

t.Logf("balance: %+v", lb.GetMetrics())

Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ func Register(srv *zen.Server, svc *Services) {
srv.RegisterRoute(
defaultMiddlewares,
v2RatelimitLimit.New(v2RatelimitLimit.Services{
Logger: svc.Logger,
DB: svc.Database,
Keys: svc.Keys,
Ratelimit: svc.Ratelimit,
Permissions: svc.Permissions,
Logger: svc.Logger,
DB: svc.Database,
Keys: svc.Keys,
Ratelimit: svc.Ratelimit,
Permissions: svc.Permissions,
RatelimitNamespaceByNameCache: svc.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: svc.Caches.RatelimitOverridesMatch,
}),
)
// v2/ratelimit.setOverride
Expand Down
2 changes: 2 additions & 0 deletions go/apps/api/routes/services.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package routes

import (
"github.com/unkeyed/unkey/go/internal/services/caches"
"github.com/unkeyed/unkey/go/internal/services/keys"
"github.com/unkeyed/unkey/go/internal/services/permissions"
"github.com/unkeyed/unkey/go/internal/services/ratelimit"
Expand All @@ -22,4 +23,5 @@ type Services struct {
Permissions permissions.PermissionService
Validator *validation.Validator
Ratelimit ratelimit.Service
Caches caches.Caches
}
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/200_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ func TestLimitSuccessfully(t *testing.T) {
require.NoError(t, err)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})

h.Register(route)
Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/400_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ func TestBadRequests(t *testing.T) {
h := testutil.NewHarness(t)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})

h.Register(route)
Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/401_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ func TestUnauthorizedAccess(t *testing.T) {
h := testutil.NewHarness(t)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})

h.Register(route)
Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/403_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ func TestWorkspacePermissions(t *testing.T) {
require.NoError(t, err)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})

h.Register(route)
Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/404_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ func TestNamespaceNotFound(t *testing.T) {
h := testutil.NewHarness(t)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})

h.Register(route)
Expand Down
12 changes: 7 additions & 5 deletions go/apps/api/routes/v2_ratelimit_limit/accuracy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@ func TestRateLimitAccuracy(t *testing.T) {
h := testutil.NewHarness(t)

route := handler.New(handler.Services{
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
DB: h.DB,
Keys: h.Keys,
Logger: h.Logger,
Permissions: h.Permissions,
Ratelimit: h.Ratelimit,
RatelimitNamespaceByNameCache: h.Caches.RatelimitNamespaceByName,
RatelimitOverrideMatchesCache: h.Caches.RatelimitOverridesMatch,
})
h.Register(route)
ctx := context.Background()
Expand Down
50 changes: 42 additions & 8 deletions go/apps/api/routes/v2_ratelimit_limit/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package v2RatelimitLimit

import (
"context"
"database/sql"
"errors"
"net/http"
"time"

"github.com/unkeyed/unkey/go/apps/api/openapi"
"github.com/unkeyed/unkey/go/internal/services/keys"
"github.com/unkeyed/unkey/go/internal/services/permissions"
"github.com/unkeyed/unkey/go/internal/services/ratelimit"
"github.com/unkeyed/unkey/go/pkg/cache"
"github.com/unkeyed/unkey/go/pkg/db"
"github.com/unkeyed/unkey/go/pkg/fault"
"github.com/unkeyed/unkey/go/pkg/otel/logging"
Expand All @@ -21,11 +24,13 @@ type Request = openapi.V2RatelimitLimitRequestBody
type Response = openapi.V2RatelimitLimitResponseBody

type Services struct {
Logger logging.Logger
Keys keys.KeyService
DB db.Database
Permissions permissions.PermissionService
Ratelimit ratelimit.Service
Logger logging.Logger
Keys keys.KeyService
DB db.Database
Permissions permissions.PermissionService
Ratelimit ratelimit.Service
RatelimitNamespaceByNameCache cache.Cache[db.FindRatelimitNamespaceByNameParams, db.RatelimitNamespace]
RatelimitOverrideMatchesCache cache.Cache[db.FindRatelimitOverrideMatchesParams, []db.RatelimitOverride]
}

// New creates a new route handler for ratelimits.limit
Expand Down Expand Up @@ -53,10 +58,26 @@ func New(svc Services) zen.Route {

ctx, span := tracing.Start(ctx, "FindRatelimitNamespaceByName")

namespace, err := db.Query.FindRatelimitNamespaceByName(ctx, svc.DB.RO(), db.FindRatelimitNamespaceByNameParams{
findNamespaceArgs := db.FindRatelimitNamespaceByNameParams{
WorkspaceID: auth.AuthorizedWorkspaceID,
Name: req.Namespace,
}
namespace, err := svc.RatelimitNamespaceByNameCache.SWR(ctx, findNamespaceArgs, func(ctx context.Context) (db.RatelimitNamespace, error) {
return db.Query.FindRatelimitNamespaceByName(ctx, svc.DB.RO(), findNamespaceArgs)
}, func(err error) cache.Op {
if err == nil {
// everything went well and we have a namespace response
return cache.WriteValue
}
if errors.Is(err, sql.ErrNoRows) {
// the response is empty, we need to store that the namespace does not exist
return cache.WriteNull
}
// this is a noop in the cache
return cache.Noop

})

span.End()
if err != nil {
return db.HandleErr(err, "namespace")
Expand Down Expand Up @@ -99,12 +120,25 @@ func New(svc Services) zen.Route {
)
}

ctx, overridesSpan := tracing.Start(ctx, "FindRatelimitOverrideMatches")
overrides, err := db.Query.FindRatelimitOverrideMatches(ctx, svc.DB.RO(), db.FindRatelimitOverrideMatchesParams{
findOverrideMatchesArgs := db.FindRatelimitOverrideMatchesParams{
WorkspaceID: auth.AuthorizedWorkspaceID,
NamespaceID: namespace.ID,
Identifier: req.Identifier,
}
ctx, overridesSpan := tracing.Start(ctx, "FindRatelimitOverrideMatches")
overrides, err := svc.RatelimitOverrideMatchesCache.SWR(ctx, findOverrideMatchesArgs, func(ctx context.Context) ([]db.RatelimitOverride, error) {
return db.Query.FindRatelimitOverrideMatches(ctx, svc.DB.RO(), findOverrideMatchesArgs)
}, func(err error) cache.Op {
if err == nil {
// everything went well and we have a namespace response
return cache.WriteValue
}

// this is a noop in the cache
return cache.Noop

})

overridesSpan.End()
if err != nil {
return db.HandleErr(err, "override")
Expand Down
18 changes: 15 additions & 3 deletions go/apps/api/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/unkeyed/unkey/go/apps/api/routes"
"github.com/unkeyed/unkey/go/internal/services/caches"
"github.com/unkeyed/unkey/go/internal/services/keys"
"github.com/unkeyed/unkey/go/internal/services/permissions"
"github.com/unkeyed/unkey/go/internal/services/ratelimit"
Expand Down Expand Up @@ -101,6 +102,14 @@ func Run(ctx context.Context, cfg Config) error {
}
}

caches, err := caches.New(caches.Config{
Logger: logger,
Clock: clk,
})
if err != nil {
return fmt.Errorf("unable to create caches: %w", err)
}

srv, err := zen.New(zen.Config{
InstanceID: cfg.ClusterInstanceID,
Logger: logger,
Expand All @@ -117,9 +126,10 @@ func Run(ctx context.Context, cfg Config) error {
}

keySvc, err := keys.New(keys.Config{
Logger: logger,
DB: db,
Clock: clk,
Logger: logger,
DB: db,
Clock: clk,
KeyCache: caches.KeyByHash,
})
if err != nil {
return fmt.Errorf("unable to create key service: %w", err)
Expand Down Expand Up @@ -156,6 +166,7 @@ func Run(ctx context.Context, cfg Config) error {
DB: db,
Logger: logger,
Clock: clk,
Cache: caches.PermissionsByKeyId,
})
if err != nil {
return fmt.Errorf("unable to create permissions service: %w", err)
Expand All @@ -169,6 +180,7 @@ func Run(ctx context.Context, cfg Config) error {
Validator: validator,
Ratelimit: rlSvc,
Permissions: p,
Caches: caches,
})

go func() {
Expand Down
Loading
Loading