gotodo/internal/persist/persist.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})
}