package main // pack_store.go:打包任务与控制台日志的本地 SQLite 持久化(不同步云端)。 import ( "strings" "time" ) const ( packTaskKeepLimit = 100 packLogKeepLimit = 2000 ) func (s *Store) markInterruptedPackTasks() { now := time.Now().Format(time.RFC3339) rows, e := s.db.Query(`SELECT id FROM pack_tasks WHERE status='running'`) if e != nil { return } var ids []string for rows.Next() { var id string if rows.Scan(&id) == nil && id != "" { ids = append(ids, id) } } _ = rows.Close() if len(ids) == 0 { return } _, _ = s.db.Exec(`UPDATE pack_tasks SET status='failed', error=?, ended_at=? WHERE status='running'`, "应用退出,任务中断", now) for _, id := range ids { _, _ = s.db.Exec(`INSERT INTO pack_task_logs(task_id,line,created_at) VALUES(?,?,?)`, id, "✗ 应用退出,任务中断", now) } } func (s *Store) insertPackTask(t LocalPackTask) error { _, e := s.db.Exec( `INSERT INTO pack_tasks(id,title,cmd,dir,status,pid,started_at,ended_at,error) VALUES(?,?,?,?,?,?,?,?,?)`, t.ID, t.Title, t.Cmd, t.Dir, t.Status, t.PID, t.StartedAt, t.EndedAt, t.Error, ) return e } func (s *Store) updatePackTaskMeta(t LocalPackTask) { _, _ = s.db.Exec( `UPDATE pack_tasks SET title=?, cmd=?, dir=?, status=?, pid=?, started_at=?, ended_at=?, error=? WHERE id=?`, t.Title, t.Cmd, t.Dir, t.Status, t.PID, t.StartedAt, t.EndedAt, t.Error, t.ID, ) } func (s *Store) appendPackTaskLog(taskID, line string) { line = strings.TrimRight(line, "\r\n") if strings.TrimSpace(line) == "" { return } if len(line) > 8000 { line = line[:8000] + "…" } _, _ = s.db.Exec(`INSERT INTO pack_task_logs(task_id,line,created_at) VALUES(?,?,?)`, taskID, line, time.Now().Format(time.RFC3339)) _, _ = s.db.Exec(`DELETE FROM pack_task_logs WHERE task_id=? AND id NOT IN ( SELECT id FROM pack_task_logs WHERE task_id=? ORDER BY id DESC LIMIT ?)`, taskID, taskID, packLogKeepLimit) } func (s *Store) listPackTasks(limit int) ([]LocalPackTask, error) { if limit <= 0 || limit > packTaskKeepLimit { limit = packTaskKeepLimit } rows, e := s.db.Query( `SELECT id,title,cmd,dir,status,pid,started_at,ended_at,error FROM pack_tasks ORDER BY started_at DESC, id DESC LIMIT ?`, limit, ) if e != nil { return nil, e } defer rows.Close() out := []LocalPackTask{} for rows.Next() { var t LocalPackTask if e = rows.Scan(&t.ID, &t.Title, &t.Cmd, &t.Dir, &t.Status, &t.PID, &t.StartedAt, &t.EndedAt, &t.Error); e != nil { return nil, e } out = append(out, t) } return out, rows.Err() } func (s *Store) getPackTask(id string) (LocalPackTask, error) { var t LocalPackTask e := s.db.QueryRow( `SELECT id,title,cmd,dir,status,pid,started_at,ended_at,error FROM pack_tasks WHERE id=?`, id, ).Scan(&t.ID, &t.Title, &t.Cmd, &t.Dir, &t.Status, &t.PID, &t.StartedAt, &t.EndedAt, &t.Error) if e != nil { return LocalPackTask{}, e } return t, nil } func (s *Store) listPackTaskLogs(taskID string) ([]string, error) { rows, e := s.db.Query( `SELECT line FROM pack_task_logs WHERE task_id=? ORDER BY id ASC`, taskID, ) if e != nil { return nil, e } defer rows.Close() out := []string{} for rows.Next() { var line string if e = rows.Scan(&line); e != nil { return nil, e } out = append(out, line) } return out, rows.Err() } func (s *Store) listPackTaskLogTail(taskID string, n int) ([]string, error) { if n <= 0 { n = 3 } rows, e := s.db.Query( `SELECT line FROM pack_task_logs WHERE task_id=? ORDER BY id DESC LIMIT ?`, taskID, n, ) if e != nil { return nil, e } defer rows.Close() rev := []string{} for rows.Next() { var line string if e = rows.Scan(&line); e != nil { return nil, e } rev = append(rev, line) } for i, j := 0, len(rev)-1; i < j; i, j = i+1, j-1 { rev[i], rev[j] = rev[j], rev[i] } return rev, rows.Err() } func (s *Store) deleteFinishedPackTasks() error { _, e := s.db.Exec(`DELETE FROM pack_task_logs WHERE task_id IN (SELECT id FROM pack_tasks WHERE status!='running')`) if e != nil { return e } _, e = s.db.Exec(`DELETE FROM pack_tasks WHERE status!='running'`) return e } func (s *Store) deletePackTask(id string) error { var status string if e := s.db.QueryRow(`SELECT status FROM pack_tasks WHERE id=?`, id).Scan(&status); e != nil { return e } if status == "running" { return nil } _, _ = s.db.Exec(`DELETE FROM pack_task_logs WHERE task_id=?`, id) _, e := s.db.Exec(`DELETE FROM pack_tasks WHERE id=?`, id) return e } func (s *Store) pruneOldPackTasks() { _, _ = s.db.Exec(`DELETE FROM pack_task_logs WHERE task_id IN ( SELECT id FROM pack_tasks WHERE id NOT IN ( SELECT id FROM pack_tasks ORDER BY started_at DESC, id DESC LIMIT ? ) )`, packTaskKeepLimit) _, _ = s.db.Exec(`DELETE FROM pack_tasks WHERE id NOT IN ( SELECT id FROM ( SELECT id FROM pack_tasks ORDER BY started_at DESC, id DESC LIMIT ? ) )`, packTaskKeepLimit) }