chore(repo): reinitialize repository
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"inbox/internal/domain/humantask"
|
||||
"inbox/internal/domain/message"
|
||||
)
|
||||
|
||||
func (s *Store) CreateHumanTask(ctx context.Context, value humantask.Record) (humantask.Record, error) {
|
||||
if err := value.Validate(); err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return humantask.Record{}, fmt.Errorf("begin create human task: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
item, err := insertHumanTaskTx(ctx, tx, s, value)
|
||||
if err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return humantask.Record{}, fmt.Errorf("commit create human task: %w", err)
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func insertHumanTaskTx(ctx context.Context, tx *sql.Tx, s *Store, value humantask.Record) (humantask.Record, error) {
|
||||
if value.ID == "" {
|
||||
id, err := s.newID("human-task")
|
||||
if err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
value.ID = id
|
||||
}
|
||||
value.Status = humantask.Status(strings.TrimSpace(string(value.Status)))
|
||||
if value.CreatedAt == "" {
|
||||
value.CreatedAt = s.now()
|
||||
}
|
||||
if value.UpdatedAt == "" {
|
||||
value.UpdatedAt = value.CreatedAt
|
||||
}
|
||||
if err := value.Validate(); err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
if _, err := tx.ExecContext(ctx, `
|
||||
INSERT INTO human_tasks(id, workspace_id, topic_id, role_name, prompt_message_id, status, answered_message_id, created_at, updated_at)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`,
|
||||
value.ID,
|
||||
value.WorkspaceID,
|
||||
value.TopicID,
|
||||
value.RoleName,
|
||||
value.PromptMessageID,
|
||||
string(value.Status),
|
||||
nullableString(value.AnsweredMessageID),
|
||||
value.CreatedAt,
|
||||
value.UpdatedAt,
|
||||
); err != nil {
|
||||
return humantask.Record{}, fmt.Errorf("insert human task: %w", err)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetHumanTask(ctx context.Context, taskID string) (humantask.Record, error) {
|
||||
row := s.db.QueryRowContext(ctx, `
|
||||
SELECT id, workspace_id, topic_id, role_name, prompt_message_id, status, answered_message_id, created_at, updated_at
|
||||
FROM human_tasks
|
||||
WHERE id = ?
|
||||
`, taskID)
|
||||
return scanHumanTask(row)
|
||||
}
|
||||
|
||||
func (s *Store) UpdateHumanTask(ctx context.Context, value humantask.Record) (humantask.Record, error) {
|
||||
if err := value.Validate(); err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
if value.UpdatedAt == "" {
|
||||
value.UpdatedAt = s.now()
|
||||
}
|
||||
if _, err := s.db.ExecContext(ctx, `
|
||||
UPDATE human_tasks
|
||||
SET status = ?, answered_message_id = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`,
|
||||
string(value.Status),
|
||||
nullableString(value.AnsweredMessageID),
|
||||
value.UpdatedAt,
|
||||
value.ID,
|
||||
); err != nil {
|
||||
return humantask.Record{}, fmt.Errorf("update human task: %w", err)
|
||||
}
|
||||
return s.GetHumanTask(ctx, value.ID)
|
||||
}
|
||||
|
||||
func (s *Store) AnswerHumanTask(ctx context.Context, taskID string, reply message.Record) (humantask.Record, message.Record, error) {
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return humantask.Record{}, message.Record{}, fmt.Errorf("begin answer human task: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
task, err := getHumanTaskTx(ctx, tx, taskID)
|
||||
if err != nil {
|
||||
return humantask.Record{}, message.Record{}, err
|
||||
}
|
||||
if task.Status != humantask.StatusPending {
|
||||
return humantask.Record{}, message.Record{}, fmt.Errorf("human task %s is not pending", task.ID)
|
||||
}
|
||||
|
||||
savedReply, err := s.createMessageTx(ctx, tx, reply)
|
||||
if err != nil {
|
||||
return humantask.Record{}, message.Record{}, err
|
||||
}
|
||||
|
||||
task.Status = humantask.StatusAnswered
|
||||
task.AnsweredMessageID = savedReply.ID
|
||||
task.UpdatedAt = coalesceString(reply.CreatedAt, s.now())
|
||||
if _, err := tx.ExecContext(ctx, `
|
||||
UPDATE human_tasks
|
||||
SET status = ?, answered_message_id = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`, string(task.Status), nullableString(task.AnsweredMessageID), task.UpdatedAt, task.ID); err != nil {
|
||||
return humantask.Record{}, message.Record{}, fmt.Errorf("update answered human task: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return humantask.Record{}, message.Record{}, fmt.Errorf("commit answer human task: %w", err)
|
||||
}
|
||||
|
||||
updated, err := s.GetHumanTask(ctx, taskID)
|
||||
if err != nil {
|
||||
return humantask.Record{}, message.Record{}, err
|
||||
}
|
||||
return updated, savedReply, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListHumanTasksByTopic(ctx context.Context, topicID string) ([]humantask.Record, error) {
|
||||
rows, err := s.db.QueryContext(ctx, `
|
||||
SELECT id, workspace_id, topic_id, role_name, prompt_message_id, status, answered_message_id, created_at, updated_at
|
||||
FROM human_tasks
|
||||
WHERE topic_id = ?
|
||||
ORDER BY created_at, id
|
||||
`, topicID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list human tasks by topic: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var out []humantask.Record
|
||||
for rows.Next() {
|
||||
item, err := scanHumanTask(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("iterate human tasks by topic: %w", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListPendingHumanTasksByWorkspace(ctx context.Context, workspaceID string) ([]humantask.Record, error) {
|
||||
rows, err := s.db.QueryContext(ctx, `
|
||||
SELECT id, workspace_id, topic_id, role_name, prompt_message_id, status, answered_message_id, created_at, updated_at
|
||||
FROM human_tasks
|
||||
WHERE workspace_id = ? AND status = ?
|
||||
ORDER BY updated_at DESC, created_at DESC, id DESC
|
||||
`, workspaceID, string(humantask.StatusPending))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list pending human tasks by workspace: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var out []humantask.Record
|
||||
for rows.Next() {
|
||||
item, err := scanHumanTask(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("iterate pending human tasks by workspace: %w", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func scanHumanTask(s scanner) (humantask.Record, error) {
|
||||
var item humantask.Record
|
||||
var status string
|
||||
var answeredMessageID sql.NullString
|
||||
if err := s.Scan(
|
||||
&item.ID,
|
||||
&item.WorkspaceID,
|
||||
&item.TopicID,
|
||||
&item.RoleName,
|
||||
&item.PromptMessageID,
|
||||
&status,
|
||||
&answeredMessageID,
|
||||
&item.CreatedAt,
|
||||
&item.UpdatedAt,
|
||||
); err != nil {
|
||||
return humantask.Record{}, err
|
||||
}
|
||||
item.Status = humantask.Status(status)
|
||||
if answeredMessageID.Valid {
|
||||
item.AnsweredMessageID = answeredMessageID.String
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func getHumanTaskTx(ctx context.Context, tx *sql.Tx, taskID string) (humantask.Record, error) {
|
||||
row := tx.QueryRowContext(ctx, `
|
||||
SELECT id, workspace_id, topic_id, role_name, prompt_message_id, status, answered_message_id, created_at, updated_at
|
||||
FROM human_tasks
|
||||
WHERE id = ?
|
||||
`, taskID)
|
||||
return scanHumanTask(row)
|
||||
}
|
||||
Reference in New Issue
Block a user