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
3 changes: 3 additions & 0 deletions iac/modules/job-dashboard-api/jobs/dashboard-api.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ job "dashboard-api" {
AUTH_DB_READ_REPLICA_CONNECTION_STRING = "${auth_db_read_replica_connection_string}"
CLICKHOUSE_CONNECTION_STRING = "${clickhouse_connection_string}"
SUPABASE_JWT_SECRETS = "${supabase_jwt_secrets}"
REDIS_URL = "${redis_url}"
REDIS_CLUSTER_URL = "${redis_cluster_url}"
REDIS_TLS_CA_BASE64 = "${redis_tls_ca_base64}"
OTEL_COLLECTOR_GRPC_ENDPOINT = "${otel_collector_grpc_endpoint}"
LOGS_COLLECTOR_ADDRESS = "${logs_collector_address}"
}
Expand Down
3 changes: 3 additions & 0 deletions iac/modules/job-dashboard-api/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ resource "nomad_job" "dashboard_api" {
auth_db_read_replica_connection_string = var.auth_db_read_replica_connection_string
clickhouse_connection_string = var.clickhouse_connection_string
supabase_jwt_secrets = var.supabase_jwt_secrets
redis_url = var.redis_url
redis_cluster_url = var.redis_cluster_url
redis_tls_ca_base64 = var.redis_tls_ca_base64

subdomain = "dashboard-api"

Expand Down
16 changes: 16 additions & 0 deletions iac/modules/job-dashboard-api/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ variable "otel_collector_grpc_port" {
default = 4317
}

variable "redis_url" {
type = string
sensitive = true
}

variable "redis_cluster_url" {
type = string
sensitive = true
}

variable "redis_tls_ca_base64" {
type = string
sensitive = true
default = ""
}

variable "logs_proxy_port" {
type = object({
name = string
Expand Down
3 changes: 3 additions & 0 deletions iac/provider-gcp/nomad/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ module "dashboard_api" {
auth_db_read_replica_connection_string = trimspace(data.google_secret_manager_secret_version.postgres_read_replica_connection_string.secret_data)
clickhouse_connection_string = local.clickhouse_connection_string
supabase_jwt_secrets = trimspace(data.google_secret_manager_secret_version.supabase_jwt_secrets.secret_data)
redis_url = local.redis_url
redis_cluster_url = local.redis_cluster_url
redis_tls_ca_base64 = trimspace(data.google_secret_manager_secret_version.redis_tls_ca_base64.secret_data)

otel_collector_grpc_port = var.otel_collector_grpc_port
logs_proxy_port = var.logs_proxy_port
Expand Down
2 changes: 1 addition & 1 deletion packages/api/internal/handlers/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func NewAPIStore(ctx context.Context, tel *telemetry.Client, redisClient redis.U
logger.L().Fatal(ctx, "Initializing Orchestrator client", zap.Error(err))
}

authCache := sharedauth.NewAuthCache[*types.Team]()
authCache := sharedauth.NewAuthCache[*types.Team](redisClient)
authStore := sharedauth.NewAuthStore(authDB)
authService := sharedauth.NewAuthService[*types.Team](authStore, authCache, config.SupabaseJWTSecrets)
templateCache := templatecache.NewTemplateCache(sqlcDB, redisClient)
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/oapi-codegen/gin-middleware v1.0.2
github.com/redis/go-redis/v9 v9.17.3
github.com/stretchr/testify v1.11.1
go.opentelemetry.io/otel v1.41.0
go.uber.org/zap v1.27.1
Expand Down Expand Up @@ -94,7 +95,6 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/redis/go-redis/v9 v9.17.3 // indirect
github.com/shirou/gopsutil/v4 v4.25.9 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/testcontainers/testcontainers-go v0.40.0 // indirect
Expand Down
34 changes: 18 additions & 16 deletions packages/auth/pkg/auth/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,34 @@ import (
"context"
"time"

"github.com/redis/go-redis/v9"

"github.com/e2b-dev/infra/packages/shared/pkg/cache"
)

const (
authInfoExpiration = 5 * time.Minute
refreshInterval = 1 * time.Minute
refreshTimeout = 30 * time.Second
callbackTimeout = 30 * time.Second

authCacheRedisPrefix = "auth:team"
)

// AuthCache is a generic TTL cache for authentication data (teams, users, etc.).
// AuthCache is a Redis-backed TTL cache for authentication data (teams, users, etc.).
type AuthCache[T any] struct {
cache *cache.MemoryCache[T]
cache *cache.RedisCache[T]
}

// NewAuthCache creates a new AuthCache with default TTL and refresh settings.
func NewAuthCache[T any]() *AuthCache[T] {
config := cache.Config[T]{
TTL: authInfoExpiration,
RefreshInterval: refreshInterval,
RefreshTimeout: refreshTimeout,
CallbackTimeout: callbackTimeout,
}

// NewAuthCache creates a new Redis-backed AuthCache with default TTL and refresh settings.
func NewAuthCache[T any](redisClient redis.UniversalClient) *AuthCache[T] {
return &AuthCache[T]{
cache: cache.NewMemoryCache(config),
cache: cache.NewRedisCache(cache.RedisConfig[T]{
RedisClient: redisClient,
TTL: authInfoExpiration,
RefreshInterval: refreshInterval,
RefreshTimeout: refreshTimeout,
RedisPrefix: authCacheRedisPrefix,
}),
}
}

Expand All @@ -39,11 +41,11 @@ func (c *AuthCache[T]) GetOrSet(ctx context.Context, key string, dataCallback fu
}

// Invalidate removes a single entry from the cache by key.
func (c *AuthCache[T]) Invalidate(key string) {
c.cache.Delete(key)
func (c *AuthCache[T]) Invalidate(ctx context.Context, key string) {
c.cache.Delete(ctx, key)
}

// Close stops the cache's background refresh goroutines.
// Close is a no-op for the Redis-backed cache (no background goroutines).
func (c *AuthCache[T]) Close(ctx context.Context) error {
return c.cache.Close(ctx)
}
6 changes: 3 additions & 3 deletions packages/auth/pkg/auth/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ func (s *AuthService[T]) ValidateSupabaseTeam(ctx context.Context, ginCtx *gin.C

// InvalidateTeamMemberCache removes the cached auth entry for a specific user-team pair.
// This should be called when team membership changes (member added or removed).
func (s *AuthService[T]) InvalidateTeamMemberCache(userID uuid.UUID, teamID string) {
s.teamCache.Invalidate(supabaseTeamCacheKey(userID, teamID))
func (s *AuthService[T]) InvalidateTeamMemberCache(ctx context.Context, userID uuid.UUID, teamID string) {
s.teamCache.Invalidate(ctx, supabaseTeamCacheKey(userID, teamID))
}

// InvalidateTeamCache queries the team's API key hashes and removes their cached entries.
Expand All @@ -212,7 +212,7 @@ func (s *AuthService[T]) InvalidateTeamCache(ctx context.Context, teamID uuid.UU
}

for _, hash := range hashes {
s.teamCache.Invalidate(hash)
s.teamCache.Invalidate(ctx, hash)
}

return nil
Expand Down
2 changes: 2 additions & 0 deletions packages/dashboard-api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/pressly/goose/v3 v3.26.0 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.17.3 // indirect
github.com/redis/go-redis/extra/redisotel/v9 v9.17.3 // indirect
github.com/redis/go-redis/v9 v9.17.3 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions packages/dashboard-api/go.sum

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

10 changes: 10 additions & 0 deletions packages/dashboard-api/internal/cfg/model.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cfg

import (
"fmt"

"github.com/caarlos0/env/v11"
)

Expand All @@ -12,6 +14,10 @@ type Config struct {

AuthDBConnectionString string `env:"AUTH_DB_CONNECTION_STRING"`
AuthDBReadReplicaConnectionString string `env:"AUTH_DB_READ_REPLICA_CONNECTION_STRING"`

RedisURL string `env:"REDIS_URL"`
RedisClusterURL string `env:"REDIS_CLUSTER_URL"`
RedisTLSCABase64 string `env:"REDIS_TLS_CA_BASE64"`
}

func Parse() (Config, error) {
Expand All @@ -22,5 +28,9 @@ func Parse() (Config, error) {
config.AuthDBConnectionString = config.PostgresConnectionString
}

if err == nil && config.RedisURL == "" && config.RedisClusterURL == "" {
err = fmt.Errorf("at least one of REDIS_URL or REDIS_CLUSTER_URL must be set")
}

return config, err
}
4 changes: 2 additions & 2 deletions packages/dashboard-api/internal/handlers/team_members.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (s *APIStore) PostTeamsTeamIDMembers(c *gin.Context, teamID api.TeamID) {
return
}

s.authService.InvalidateTeamMemberCache(user.ID, teamInfo.Team.ID.String())
s.authService.InvalidateTeamMemberCache(ctx, user.ID, teamInfo.Team.ID.String())

c.Status(http.StatusCreated)
}
Expand Down Expand Up @@ -189,7 +189,7 @@ func (s *APIStore) DeleteTeamsTeamIDMembersUserId(c *gin.Context, teamID api.Tea
return
}

s.authService.InvalidateTeamMemberCache(userId, teamInfo.Team.ID.String())
s.authService.InvalidateTeamMemberCache(ctx, userId, teamInfo.Team.ID.String())

c.Status(http.StatusNoContent)
}
17 changes: 16 additions & 1 deletion packages/dashboard-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
authdb "github.com/e2b-dev/infra/packages/db/pkg/auth"
"github.com/e2b-dev/infra/packages/db/pkg/pool"
e2benv "github.com/e2b-dev/infra/packages/shared/pkg/env"
"github.com/e2b-dev/infra/packages/shared/pkg/factories"
"github.com/e2b-dev/infra/packages/shared/pkg/logger"
sharedmiddleware "github.com/e2b-dev/infra/packages/shared/pkg/middleware"
"github.com/e2b-dev/infra/packages/shared/pkg/telemetry"
Expand Down Expand Up @@ -140,7 +141,21 @@ func run() int {
defer clickhouseClient.Close(ctx)
}

authCache := sharedauth.NewAuthCache[*types.Team]()
redisClient, err := factories.NewRedisClient(ctx, factories.RedisConfig{
RedisURL: config.RedisURL,
RedisClusterURL: config.RedisClusterURL,
RedisTLSCABase64: config.RedisTLSCABase64,
})
if err != nil {
l.Fatal(ctx, "Initializing Redis client", zap.Error(err))
}
defer func() {
if err := factories.CloseCleanly(redisClient); err != nil {
l.Error(ctx, "Failed to close Redis client", zap.Error(err))
}
}()

authCache := sharedauth.NewAuthCache[*types.Team](redisClient)
authStore := sharedauth.NewAuthStore(authDB)
authService := sharedauth.NewAuthService[*types.Team](authStore, authCache, config.SupabaseJWTSecrets)
defer authService.Close(ctx)
Expand Down
Loading