simgle package sync service
This commit is contained in:
parent
74775ac244
commit
204c712cc6
2
Makefile
2
Makefile
|
@ -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/
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
|
@ -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)
|
|
@ -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")
|
||||
|
|
@ -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) {
|
|
@ -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)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package planner
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue