diff --git a/.gitignore b/.gitignore index 1eae0cf..2689316 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ dist/ node_modules/ + +*.local* diff --git a/main.go b/main.go index ccebd2a..593d249 100644 --- a/main.go +++ b/main.go @@ -20,8 +20,65 @@ func main() { log.Fatal(server.ListenAndServe()) } +type Store interface { + Count() (int, error) + Increment() (int, error) + Decrement() (int, error) +} + +const StoreFilename = "store.local.json" + +type fileStore struct { + Counter int `json:"counter"` +} + +func (db *fileStore) Count() (int, error) { + if err := readOrCreateJson(StoreFilename, db); err != nil { + return 0, err + } + + return db.Counter, nil +} + +func (db *fileStore) Increment() (int, error) { + if err := readOrCreateJson(StoreFilename, db); err != nil { + return 0, err + } + + db.Counter++ + + if err := writeJson(StoreFilename, db); err != nil { + return 0, err + } + + return db.Counter, nil +} + +func (db *fileStore) Decrement() (int, error) { + if err := readOrCreateJson(StoreFilename, db); err != nil { + return 0, err + } + + db.Counter-- + + if err := writeJson(StoreFilename, db); err != nil { + return 0, err + } + + return db.Counter, nil +} + func setupRoutes(mux *http.ServeMux) { - counter := 0 + var db Store = &fileStore{Counter: 0} + { + initialCount, err := db.Count() + if err != nil { + log.Fatalf(`Unable to create store: %v`, err) + return + } + + log.Printf(`Store correctly initialized, count: %v`, initialCount) + } // API Routes @@ -46,12 +103,17 @@ func setupRoutes(mux *http.ServeMux) { return } - w.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(w).Encode(counter) + count, err := db.Count() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(count); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } }) mux.HandleFunc("/api/increment", func(w http.ResponseWriter, r *http.Request) { @@ -60,11 +122,14 @@ func setupRoutes(mux *http.ServeMux) { return } - counter++ + newCount, err := db.Increment() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } w.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(w).Encode(counter) - if err != nil { + if err := json.NewEncoder(w).Encode(newCount); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -76,11 +141,14 @@ func setupRoutes(mux *http.ServeMux) { return } - counter-- + newCount, err := db.Decrement() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } w.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(w).Encode(counter) - if err != nil { + if err := json.NewEncoder(w).Encode(newCount); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..150e991 --- /dev/null +++ b/utils.go @@ -0,0 +1,40 @@ +package main + +import ( + "encoding/json" + "os" +) + +func readOrCreateJson(filename string, value any) error { + f, err := os.Open(filename) + if err != nil { + if os.IsNotExist(err) { + return writeJson(filename, value) + } + + return err + } + defer f.Close() + + if json.NewDecoder(f).Decode(value); err != nil { + return err + } + + return nil +} + +func writeJson(filename string, value any) error { + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + enc := json.NewEncoder(f) + enc.SetIndent("", " ") + if err := enc.Encode(value); err != nil { + return err + } + + return nil +}