Compare commits
No commits in common. "main" and "feat/routing" have entirely different histories.
main
...
feat/routi
14
go.mod
14
go.mod
@ -9,17 +9,17 @@ require (
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.3.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
|
15
go.sum
15
go.sum
@ -6,8 +6,6 @@ github.com/dgraph-io/badger/v4 v4.8.0 h1:JYph1ChBijCw8SLeybvPINizbDKWZ5n/GYbz2yh
|
||||
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI=
|
||||
github.com/dgraph-io/ristretto/v2 v2.3.0 h1:qTQ38m7oIyd4GAed/QkUZyPFNMnvVWyazGXRwvOt5zk=
|
||||
github.com/dgraph-io/ristretto/v2 v2.3.0/go.mod h1:gpoRV3VzrEY1a9dWAYV6T1U7YzfgttXdd/ZzL1s9OZM=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
@ -29,32 +27,19 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -1,13 +1,14 @@
|
||||
package routing
|
||||
package joist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HandlerFn func(w http.ResponseWriter, r *http.Request) error
|
||||
|
||||
type Middlewares []func(http.ResponseWriter, *http.Request)
|
||||
type (
|
||||
HandlerFn func(w http.ResponseWriter, r *http.Request) error
|
||||
MiddlewareFn func(HandlerFn) HandlerFn
|
||||
)
|
||||
|
||||
func (h HandlerFn) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if err := h(w, r); err != nil {
|
@ -1,4 +1,4 @@
|
||||
package storage
|
||||
package joist
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -12,3 +12,11 @@ type Storer interface {
|
||||
GetForPrefix(ctx context.Context, prefix string) (map[string][]byte, error)
|
||||
Put(ctx context.Context, key string, val []byte, ttl time.Duration) error
|
||||
}
|
||||
|
||||
type RouteCacher interface {
|
||||
Add(name string, path string) error
|
||||
AddRouteInfo(routeInfo RouteInfo) error
|
||||
GetPath(name string) (string, error)
|
||||
GetRouteInfo(name string) (RouteInfo, error)
|
||||
All() (map[string]string, error)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package storage
|
||||
package badger
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package storage
|
||||
package badger
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,26 +0,0 @@
|
||||
package routing
|
||||
|
||||
type RouteInfo struct {
|
||||
Method string
|
||||
Name string
|
||||
Path string
|
||||
Description string
|
||||
Title string
|
||||
}
|
||||
|
||||
func NewRouteInfo(method, path, description, title string) (*RouteInfo, error) {
|
||||
name, err := convertRouteToRouteName(path)
|
||||
if err != nil {
|
||||
return &RouteInfo{}, err
|
||||
}
|
||||
|
||||
return &RouteInfo{
|
||||
Method: method,
|
||||
Name: name,
|
||||
Path: path,
|
||||
Description: description,
|
||||
Title: title,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type routeInfoKey struct{}
|
@ -1,20 +0,0 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.markbailey.dev/cerbervs/joist/internal/errors"
|
||||
chi "github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
func NewRouter() *Router {
|
||||
ttl := 8 * time.Hour
|
||||
|
||||
cache, err := NewRouteCacheService(WithTTL(ttl))
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, errors.ErrRouterNotCreated))
|
||||
}
|
||||
|
||||
return &Router{Mux: chi.NewRouter(), cache: cache, cacheTTL: ttl}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package routing
|
||||
package joist
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -7,37 +7,37 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.markbailey.dev/cerbervs/joist/internal/badger"
|
||||
jerr "git.markbailey.dev/cerbervs/joist/internal/errors"
|
||||
"git.markbailey.dev/cerbervs/joist/internal/storage"
|
||||
)
|
||||
|
||||
type RouteCache struct {
|
||||
type routeCache struct {
|
||||
rs map[string]string
|
||||
ris map[string]*RouteInfo
|
||||
s storage.Storer
|
||||
s Storer
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
type RouteCacheOpt func(*RouteCache)
|
||||
type RouteCacheOpt func(*routeCache)
|
||||
|
||||
var (
|
||||
rcOnce sync.Once
|
||||
cache *RouteCache
|
||||
cache *routeCache
|
||||
)
|
||||
|
||||
func WithTTL(ttl time.Duration) RouteCacheOpt {
|
||||
return func(r *RouteCache) {
|
||||
return func(r *routeCache) {
|
||||
r.ttl = ttl
|
||||
}
|
||||
}
|
||||
|
||||
func WithStore(store storage.Storer) RouteCacheOpt {
|
||||
return func(r *RouteCache) {
|
||||
func WithStore(store Storer) RouteCacheOpt {
|
||||
return func(r *routeCache) {
|
||||
r.s = store
|
||||
}
|
||||
}
|
||||
|
||||
func NewRouteCacheService(opts ...RouteCacheOpt) (*RouteCache, error) {
|
||||
func NewRouteCacheService(opts ...RouteCacheOpt) (*routeCache, error) {
|
||||
rcOnce.Do(func() {
|
||||
c, err := newRouteCache(opts...)
|
||||
if err != nil {
|
||||
@ -54,14 +54,14 @@ func NewRouteCacheService(opts ...RouteCacheOpt) (*RouteCache, error) {
|
||||
return cache, nil
|
||||
}
|
||||
|
||||
func (r *RouteCache) All() (map[string]string, error) {
|
||||
func (r *routeCache) All() (map[string]string, error) {
|
||||
if r.rs == nil {
|
||||
return nil, jerr.ErrCacheUninitialized
|
||||
}
|
||||
return r.rs, nil
|
||||
}
|
||||
|
||||
func (r *RouteCache) Add(name string, path string) error {
|
||||
func (r *routeCache) Add(name string, path string) error {
|
||||
ttl := r.ttl
|
||||
if ttl == 0 {
|
||||
ttl = 1 * time.Hour
|
||||
@ -76,7 +76,7 @@ func (r *RouteCache) Add(name string, path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RouteCache) GetPath(name string) (string, error) {
|
||||
func (r *routeCache) GetPath(name string) (string, error) {
|
||||
if path, ok := r.rs[name]; ok {
|
||||
return path, nil
|
||||
}
|
||||
@ -88,7 +88,7 @@ func (r *RouteCache) GetPath(name string) (string, error) {
|
||||
return "", errors.New("route not found in cache")
|
||||
}
|
||||
|
||||
func (r *RouteCache) AddRouteInfo(routeInfo RouteInfo) error {
|
||||
func (r *routeCache) AddRouteInfo(routeInfo RouteInfo) error {
|
||||
ttl := r.ttl
|
||||
if ttl == 0 {
|
||||
ttl = 1 * time.Hour
|
||||
@ -113,7 +113,7 @@ func (r *RouteCache) AddRouteInfo(routeInfo RouteInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RouteCache) GetRouteInfo(name string) (RouteInfo, error) {
|
||||
func (r *routeCache) GetRouteInfo(name string) (RouteInfo, error) {
|
||||
if ri, ok := r.ris[name]; ok {
|
||||
return *ri, nil
|
||||
}
|
||||
@ -131,13 +131,13 @@ func (r *RouteCache) GetRouteInfo(name string) (RouteInfo, error) {
|
||||
return RouteInfo{}, errors.New("route info not found in cache")
|
||||
}
|
||||
|
||||
func newRouteCache(opts ...RouteCacheOpt) (*RouteCache, error) {
|
||||
s, err := storage.NewBadgerStore(storage.WithSubDir("route_cache"))
|
||||
func newRouteCache(opts ...RouteCacheOpt) (*routeCache, error) {
|
||||
s, err := badger.NewBadgerStore(badger.WithSubDir("route_cache"))
|
||||
if err != nil {
|
||||
return nil, jerr.Wrap(jerr.ErrFailedToCreateRouteCache, err)
|
||||
}
|
||||
|
||||
cache := &RouteCache{
|
||||
cache := &routeCache{
|
||||
rs: make(map[string]string),
|
||||
s: s,
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package routing
|
||||
package joist
|
||||
|
||||
import "testing"
|
||||
|
@ -1,29 +1,59 @@
|
||||
package routing
|
||||
package joist
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jerr "git.markbailey.dev/cerbervs/joist/internal/errors"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type RouteCacher interface {
|
||||
Add(string, string) error
|
||||
AddRouteInfo(RouteInfo) error
|
||||
GetPath(string) (string, error)
|
||||
GetRouteInfo(string) (RouteInfo, error)
|
||||
All() (map[string]string, error)
|
||||
type RouteInfo struct {
|
||||
Method string
|
||||
Name string
|
||||
Path string
|
||||
Description string
|
||||
Title string
|
||||
}
|
||||
|
||||
func NewRouteInfo(method, path, description, title string) (RouteInfo, error) {
|
||||
name, err := convertRouteToRouteName(path)
|
||||
if err != nil {
|
||||
return RouteInfo{}, err
|
||||
}
|
||||
|
||||
return RouteInfo{
|
||||
Method: method,
|
||||
Name: name,
|
||||
Path: path,
|
||||
Description: description,
|
||||
Title: title,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type routeInfoKey struct{}
|
||||
|
||||
type Router struct {
|
||||
*chi.Mux
|
||||
chi.Mux
|
||||
cache RouteCacher
|
||||
cacheTTL time.Duration
|
||||
}
|
||||
|
||||
func NewRouter() Router {
|
||||
ttl := 8 * time.Hour
|
||||
|
||||
cache, err := NewRouteCacheService(WithTTL(ttl))
|
||||
if err != nil {
|
||||
log.Fatal(jerr.Wrap(err, jerr.ErrRouterNotCreated))
|
||||
}
|
||||
|
||||
return Router{cache: cache, cacheTTL: ttl}
|
||||
}
|
||||
|
||||
func (ro *Router) WithRouteInfo(ri RouteInfo, h HandlerFn) http.HandlerFunc {
|
||||
ro.cache.AddRouteInfo(ri)
|
||||
|
Loading…
x
Reference in New Issue
Block a user