summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2024-05-06 20:32:35 +0300
committerPaul Buetow <paul@buetow.org>2024-05-06 20:32:35 +0300
commit8c2e75df51d1a74d8bca1d3d1a423f777159ba82 (patch)
treeb340984869230f92d0aea54d104efc5618c54954
parentd06809e50aa20b7f2e12ed43374aebb39e77a220 (diff)
refactor project file structure
-rw-r--r--Taskfile.yml19
-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.go36
-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)
diff --git a/io.go b/internal/io.go
index 4bf795f..c0f28bf 100644
--- a/io.go
+++ b/internal/io.go
@@ -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)
}