From 73423064a80f26196e4f304fdb9341c70ae07f9b Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Wed, 20 Mar 2019 10:00:19 -0600 Subject: [PATCH] Implement optional namespace for server --- notes/consistent_and_namespaces | 9 +++++++++ server/config/config.go | 13 +++++++------ server/config/new.go | 12 +++++++----- server/serve/routes.go | 27 +++++++++++++++++++-------- server/serve/routes_test.go | 15 +++++++++++++-- 5 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 notes/consistent_and_namespaces diff --git a/notes/consistent_and_namespaces b/notes/consistent_and_namespaces new file mode 100644 index 0000000..478afe7 --- /dev/null +++ b/notes/consistent_and_namespaces @@ -0,0 +1,9 @@ +a key goes to a consistent hash to determine a partition id. Look up the addr which holds that partition ID. +end:1 key -> client +client:1 key -> 1+ partitionID +client:1 partitionID -> serverAddr +client:partition,key,serverAddr -> server +server:partition,key -> value +1+ server:value -> client +client:1+ value -> 1 end:value + diff --git a/server/config/config.go b/server/config/config.go index c320baf..6a2a309 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -10,12 +10,13 @@ var config Config var lock = &sync.RWMutex{} type Config struct { - db string - DB storage.DB - Port string - Addr string - Username string - Password string + db string + DB storage.DB + Port string + Addr string + Username string + Password string + DefaultNamespace string } func Values() Config { diff --git a/server/config/new.go b/server/config/new.go index a8734e7..482f8e5 100644 --- a/server/config/new.go +++ b/server/config/new.go @@ -7,12 +7,14 @@ import ( func New() error { config = Config{ - db: orEnv(storage.MAP.String(), "DB", "DATABASE"), - Addr: orEnv("", "ADDR", "FILE"), - Username: orEnv("", "USER", "USERNAME"), - Password: orEnv("", "PASS", "PASSWORD"), - Port: orEnv("21412", "PORT", "LISTEN"), + db: orEnv(storage.MAP.String(), "DB", "DATABASE"), + Addr: orEnv("", "ADDR", "FILE"), + Username: orEnv("", "USER", "USERNAME"), + Password: orEnv("", "PASS", "PASSWORD"), + Port: orEnv("21412", "PORT", "LISTEN"), + DefaultNamespace: orEnv(storage.DefaultNamespace, "NS", "NAMESPACE"), } + storage.DefaultNamespace = config.DefaultNamespace DB, err := storage.New(storage.TypeFromString(config.db), config.Addr, config.Username, config.Password) config.DB = DB return err diff --git a/server/serve/routes.go b/server/serve/routes.go index 47cacd1..141728e 100644 --- a/server/serve/routes.go +++ b/server/serve/routes.go @@ -6,17 +6,26 @@ import ( "local/s2sa/s2sa/server/router" "local/storage" "net/http" + "path" "strings" ) func (s *Server) Routes() error { - if err := s.router.Add("/"+router.Wildcard, s.CatchAll); err != nil { + if err := s.router.Add("/"+router.Wildcard, s.SimpleCatchAll); err != nil { + return err + } + if err := s.router.Add("/"+router.Wildcard+"/"+router.Wildcard, s.NSCatchAll); err != nil { return err } return nil } -func (s *Server) CatchAll(w http.ResponseWriter, r *http.Request) { +func (s *Server) SimpleCatchAll(w http.ResponseWriter, r *http.Request) { + r.URL.Path = path.Join("/"+storage.DefaultNamespace, r.URL.Path) + s.NSCatchAll(w, r) +} + +func (s *Server) NSCatchAll(w http.ResponseWriter, r *http.Request) { foo := http.NotFound switch strings.ToLower(r.Method) { case "get": @@ -30,9 +39,10 @@ func (s *Server) CatchAll(w http.ResponseWriter, r *http.Request) { } func (s *Server) get(w http.ResponseWriter, r *http.Request) { - config := config.Values() - key := strings.Split(r.URL.Path, "/")[1] - if value, err := config.DB.Get(key); err == storage.ErrNotFound { + db := config.Values().DB + ns := strings.Split(r.URL.Path, "/")[1] + key := strings.Split(r.URL.Path, "/")[2] + if value, err := db.Get(key, ns); err == storage.ErrNotFound { w.WriteHeader(http.StatusNotFound) return } else if err != nil { @@ -44,8 +54,9 @@ func (s *Server) get(w http.ResponseWriter, r *http.Request) { } func (s *Server) put(w http.ResponseWriter, r *http.Request) { - config := config.Values() - key := strings.Split(r.URL.Path, "/")[1] + db := config.Values().DB + ns := strings.Split(r.URL.Path, "/")[1] + key := strings.Split(r.URL.Path, "/")[2] if r == nil || r.Body == nil { w.WriteHeader(http.StatusBadRequest) return @@ -55,7 +66,7 @@ func (s *Server) put(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) return } - if err := config.DB.Set(key, value); err != nil { + if err := db.Set(key, value, ns); err != nil { w.WriteHeader(http.StatusInternalServerError) return } diff --git a/server/serve/routes_test.go b/server/serve/routes_test.go index bd10975..8f7b397 100644 --- a/server/serve/routes_test.go +++ b/server/serve/routes_test.go @@ -10,6 +10,7 @@ import ( "testing" ) +var validNS = "ns" var validKey = "key" var validValue = "value" @@ -112,7 +113,7 @@ func TestPutGet(t *testing.T) { } w := httptest.NewRecorder() - r, err := http.NewRequest("PUT", "/"+validKey, strings.NewReader(validValue)) + r, err := http.NewRequest("PUT", "/"+validNS+"/"+validKey, strings.NewReader(validValue)) if err != nil { t.Fatalf("err making put request: %v", err) } @@ -122,7 +123,17 @@ func TestPutGet(t *testing.T) { } w = httptest.NewRecorder() - r, err = http.NewRequest("GET", "/"+validKey, nil) + r, err = http.NewRequest("GET", "/not_"+validNS+"/"+validKey, nil) + if err != nil { + t.Fatalf("err making get request: %v", err) + } + s.get(w, r) + if w.Code != http.StatusNotFound { + t.Fatalf("err status on bad get: %v", w.Code) + } + + w = httptest.NewRecorder() + r, err = http.NewRequest("GET", "/"+validNS+"/"+validKey, nil) if err != nil { t.Fatalf("err making get request: %v", err) }