fixes
This commit is contained in:
1 parent
c8cc0fb28a
commit
e790c02d59
16 files changed
+659
-15
No files matched your search
+71
-2
@@ -27,12 +27,16 @@ type Todo struct {
|
||||
UserAgent string `json:"userAgent,omitempty"`
|
||||
Session string `json:"session,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Done bool `json:"done"`
|
||||
DoneAt time.Time `json:"doneAt,omitzero"`
|
||||
}
|
||||
|
||||
// Store persists todos. List returns newest first; an empty project means all.
|
||||
type Store interface {
|
||||
Add(ctx context.Context, t Todo) error
|
||||
List(ctx context.Context, project string, limit int) ([]Todo, error)
|
||||
// SetDone marks a todo done or open; ok is false for an unknown id.
|
||||
SetDone(ctx context.Context, id string, done bool) (t Todo, ok bool, err error)
|
||||
}
|
||||
|
||||
// FileStore keeps todos in memory and appends them to a JSONL file.
|
||||
@@ -82,6 +86,35 @@ func (s *FileStore) Add(_ context.Context, t Todo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FileStore) SetDone(_ context.Context, id string, done bool) (Todo, bool, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for i := range s.items {
|
||||
if s.items[i].ID != id {
|
||||
continue
|
||||
}
|
||||
s.items[i].Done = done
|
||||
s.items[i].DoneAt = time.Time{}
|
||||
if done {
|
||||
s.items[i].DoneAt = time.Now().UTC()
|
||||
}
|
||||
var buf []byte
|
||||
for _, t := range s.items {
|
||||
line, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
return Todo{}, false, err
|
||||
}
|
||||
buf = append(append(buf, line...), '\n')
|
||||
}
|
||||
tmp := s.path + ".tmp"
|
||||
if err := os.WriteFile(tmp, buf, 0o644); err != nil {
|
||||
return Todo{}, false, err
|
||||
}
|
||||
return s.items[i], true, os.Rename(tmp, s.path)
|
||||
}
|
||||
return Todo{}, false, nil
|
||||
}
|
||||
|
||||
func (s *FileStore) List(_ context.Context, project string, limit int) ([]Todo, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -121,6 +154,11 @@ func NewClickHouseStore(ctx context.Context, conn driver.Conn, db string) (*Clic
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, col := range []string{"done UInt8", "done_at DateTime64(3, 'UTC')"} {
|
||||
if err := conn.Exec(ctx, fmt.Sprintf(`ALTER TABLE %s.todos ADD COLUMN IF NOT EXISTS %s`, db, col)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &ClickHouseStore{conn: conn, db: db}, nil
|
||||
}
|
||||
|
||||
@@ -130,7 +168,7 @@ func (s *ClickHouseStore) Add(ctx context.Context, t Todo) error {
|
||||
}
|
||||
|
||||
func (s *ClickHouseStore) List(ctx context.Context, project string, limit int) ([]Todo, error) {
|
||||
q := fmt.Sprintf(`SELECT id, project, text, component, path, hash, url, user_agent, session, created_at FROM %s.todos`, s.db)
|
||||
q := fmt.Sprintf(`SELECT id, project, text, component, path, hash, url, user_agent, session, created_at, done, done_at FROM %s.todos`, s.db)
|
||||
var args []any
|
||||
if project != "" {
|
||||
q += ` WHERE project = ?`
|
||||
@@ -146,10 +184,41 @@ func (s *ClickHouseStore) List(ctx context.Context, project string, limit int) (
|
||||
var out []Todo
|
||||
for rows.Next() {
|
||||
var t Todo
|
||||
if err := rows.Scan(&t.ID, &t.Project, &t.Text, &t.Component, &t.Path, &t.Hash, &t.URL, &t.UserAgent, &t.Session, &t.CreatedAt); err != nil {
|
||||
var done uint8
|
||||
if err := rows.Scan(&t.ID, &t.Project, &t.Text, &t.Component, &t.Path, &t.Hash, &t.URL, &t.UserAgent, &t.Session, &t.CreatedAt, &done, &t.DoneAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Done = done != 0
|
||||
out = append(out, t)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *ClickHouseStore) SetDone(ctx context.Context, id string, done bool) (Todo, bool, error) {
|
||||
var d uint8
|
||||
doneAt := time.Unix(0, 0).UTC()
|
||||
if done {
|
||||
d, doneAt = 1, time.Now().UTC()
|
||||
}
|
||||
if err := s.conn.Exec(ctx, fmt.Sprintf(`ALTER TABLE %s.todos UPDATE done = ?, done_at = ? WHERE id = ? SETTINGS mutations_sync = 1`, s.db), d, doneAt, id); err != nil {
|
||||
return Todo{}, false, err
|
||||
}
|
||||
rows, err := s.conn.Query(ctx, fmt.Sprintf(`SELECT id, project, text, component, path, hash, url, user_agent, session, created_at, done, done_at FROM %s.todos WHERE id = ?`, s.db), id)
|
||||
if err != nil {
|
||||
return Todo{}, false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
if !rows.Next() {
|
||||
return Todo{}, false, nil
|
||||
}
|
||||
var t Todo
|
||||
var dn uint8
|
||||
if err := rows.Scan(&t.ID, &t.Project, &t.Text, &t.Component, &t.Path, &t.Hash, &t.URL, &t.UserAgent, &t.Session, &t.CreatedAt, &dn, &t.DoneAt); err != nil {
|
||||
return Todo{}, false, err
|
||||
}
|
||||
t.Done = dn != 0
|
||||
if !t.Done {
|
||||
t.DoneAt = time.Time{}
|
||||
}
|
||||
return t, true, nil
|
||||
}
|
||||
Reference in new issue
Block a user