refactor: Use functional options pattern for NewPageServer

This commit is contained in:
dragon
2026-01-29 13:44:00 +08:00
parent cd573483ea
commit 4fdb77c833
4 changed files with 119 additions and 36 deletions

View File

@@ -71,19 +71,25 @@ func main() {
zap.L().Fatal("failed to init memory provider", zap.Error(err)) zap.L().Fatal("failed to init memory provider", zap.Error(err))
} }
subscriber := subscribe.NewMemorySubscriber() subscriber := subscribe.NewMemorySubscriber()
server, err := pkg.NewPageServer(http.DefaultClient, server, err := pkg.NewPageServer(
provider, domain, memory, subscriber, memory, 0, &nopCache{}, 0, provider, domain, memory,
func(w http.ResponseWriter, r *http.Request, err error) { pkg.WithClient(http.DefaultClient),
pkg.WithEvent(subscriber),
pkg.WithMetaCache(memory, 0),
pkg.WithBlobCache(&nopCache{}, 0),
pkg.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
http.Error(w, "page not found.", http.StatusNotFound) http.Error(w, "page not found.", http.StatusNotFound)
} else if err != nil { } else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
}, map[string]map[string]any{ }),
pkg.WithFilterConfig(map[string]map[string]any{
"redirect": { "redirect": {
"scheme": "http", "scheme": "http",
}, },
}) }),
)
if err != nil { if err != nil {
zap.L().Fatal("failed to init page", zap.Error(err)) zap.L().Fatal("failed to init page", zap.Error(err))
} }

View File

@@ -74,17 +74,15 @@ func main() {
config.Filters = make(map[string]map[string]any) config.Filters = make(map[string]map[string]any)
} }
pageServer, err := pkg.NewPageServer( pageServer, err := pkg.NewPageServer(
http.DefaultClient,
backend, backend,
config.Domain, config.Domain,
cdb, cdb,
event, pkg.WithClient(http.DefaultClient),
cacheMeta, pkg.WithEvent(event),
config.Cache.MetaTTL, pkg.WithMetaCache(cacheMeta, config.Cache.MetaTTL),
cacheBlob.Child("filter"), pkg.WithBlobCache(cacheBlob.Child("filter"), config.Cache.BlobTTL),
config.Cache.BlobTTL, pkg.WithErrorHandler(config.ErrorHandler),
config.ErrorHandler, pkg.WithFilterConfig(config.Filters),
config.Filters,
) )
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)

View File

@@ -40,27 +40,108 @@ type Server struct {
errorHandler func(w http.ResponseWriter, r *http.Request, err error) errorHandler func(w http.ResponseWriter, r *http.Request, err error)
} }
type serverConfig struct {
client *http.Client
event subscribe.Subscriber
cacheMeta kv.KV
cacheMetaTTL time.Duration
cacheBlob cache.Cache
cacheBlobTTL time.Duration
errorHandler func(w http.ResponseWriter, r *http.Request, err error)
filterConfig map[string]map[string]any
}
type ServerOption func(*serverConfig)
func WithClient(client *http.Client) ServerOption {
return func(c *serverConfig) {
c.client = client
}
}
func WithEvent(event subscribe.Subscriber) ServerOption {
return func(c *serverConfig) {
c.event = event
}
}
func WithMetaCache(cache kv.KV, ttl time.Duration) ServerOption {
return func(c *serverConfig) {
c.cacheMeta = cache
c.cacheMetaTTL = ttl
}
}
func WithBlobCache(cache cache.Cache, ttl time.Duration) ServerOption {
return func(c *serverConfig) {
c.cacheBlob = cache
c.cacheBlobTTL = ttl
}
}
func WithErrorHandler(handler func(w http.ResponseWriter, r *http.Request, err error)) ServerOption {
return func(c *serverConfig) {
c.errorHandler = handler
}
}
func WithFilterConfig(config map[string]map[string]any) ServerOption {
return func(c *serverConfig) {
c.filterConfig = config
}
}
func NewPageServer( func NewPageServer(
client *http.Client,
backend core.Backend, backend core.Backend,
domain string, domain string,
db kv.CursorPagedKV, db kv.CursorPagedKV,
event subscribe.Subscriber, opts ...ServerOption,
cacheMeta kv.KV,
cacheMetaTTL time.Duration,
cacheBlob cache.Cache,
cacheBlobTTL time.Duration,
errorHandler func(w http.ResponseWriter, r *http.Request, err error),
filterConfig map[string]map[string]any,
) (*Server, error) { ) (*Server, error) {
cfg := &serverConfig{
client: http.DefaultClient,
filterConfig: make(map[string]map[string]any),
}
for _, opt := range opts {
opt(cfg)
}
if cfg.event == nil {
cfg.event = subscribe.NewMemorySubscriber()
}
if cfg.cacheMeta == nil {
var err error
cfg.cacheMeta, err = kv.NewMemory("")
if err != nil {
return nil, err
}
}
if cfg.cacheBlob == nil {
var err error
cfg.cacheBlob, err = cache.NewMemoryCache(cache.MemoryCacheConfig{
MaxCapacity: 128,
CleanupInt: time.Minute,
})
if err != nil {
return nil, err
}
}
if cfg.errorHandler == nil {
cfg.errorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
alias := core.NewDomainAlias(db.Child("config", "alias")) alias := core.NewDomainAlias(db.Child("config", "alias"))
svcMeta := core.NewServerMeta(client, backend, domain, alias, cacheMeta, cacheMetaTTL) svcMeta := core.NewServerMeta(cfg.client, backend, domain, alias, cfg.cacheMeta, cfg.cacheMetaTTL)
pageMeta := core.NewPageDomain(svcMeta, domain) pageMeta := core.NewPageDomain(svcMeta, domain)
globCache, err := lru.New[string, glob.Glob](512) globCache, err := lru.New[string, glob.Glob](512)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defaultFilters, err := filters.DefaultFilters(filterConfig) defaultFilters, err := filters.DefaultFilters(cfg.filterConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -70,10 +151,10 @@ func NewPageServer(
db: db, db: db,
globCache: globCache, globCache: globCache,
filterMgr: defaultFilters, filterMgr: defaultFilters,
errorHandler: errorHandler, errorHandler: cfg.errorHandler,
cacheBlob: cacheBlob, cacheBlob: cfg.cacheBlob,
cacheBlobTTL: cacheBlobTTL, cacheBlobTTL: cfg.cacheBlobTTL,
event: event, event: cfg.event,
}, nil }, nil
} }

View File

@@ -48,23 +48,21 @@ func NewTestServer(domain string) *TestServer {
}) })
memoryKV, _ := kv.NewMemory("") memoryKV, _ := kv.NewMemory("")
server, err := pkg.NewPageServer( server, err := pkg.NewPageServer(
http.DefaultClient,
dummy, dummy,
domain, domain,
memoryKV, memoryKV,
subscribe.NewMemorySubscriber(), pkg.WithClient(http.DefaultClient),
memoryKV.Child("cache"), pkg.WithEvent(subscribe.NewMemorySubscriber()),
0, pkg.WithMetaCache(memoryKV.Child("cache"), 0),
memoryCache, pkg.WithBlobCache(memoryCache, 0),
0, pkg.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
func(w http.ResponseWriter, r *http.Request, err error) {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
http.Error(w, "page not found.", http.StatusNotFound) http.Error(w, "page not found.", http.StatusNotFound)
} else if err != nil { } else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
}, }),
make(map[string]map[string]any), pkg.WithFilterConfig(make(map[string]map[string]any)),
) )
if err != nil { if err != nil {
panic(err) panic(err)