132 lines
2.3 KiB
Go
132 lines
2.3 KiB
Go
package persist
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
"snamellit.com/play/todo/internal/model"
|
|
)
|
|
|
|
var EMPTY_TODO = model.Todo{Id: 0, Title: "", Completed: false}
|
|
|
|
var maxId int = 0
|
|
|
|
var todos model.Todos
|
|
|
|
type eventType string
|
|
const (
|
|
ADDED eventType = "ADDED"
|
|
DELETED eventType = "DELETED"
|
|
CHANGED eventType = "CHANGED"
|
|
)
|
|
|
|
type event struct {
|
|
Kind eventType
|
|
Todo model.Todo
|
|
}
|
|
|
|
func readTodos() (model.Todos, error) {
|
|
f, err := os.OpenFile("todo_events.txt", os.O_RDONLY|os.O_CREATE, 0644)
|
|
defer f.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dec := json.NewDecoder(f)
|
|
|
|
todos = make(model.Todos)
|
|
for {
|
|
var e event
|
|
err = dec.Decode(&e)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return nil, err
|
|
}
|
|
fmt.Println("Read event", e)
|
|
id := e.Todo.Id
|
|
if id > maxId {
|
|
maxId = id
|
|
}
|
|
applyEvent(e.Kind, e.Todo)
|
|
}
|
|
return todos, nil
|
|
}
|
|
|
|
func applyEvent(kind eventType, todo model.Todo) error {
|
|
id := todo.Id
|
|
switch t := kind; t {
|
|
case ADDED:
|
|
fmt.Println("apply add ", todo)
|
|
todos[id] = todo
|
|
case CHANGED:
|
|
fmt.Println("apply change ", todo)
|
|
todos[id] = todo
|
|
case DELETED:
|
|
fmt.Println("apply delete ", todo)
|
|
delete(todos, id)
|
|
default:
|
|
return fmt.Errorf("Unknown event type %s", t)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func addEvent(kind eventType, todo model.Todo) error {
|
|
err := applyEvent(kind, todo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f, err := os.OpenFile("todo_events.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
|
defer f.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("Write todo", todo)
|
|
enc := json.NewEncoder(f)
|
|
e := event{Kind: kind, Todo: todo}
|
|
fmt.Println("Write event", e)
|
|
err = enc.Encode(e)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetTodos() (model.Todos, error) {
|
|
if len(todos) == 0 {
|
|
return readTodos()
|
|
}
|
|
return todos, nil
|
|
}
|
|
|
|
|
|
func GetTodoById(id int) (model.Todo, error) {
|
|
todo, present := todos[id]
|
|
if !present {
|
|
return EMPTY_TODO, fmt.Errorf("Todo with id %d not found", id)
|
|
}
|
|
return todo, nil
|
|
}
|
|
|
|
func SetTodo(todo model.Todo) error {
|
|
fmt.Println("SetTodo", todo)
|
|
todos[todo.Id] = todo
|
|
return addEvent(CHANGED, todo)
|
|
}
|
|
|
|
func AddTodo(title string) error {
|
|
fmt.Println("AddTodo", title)
|
|
maxId++;
|
|
todo := model.Todo{Id: maxId, Title: title, Completed: false}
|
|
return addEvent(ADDED, todo)
|
|
}
|
|
|
|
func DeleteTodoById(id int) error {
|
|
delete(todos, id)
|
|
return addEvent(DELETED, model.Todo{Id: id})
|
|
}
|
|
|