feat(events): EventBus + domain-модель статусов
- internal/model: единый источник статусов задачи (Status, TraceStatus, машина переходов), без зависимости от storage. - internal/storage: совместимый мост (type Status = model.Status, re-export констант) — внешний код не меняется. - internal/events: шина событий (fan-out, блокирующий Publish с гарантией порядка), события задач/трейсов, отдельная логовая шина + LogWriter, Publisher/NilPublisher для внедрения в Core/Worker. - docs/ui-spec.md: спецификация десктопного UI (Fyne).
This commit is contained in:
@@ -1,66 +1,43 @@
|
||||
package storage
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
// Status — статус задачи (state machine).
|
||||
type Status string
|
||||
"github.com/kamelion/ratatoskr-go/internal/model"
|
||||
)
|
||||
|
||||
// Status — алиас доменного статуса задачи.
|
||||
//
|
||||
// Совместимый мост: весь внешний код продолжает использовать storage.Status
|
||||
// (например «storage.StatusRunning»), но единый источник истины — model.Status.
|
||||
type Status = model.Status
|
||||
|
||||
// Статусы задачи — re-export из model.
|
||||
const (
|
||||
StatusDraft Status = "draft" // только что создана
|
||||
StatusCollecting Status = "collecting" // аналитик собирает детали
|
||||
StatusReady Status = "ready" // черновик готов, ждёт одобрения пользователя
|
||||
StatusApproved Status = "approved" // пользователь одобрил («создавай») — воркер берёт в работу
|
||||
StatusRunning Status = "running" // opencode работает
|
||||
StatusSuccess Status = "success" // задача выполнена
|
||||
StatusFailed Status = "failed" // ошибка выполнения
|
||||
StatusTimeout Status = "timeout" // таймаут opencode
|
||||
StatusCancelled Status = "cancelled" // отменена пользователем
|
||||
StatusAborted Status = "aborted" // сбой сбора, черновик выброшен
|
||||
StatusClosed Status = "closed" // закрыта вручную
|
||||
StatusDraft = model.StatusDraft
|
||||
StatusCollecting = model.StatusCollecting
|
||||
StatusReady = model.StatusReady
|
||||
StatusApproved = model.StatusApproved
|
||||
StatusRunning = model.StatusRunning
|
||||
StatusSuccess = model.StatusSuccess
|
||||
StatusFailed = model.StatusFailed
|
||||
StatusTimeout = model.StatusTimeout
|
||||
StatusCancelled = model.StatusCancelled
|
||||
StatusAborted = model.StatusAborted
|
||||
StatusClosed = model.StatusClosed
|
||||
)
|
||||
|
||||
// AllStatuses — все возможные статусы для валидации.
|
||||
var AllStatuses = []Status{
|
||||
StatusDraft, StatusCollecting, StatusReady, StatusApproved,
|
||||
StatusRunning, StatusSuccess, StatusFailed, StatusTimeout,
|
||||
StatusCancelled, StatusAborted, StatusClosed,
|
||||
}
|
||||
|
||||
// validTransitions задаёт разрешённые переходы статусов.
|
||||
var validTransitions = map[Status][]Status{
|
||||
StatusDraft: {StatusCollecting, StatusCancelled, StatusAborted},
|
||||
StatusCollecting: {StatusReady, StatusDraft, StatusCancelled, StatusAborted},
|
||||
// ready — черновик готов: «создавай» → approved, либо правка/отмена/закрытие.
|
||||
StatusReady: {StatusApproved, StatusCancelled, StatusAborted, StatusClosed, StatusCollecting},
|
||||
// approved — финальное одобрение: воркер берёт в running, либо отмена/сбой/закрытие.
|
||||
StatusApproved: {StatusRunning, StatusCancelled, StatusAborted, StatusClosed},
|
||||
StatusRunning: {StatusSuccess, StatusFailed, StatusTimeout, StatusCancelled},
|
||||
StatusSuccess: {StatusClosed},
|
||||
StatusFailed: {StatusReady, StatusClosed, StatusCancelled, StatusCollecting}, // retry: перезапуск сбора
|
||||
StatusTimeout: {StatusReady, StatusClosed, StatusCancelled, StatusCollecting}, // retry: перезапуск сбора
|
||||
StatusCancelled: {StatusClosed},
|
||||
StatusAborted: {StatusClosed},
|
||||
StatusClosed: {}, // терминальный
|
||||
}
|
||||
var AllStatuses = model.AllStatuses
|
||||
|
||||
// IsValidTransition проверяет, допустим ли переход from → to.
|
||||
func IsValidTransition(from, to Status) bool {
|
||||
allowed, ok := validTransitions[from]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, s := range allowed {
|
||||
if s == to {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return model.IsValidTransition(from, to)
|
||||
}
|
||||
|
||||
// IsTerminal возвращает true, если статус терминальный.
|
||||
func IsTerminal(s Status) bool {
|
||||
return s == StatusSuccess || s == StatusCancelled ||
|
||||
s == StatusAborted || s == StatusClosed
|
||||
return model.IsTerminal(s)
|
||||
}
|
||||
|
||||
// Task — запись задачи в БД.
|
||||
@@ -111,14 +88,14 @@ func (t *Task) SetReposFromDB(repos string) {
|
||||
_ = json.Unmarshal([]byte(repos), &t.Repos)
|
||||
}
|
||||
|
||||
// Trace — запись трассировки выполнения.
|
||||
type TraceStatus string
|
||||
// TraceStatus — алиас доменного статуса трассировки.
|
||||
type TraceStatus = model.TraceStatus
|
||||
|
||||
const (
|
||||
TraceRunning TraceStatus = "running"
|
||||
TraceSuccess TraceStatus = "success"
|
||||
TraceFailed TraceStatus = "failed"
|
||||
TraceTimeout TraceStatus = "timeout"
|
||||
TraceRunning TraceStatus = model.TraceRunning
|
||||
TraceSuccess TraceStatus = model.TraceSuccess
|
||||
TraceFailed TraceStatus = model.TraceFailed
|
||||
TraceTimeout TraceStatus = model.TraceTimeout
|
||||
)
|
||||
|
||||
// Trace — лог одного субагента.
|
||||
|
||||
Reference in New Issue
Block a user