simgle package sync service

This commit is contained in:
Erik Winter 2024-09-08 10:09:54 +02:00
parent 74775ac244
commit 204c712cc6
9 changed files with 49 additions and 66 deletions

View File

@ -1,3 +1,3 @@
run:
PLANNER_PORT=8092 PLANNER_API_KEY=testKey go run .
PLANNER_PORT=8092 PLANNER_API_KEY=testKey go run ./sync-service/

View File

@ -1,17 +0,0 @@
package storage
import (
"errors"
"time"
"code.ewintr.nl/planner/planner"
)
var (
ErrNotFound = errors.New("not found")
)
type Syncer interface {
Update(item planner.Syncable) error
Updated(t time.Time) ([]planner.Syncable, error)
}

View File

@ -1,4 +1,4 @@
package handler
package main
import (
"encoding/json"
@ -9,18 +9,15 @@ import (
"path"
"strings"
"time"
"code.ewintr.nl/planner/planner"
"code.ewintr.nl/planner/storage"
)
type Server struct {
syncer storage.Syncer
syncer Syncer
apiKey string
logger *slog.Logger
}
func NewServer(syncer storage.Syncer, apiKey string, logger *slog.Logger) *Server {
func NewServer(syncer Syncer, apiKey string, logger *slog.Logger) *Server {
return &Server{
syncer: syncer,
apiKey: apiKey,
@ -87,7 +84,7 @@ func (s *Server) SyncPost(w http.ResponseWriter, r *http.Request) {
}
defer r.Body.Close()
var items []planner.Syncable
var items []Syncable
if err := json.Unmarshal(body, &items); err != nil {
http.Error(w, fmtError(err), http.StatusBadRequest)
return

View File

@ -1,4 +1,4 @@
package handler_test
package main
import (
"bytes"
@ -13,17 +13,13 @@ import (
"sort"
"testing"
"time"
"code.ewintr.nl/planner/handler"
"code.ewintr.nl/planner/planner"
"code.ewintr.nl/planner/storage"
)
func TestServerServeHTTP(t *testing.T) {
t.Parallel()
apiKey := "test"
srv := handler.NewServer(storage.NewMemory(), apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
srv := NewServer(NewMemory(), apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
for _, tc := range []struct {
name string
@ -57,9 +53,9 @@ func TestSyncGet(t *testing.T) {
t.Parallel()
now := time.Now()
mem := storage.NewMemory()
mem := NewMemory()
items := []planner.Syncable{
items := []Syncable{
{ID: "id-0", Updated: now.Add(-10 * time.Minute)},
{ID: "id-1", Updated: now.Add(-5 * time.Minute)},
{ID: "id-2", Updated: now.Add(time.Minute)},
@ -72,13 +68,13 @@ func TestSyncGet(t *testing.T) {
}
apiKey := "test"
srv := handler.NewServer(mem, apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
srv := NewServer(mem, apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
for _, tc := range []struct {
name string
ts time.Time
expStatus int
expItems []planner.Syncable
expItems []Syncable
}{
{
name: "full",
@ -89,7 +85,7 @@ func TestSyncGet(t *testing.T) {
name: "normal",
ts: now.Add(-6 * time.Minute),
expStatus: http.StatusOK,
expItems: []planner.Syncable{items[1], items[2]},
expItems: []Syncable{items[1], items[2]},
},
} {
t.Run(tc.name, func(t *testing.T) {
@ -105,7 +101,7 @@ func TestSyncGet(t *testing.T) {
if res.Result().StatusCode != tc.expStatus {
t.Errorf("exp %v, got %v", tc.expStatus, res.Result().StatusCode)
}
var actItems []planner.Syncable
var actItems []Syncable
actBody, err := io.ReadAll(res.Result().Body)
if err != nil {
t.Errorf("exp nil, got %v", err)
@ -139,7 +135,7 @@ func TestSyncPost(t *testing.T) {
name string
reqBody []byte
expStatus int
expItems []planner.Syncable
expItems []Syncable
}{
{
name: "empty",
@ -157,15 +153,15 @@ func TestSyncPost(t *testing.T) {
{"ID":"id-2","Updated":"2024-09-06T08:12:00Z","Deleted":false,"Item":""}
]`),
expStatus: http.StatusNoContent,
expItems: []planner.Syncable{
expItems: []Syncable{
{ID: "id-1", Updated: time.Date(2024, 9, 6, 8, 0, 0, 0, time.UTC)},
{ID: "id-2", Updated: time.Date(2024, 9, 6, 12, 0, 0, 0, time.UTC)},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
mem := storage.NewMemory()
srv := handler.NewServer(mem, apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
mem := NewMemory()
srv := NewServer(mem, apiKey, slog.New(slog.NewJSONHandler(os.Stdout, nil)))
req, err := http.NewRequest(http.MethodPost, "/sync", bytes.NewBuffer(tc.reqBody))
if err != nil {
t.Errorf("exp nil, got %v", err)
@ -205,9 +201,9 @@ func TestSyncHandler(t *testing.T) {
name string
items []item
method string
body handler.ChangeSummary
body .ChangeSummary
expStatus int
expBody handler.ChangeSummary
expBody .ChangeSummary
}{
{
name: "empty",
@ -218,11 +214,11 @@ func TestSyncHandler(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
mem := storage.NewMemory()
mem := NewMemory()
for _, i := range tc.items {
mem.Update(i)
}
sh := handler.NewSyncHandler(mem)
sh := .NewSyncHandler(mem)
req, err := http.NewRequest(tc.method, "/sync", nil)
if err != nil {
t.Errorf("exp nil, got %v", err)

View File

@ -8,9 +8,6 @@ import (
"os/signal"
"strconv"
"syscall"
"code.ewintr.nl/planner/handler"
"code.ewintr.nl/planner/storage"
)
func main() {
@ -25,10 +22,10 @@ func main() {
os.Exit(1)
}
mem := storage.NewMemory()
mem := NewMemory()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
go http.ListenAndServe(fmt.Sprintf(":%d", port), handler.NewServer(mem, apiKey, logger))
go http.ListenAndServe(fmt.Sprintf(":%d", port), NewServer(mem, apiKey, logger))
logger.Info("service started")

View File

@ -1,29 +1,27 @@
package storage
package main
import (
"time"
"code.ewintr.nl/planner/planner"
)
type Memory struct {
items map[string]planner.Syncable
items map[string]Syncable
}
func NewMemory() *Memory {
return &Memory{
items: make(map[string]planner.Syncable),
items: make(map[string]Syncable),
}
}
func (m *Memory) Update(item planner.Syncable) error {
func (m *Memory) Update(item Syncable) error {
m.items[item.ID] = item
return nil
}
func (m *Memory) Updated(timestamp time.Time) ([]planner.Syncable, error) {
result := make([]planner.Syncable, 0)
func (m *Memory) Updated(timestamp time.Time) ([]Syncable, error) {
result := make([]Syncable, 0)
for _, i := range m.items {
if timestamp.IsZero() || i.Updated.Equal(timestamp) || i.Updated.After(timestamp) {

View File

@ -1,17 +1,14 @@
package storage_test
package main
import (
"testing"
"time"
"code.ewintr.nl/planner/planner"
"code.ewintr.nl/planner/storage"
)
func TestMemoryItem(t *testing.T) {
t.Parallel()
mem := storage.NewMemory()
mem := NewMemory()
t.Log("start empty")
actItems, actErr := mem.Updated(time.Time{})
@ -23,7 +20,7 @@ func TestMemoryItem(t *testing.T) {
}
t.Log("add one")
t1 := planner.NewSyncable("test")
t1 := NewSyncable("test")
if actErr := mem.Update(t1); actErr != nil {
t.Errorf("exp nil, got %v", actErr)
}
@ -41,7 +38,7 @@ func TestMemoryItem(t *testing.T) {
before := time.Now()
t.Log("add second")
t2 := planner.NewSyncable("test 2")
t2 := NewSyncable("test 2")
if actErr := mem.Update(t2); actErr != nil {
t.Errorf("exp nil, got %v", actErr)
}

View File

@ -1,4 +1,4 @@
package planner
package main
import (
"time"

15
sync-service/storage.go Normal file
View File

@ -0,0 +1,15 @@
package main
import (
"errors"
"time"
)
var (
ErrNotFound = errors.New("not found")
)
type Syncer interface {
Update(item Syncable) error
Updated(t time.Time) ([]Syncable, error)
}