From ce5505de0b10da2af6658ef9405e734b2ee6e935 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Fri, 14 Feb 2025 13:29:47 -0500 Subject: [PATCH] Services are in a map now --- pkg/calls/callstore/store.go | 5 ++- pkg/database/database.go | 6 ++- pkg/incidents/incstore/store.go | 5 ++- pkg/rbac/rbac.go | 5 ++- pkg/server/server.go | 4 ++ pkg/services/services.go | 66 +++++++++++++++++++++++++++++++++ pkg/shares/store.go | 5 ++- pkg/talkgroups/tgstore/store.go | 5 ++- pkg/users/store.go | 5 ++- 9 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 pkg/services/services.go diff --git a/pkg/calls/callstore/store.go b/pkg/calls/callstore/store.go index 84b5bc7..d446b52 100644 --- a/pkg/calls/callstore/store.go +++ b/pkg/calls/callstore/store.go @@ -12,6 +12,7 @@ import ( "dynatron.me/x/stillbox/pkg/database" "dynatron.me/x/stillbox/pkg/rbac" "dynatron.me/x/stillbox/pkg/rbac/entities" + "dynatron.me/x/stillbox/pkg/services" "dynatron.me/x/stillbox/pkg/talkgroups/tgstore" "dynatron.me/x/stillbox/pkg/users" @@ -55,11 +56,11 @@ type storeCtxKey string const StoreCtxKey storeCtxKey = "store" func CtxWithStore(ctx context.Context, s Store) context.Context { - return context.WithValue(ctx, StoreCtxKey, s) + return services.WithValue(ctx, StoreCtxKey, s) } func FromCtx(ctx context.Context) Store { - s, ok := ctx.Value(StoreCtxKey).(Store) + s, ok := services.Value(ctx, StoreCtxKey).(Store) if !ok { panic("no call store in context") } diff --git a/pkg/database/database.go b/pkg/database/database.go index 874ab30..bf28295 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -7,6 +7,7 @@ import ( "strings" "dynatron.me/x/stillbox/pkg/config" + "dynatron.me/x/stillbox/pkg/services" sqlembed "dynatron.me/x/stillbox/sql" "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/pgx/v5" @@ -144,7 +145,8 @@ const DBCtxKey dBCtxKey = "dbctx" // FromCtx returns the database handle from the provided Context. func FromCtx(ctx context.Context) Store { - c, ok := ctx.Value(DBCtxKey).(Store) + sv := services.Value(ctx, DBCtxKey) + c, ok := sv.(Store) if !ok { panic("no DB in context") } @@ -154,7 +156,7 @@ func FromCtx(ctx context.Context) Store { // CtxWithDB returns a Context with the provided database handle. func CtxWithDB(ctx context.Context, conn Store) context.Context { - return context.WithValue(ctx, DBCtxKey, conn) + return services.WithValue(ctx, DBCtxKey, conn) } // IsNoRows is a convenience function that returns whether a returned error is a database diff --git a/pkg/incidents/incstore/store.go b/pkg/incidents/incstore/store.go index 81ce14d..5bddd5c 100644 --- a/pkg/incidents/incstore/store.go +++ b/pkg/incidents/incstore/store.go @@ -11,6 +11,7 @@ import ( "dynatron.me/x/stillbox/pkg/incidents" "dynatron.me/x/stillbox/pkg/rbac" "dynatron.me/x/stillbox/pkg/rbac/entities" + "dynatron.me/x/stillbox/pkg/services" "dynatron.me/x/stillbox/pkg/talkgroups" "dynatron.me/x/stillbox/pkg/users" "github.com/google/uuid" @@ -67,11 +68,11 @@ type storeCtxKey string const StoreCtxKey storeCtxKey = "store" func CtxWithStore(ctx context.Context, s Store) context.Context { - return context.WithValue(ctx, StoreCtxKey, s) + return services.WithValue(ctx, StoreCtxKey, s) } func FromCtx(ctx context.Context) Store { - s, ok := ctx.Value(StoreCtxKey).(Store) + s, ok := services.Value(ctx, StoreCtxKey).(Store) if !ok { return NewStore() } diff --git a/pkg/rbac/rbac.go b/pkg/rbac/rbac.go index c443da5..9604bc2 100644 --- a/pkg/rbac/rbac.go +++ b/pkg/rbac/rbac.go @@ -5,6 +5,7 @@ import ( "errors" "dynatron.me/x/stillbox/pkg/rbac/entities" + "dynatron.me/x/stillbox/pkg/services" "github.com/el-mike/restrict/v2" "github.com/el-mike/restrict/v2/adapters" @@ -33,7 +34,7 @@ type rbacCtxKey string const RBACCtxKey rbacCtxKey = "rbac" func FromCtx(ctx context.Context) RBAC { - rbac, ok := ctx.Value(RBACCtxKey).(RBAC) + rbac, ok := services.Value(ctx, RBACCtxKey).(RBAC) if !ok { panic("no RBAC in context") } @@ -42,7 +43,7 @@ func FromCtx(ctx context.Context) RBAC { } func CtxWithRBAC(ctx context.Context, rbac RBAC) context.Context { - return context.WithValue(ctx, RBACCtxKey, rbac) + return services.WithValue(ctx, RBACCtxKey, rbac) } var ( diff --git a/pkg/server/server.go b/pkg/server/server.go index a2553d7..e8a5803 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -19,6 +19,7 @@ import ( "dynatron.me/x/stillbox/pkg/rbac" "dynatron.me/x/stillbox/pkg/rbac/policy" "dynatron.me/x/stillbox/pkg/rest" + "dynatron.me/x/stillbox/pkg/services" "dynatron.me/x/stillbox/pkg/shares" "dynatron.me/x/stillbox/pkg/sinks" "dynatron.me/x/stillbox/pkg/sources" @@ -158,6 +159,9 @@ func New(ctx context.Context, cfg *config.Configuration) (*Server, error) { } func (s *Server) fillCtx(ctx context.Context) context.Context { + svc := services.New() + ctx = services.CtxWith(ctx, svc) + ctx = database.CtxWithDB(ctx, s.db) ctx = tgstore.CtxWithStore(ctx, s.tgs) ctx = users.CtxWithStore(ctx, s.users) diff --git a/pkg/services/services.go b/pkg/services/services.go new file mode 100644 index 0000000..9288bf1 --- /dev/null +++ b/pkg/services/services.go @@ -0,0 +1,66 @@ +// Package services avoids having to wrap contexts so much for multiple services. +package services + +import ( + "context" + "sync" +) + +type Services interface { + Set(key, val any) + Value(key any) any +} + +type services struct { + sync.RWMutex + m map[any]any +} + +func New() Services { + return &services{ + m: make(map[any]any), + } +} + +func CtxWith(ctx context.Context, svc Services) context.Context { + return context.WithValue(ctx, ServiceKey, svc) +} + +func (s *services) Value(key any) any { + s.RLock() + defer s.RUnlock() + + return s.m[key] +} + +func (s *services) Set(key, val any) { + s.Lock() + defer s.Unlock() + + s.m[key] = val +} + +type serviceKey string + +const ServiceKey serviceKey = "service" + +func WithValue(ctx context.Context, key, val any) context.Context { + v := ctx.Value(ServiceKey) + if v == nil { + return context.WithValue(ctx, key, val) + } + + sv := v.(Services) + sv.Set(key, val) + + return ctx +} + +func Value(ctx context.Context, key any) any { + sv := ctx.Value(ServiceKey) + if sv == nil { + return ctx.Value(key) + } + + return sv.(Services).Value(key) +} diff --git a/pkg/shares/store.go b/pkg/shares/store.go index f44c524..0f3308e 100644 --- a/pkg/shares/store.go +++ b/pkg/shares/store.go @@ -10,6 +10,7 @@ import ( "dynatron.me/x/stillbox/pkg/database" "dynatron.me/x/stillbox/pkg/rbac" "dynatron.me/x/stillbox/pkg/rbac/entities" + "dynatron.me/x/stillbox/pkg/services" "dynatron.me/x/stillbox/pkg/users" "github.com/jackc/pgx/v5" ) @@ -169,11 +170,11 @@ type storeCtxKey string const StoreCtxKey storeCtxKey = "store" func CtxWithStore(ctx context.Context, s Shares) context.Context { - return context.WithValue(ctx, StoreCtxKey, s) + return services.WithValue(ctx, StoreCtxKey, s) } func FromCtx(ctx context.Context) Shares { - s, ok := ctx.Value(StoreCtxKey).(Shares) + s, ok := services.Value(ctx, StoreCtxKey).(Shares) if !ok { panic("no shares store in context") } diff --git a/pkg/talkgroups/tgstore/store.go b/pkg/talkgroups/tgstore/store.go index b7dd472..bcad6da 100644 --- a/pkg/talkgroups/tgstore/store.go +++ b/pkg/talkgroups/tgstore/store.go @@ -13,6 +13,7 @@ import ( "dynatron.me/x/stillbox/pkg/database" "dynatron.me/x/stillbox/pkg/rbac" "dynatron.me/x/stillbox/pkg/rbac/entities" + "dynatron.me/x/stillbox/pkg/services" tgsp "dynatron.me/x/stillbox/pkg/talkgroups" "dynatron.me/x/stillbox/pkg/users" @@ -172,11 +173,11 @@ type storeCtxKey string const StoreCtxKey storeCtxKey = "store" func CtxWithStore(ctx context.Context, s Store) context.Context { - return context.WithValue(ctx, StoreCtxKey, s) + return services.WithValue(ctx, StoreCtxKey, s) } func FromCtx(ctx context.Context) Store { - s, ok := ctx.Value(StoreCtxKey).(Store) + s, ok := services.Value(ctx, StoreCtxKey).(Store) if !ok { panic("no tg store in context") } diff --git a/pkg/users/store.go b/pkg/users/store.go index 5722ab2..7326429 100644 --- a/pkg/users/store.go +++ b/pkg/users/store.go @@ -6,6 +6,7 @@ import ( "dynatron.me/x/stillbox/internal/cache" "dynatron.me/x/stillbox/pkg/database" + "dynatron.me/x/stillbox/pkg/services" ) var ( @@ -49,11 +50,11 @@ type storeCtxKey string const StoreCtxKey storeCtxKey = "store" func CtxWithStore(ctx context.Context, s Store) context.Context { - return context.WithValue(ctx, StoreCtxKey, s) + return services.WithValue(ctx, StoreCtxKey, s) } func FromCtx(ctx context.Context) Store { - s, ok := ctx.Value(StoreCtxKey).(Store) + s, ok := services.Value(ctx, StoreCtxKey).(Store) if !ok { panic("no users store in context") }