diff options
| author | Paul Buetow <paul@buetow.org> | 2024-05-06 20:32:35 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2024-05-06 20:32:35 +0300 |
| commit | 8c2e75df51d1a74d8bca1d3d1a423f777159ba82 (patch) | |
| tree | b340984869230f92d0aea54d104efc5618c54954 | |
| parent | d06809e50aa20b7f2e12ed43374aebb39e77a220 (diff) | |
refactor project file structure
| -rw-r--r-- | Taskfile.yml | 19 | ||||
| -rw-r--r-- | cmd/gosd/main.go (renamed from main.go) | 25 | ||||
| -rw-r--r-- | internal/io.go (renamed from io.go) | 4 | ||||
| -rw-r--r-- | internal/server/handle/handle.go (renamed from handlers.go) | 24 | ||||
| -rw-r--r-- | internal/server/health/health.go (renamed from health.go) | 42 | ||||
| -rw-r--r-- | internal/server/health/health_test.go (renamed from health_test.go) | 14 | ||||
| -rw-r--r-- | internal/server/repository/repository.go | 36 | ||||
| -rw-r--r-- | internal/types/entry.go (renamed from entry.go) | 20 |
8 files changed, 124 insertions, 60 deletions
diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..4363202 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,19 @@ +version: '3' + +tasks: + build: + cmds: + - go build -o gosd cmd/gosd/main.go + dev: + deps: ["vet", "lint"] + cmds: + - go build -race -o gosd cmd/gosd/main.go + vet: + cmds: + - go vet **/*.go + lint: + cmds: + - golangci-lint run + lint-install: + cmds: + - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest diff --git a/main.go b/cmd/gosd/main.go index f4a3e5c..8f43d3f 100644 --- a/main.go +++ b/cmd/gosd/main.go @@ -5,46 +5,49 @@ import ( "fmt" "log" "net/http" + + "codeberg.org/snonux/gos/internal/server/handle" + "codeberg.org/snonux/gos/internal/server/health" ) func main() { listenAddr := flag.String("listenAddr", "localhost:8080", "The listen address") dataDir := flag.String("dataDir", "data", "The data directory") - health := newHealthStatus() + hs := health.NewStatus() http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { log.Println("Someone requested /health") - fmt.Fprint(w, health.String()) + fmt.Fprint(w, hs.String()) }) http.HandleFunc("/submit", func(w http.ResponseWriter, r *http.Request) { log.Println("Someone requested /submit") - if err := handleSubmit(w, r, *dataDir); err != nil { + if err := handle.Submit(w, r, *dataDir); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) - health.set(critical, "submitHandler", err.Error()) + hs.Set(health.Critical, "submitHandler", err.Error()) return } - health.clear("submitHandler") + hs.Clear("submitHandler") }) http.HandleFunc("/list", func(w http.ResponseWriter, r *http.Request) { log.Println("Someone requested /list") - if err := handleList(w, r, *dataDir); err != nil { + if err := handle.List(w, r, *dataDir); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) - health.set(critical, "listHandler", err.Error()) + hs.Set(health.Critical, "listHandler", err.Error()) return } - health.clear("listHandler") + hs.Clear("listHandler") }) http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { log.Println("Someone requested /get") - if err := handleGet(w, r, *dataDir); err != nil { + if err := handle.Get(w, r, *dataDir); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) - health.set(critical, "getHandler", err.Error()) + hs.Set(health.Critical, "getHandler", err.Error()) return } - health.clear("getHandler") + hs.Clear("getHandler") }) log.Println("Server is starting on ", *listenAddr) @@ -1,11 +1,11 @@ -package main +package internal import ( "os" "path/filepath" ) -func saveFile(filePath string, bytes []byte) error { +func SaveFile(filePath string, bytes []byte) error { dir := filepath.Dir(filePath) if _, err := os.Stat(dir); os.IsNotExist(err) { if err := os.MkdirAll(dir, 0755); err != nil { diff --git a/handlers.go b/internal/server/handle/handle.go index f293e9c..d1f7748 100644 --- a/handlers.go +++ b/internal/server/handle/handle.go @@ -1,4 +1,4 @@ -package main +package handle import ( "encoding/json" @@ -8,11 +8,15 @@ import ( "os" "regexp" "time" + + "codeberg.org/snonux/gos/internal" + "codeberg.org/snonux/gos/internal/server/repository" + "codeberg.org/snonux/gos/internal/types" ) var getIDRe = regexp.MustCompile(`^/[0-9]{4}/[a-z0-9]{64}\.json$`) -func handleSubmit(w http.ResponseWriter, r *http.Request, dataDir string) error { +func Submit(w http.ResponseWriter, r *http.Request, dataDir string) error { if r.Method != "POST" { return fmt.Errorf("expexted POST request") } @@ -22,31 +26,31 @@ func handleSubmit(w http.ResponseWriter, r *http.Request, dataDir string) error return err } - entry, err := newEntry(bytes) + entry, err := types.NewEntry(bytes) if err != nil { return err } - filePath := fmt.Sprintf("%s/%s/%s.json", dataDir, time.Now().Format("2006"), entry.id) + filePath := fmt.Sprintf("%s/%s/%s.json", dataDir, time.Now().Format("2006"), entry.ID) - jsonStr, err := entry.serialize() + jsonStr, err := entry.Serialize() if err != nil { return err } - if err := saveFile(filePath, jsonStr); err != nil { + if err := internal.SaveFile(filePath, jsonStr); err != nil { return err } return nil } -func handleList(w http.ResponseWriter, r *http.Request, dataDir string) error { +func List(w http.ResponseWriter, r *http.Request, dataDir string) error { if r.Method != "GET" { return fmt.Errorf("expexted GET request") } - repository := newRepository(dataDir) - ids, err := repository.list() + repository := repository.New(dataDir) + ids, err := repository.List() if err != nil { return err } @@ -60,7 +64,7 @@ func handleList(w http.ResponseWriter, r *http.Request, dataDir string) error { return nil } -func handleGet(w http.ResponseWriter, r *http.Request, dataDir string) error { +func Get(w http.ResponseWriter, r *http.Request, dataDir string) error { path := r.URL.Query().Get("path") if !getIDRe.MatchString(path) { return fmt.Errorf("invalid path %s", path) diff --git a/health.go b/internal/server/health/health.go index 0ab9ba1..d87bd3d 100644 --- a/health.go +++ b/internal/server/health/health.go @@ -1,4 +1,4 @@ -package main +package health import ( "fmt" @@ -7,51 +7,51 @@ import ( "sync" ) -type alertSeverity int +type Severity int const ( - ok alertSeverity = iota - warning - critical - unknown + OK Severity = iota + Warning + Critical + Unknown ) -func (s alertSeverity) String() string { +func (s Severity) String() string { switch s { - case ok: + case OK: return "OK" - case warning: + case Warning: return "WARNING" - case critical: + case Critical: return "CRITICAL" - case unknown: - return "UNKNOWN" + case Unknown: + fallthrough default: - panic("encountered an unknown alertSeverity") + return "UNKNOWN" } } type alert struct { text string - severity alertSeverity + severity Severity } func (a alert) String() string { return fmt.Sprintf("%s: %s", a.severity, a.text) } -type healthStatus struct { +type Status struct { alerts map[string]alert mu sync.Mutex } -func newHealthStatus() healthStatus { - return healthStatus{ +func NewStatus() Status { + return Status{ alerts: make(map[string]alert), } } -func (hs healthStatus) set(s alertSeverity, what, text string) { +func (hs Status) Set(s Severity, what, text string) { log.Println("alerting", what, "to", text, "with severity", s) hs.mu.Lock() @@ -63,7 +63,7 @@ func (hs healthStatus) set(s alertSeverity, what, text string) { } } -func (hs healthStatus) clear(what string) { +func (hs Status) Clear(what string) { hs.mu.Lock() defer hs.mu.Unlock() @@ -73,7 +73,7 @@ func (hs healthStatus) clear(what string) { } } -func (hs healthStatus) String() string { +func (hs Status) String() string { var ( alerts [4][]string // Alerts by severity sb strings.Builder @@ -86,7 +86,7 @@ func (hs healthStatus) String() string { alerts[alert.severity] = append(alerts[alert.severity], alert.String()) } - possible := [4]alertSeverity{unknown, critical, warning, ok} + possible := [4]Severity{Unknown, Critical, Warning, OK} for _, severity := range possible { if len(alerts[severity]) == 0 { continue diff --git a/health_test.go b/internal/server/health/health_test.go index 8dc35bc..1723d42 100644 --- a/health_test.go +++ b/internal/server/health/health_test.go @@ -1,16 +1,16 @@ -package main +package health import "testing" func TestHealthStatus(t *testing.T) { t.Parallel() - h := newHealthStatus() - h.set(warning, "fooService", "this is not good") - h.set(critical, "barService", "this is not good either") - h.set(warning, "bazService", "urgh!") - h.set(unknown, "bazService", "don't know what happened here!") - h.clear("fooService") + h := NewStatus() + h.Set(warning, "fooService", "this is not good") + h.Set(critical, "barService", "this is not good either") + h.Set(warning, "bazService", "urgh!") + h.Set(unknown, "bazService", "don't know what happened here!") + h.Clear("fooService") result := h.String() expected := `UNKNOWN: don't know what happened here! diff --git a/internal/server/repository/repository.go b/internal/server/repository/repository.go new file mode 100644 index 0000000..5fe79fd --- /dev/null +++ b/internal/server/repository/repository.go @@ -0,0 +1,36 @@ +package repository + +import ( + "log" + "os" + "path/filepath" + "strings" +) + +type Repository struct { + dataDir string +} + +func New(dataDir string) Repository { + return Repository{dataDir} +} + +func (r Repository) List() ([]string, error) { + var ids []string + + visit := func(files *[]string) filepath.WalkFunc { + return func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Println(err) + return nil + } + if !info.IsDir() && strings.HasSuffix(path, ".json") { + *files = append(*files, strings.TrimPrefix(path, r.dataDir)) + } + return nil + } + } + + err := filepath.Walk(r.dataDir, visit(&ids)) + return ids, err +} diff --git a/entry.go b/internal/types/entry.go index a91e0b7..a274e2c 100644 --- a/entry.go +++ b/internal/types/entry.go @@ -1,4 +1,4 @@ -package main +package types import ( "crypto/sha256" @@ -6,27 +6,29 @@ import ( "fmt" ) -type shared struct { +type Shared struct { Name string `json:"id"` Is bool `json:"is,omitempty"` } -type entry struct { +type Entry struct { Body string `json:"body"` - Shared []shared `json:"shared,omitempty"` + Shared []Shared `json:"shared,omitempty"` Epoch int `json:"epoch,omitempty"` - id string + ID string `json:"id,omitempty"` } -func newEntry(bytes []byte) (entry, error) { - var entry entry +func NewEntry(bytes []byte) (Entry, error) { + var entry Entry if err := json.Unmarshal(bytes, &entry); err != nil { return entry, fmt.Errorf("unable to deserialise payload: %w", err) } - entry.id = fmt.Sprintf("%x", sha256.Sum256(bytes)) + if entry.ID == "" { + entry.ID = fmt.Sprintf("%x", sha256.Sum256(bytes)) + } return entry, nil } -func (e entry) serialize() ([]byte, error) { +func (e Entry) Serialize() ([]byte, error) { return json.Marshal(e) } |
