- база своя: два пула, захват одним UPDATE ... RETURNING, шаги схемы на goose под файловым замком, одна миграция начальной схемы вместо семи прежних - транспорт переписан на net/http: свои слои, свой ограничитель частоты, отдача файла с проверкой владельца; панель /_/ и пространство /api/ исчезли - по находкам ревью: журнал не пишет путь под корнем приложения, ключ бюджета читается справа налево, узнавание известного идёт читающим пулом
122 lines
5.4 KiB
Go
122 lines
5.4 KiB
Go
package entity
|
|
|
|
import "time"
|
|
|
|
// RecognitionStatus представляет статус операции распознавания у провайдера.
|
|
type RecognitionStatus int
|
|
|
|
const (
|
|
// RecognitionStatusInProgress - операция в процессе выполнения
|
|
RecognitionStatusInProgress RecognitionStatus = iota
|
|
// RecognitionStatusCompleted - операция завершена успешно
|
|
RecognitionStatusCompleted
|
|
// RecognitionStatusFailed - операция завершена с ошибкой
|
|
RecognitionStatusFailed
|
|
)
|
|
|
|
// String возвращает строковое представление статуса
|
|
func (s RecognitionStatus) String() string {
|
|
switch s {
|
|
case RecognitionStatusInProgress:
|
|
return "in_progress"
|
|
case RecognitionStatusCompleted:
|
|
return "completed"
|
|
case RecognitionStatusFailed:
|
|
return "failed"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// RecognitionResult представляет исход опроса операции распознавания.
|
|
type RecognitionResult struct {
|
|
Status RecognitionStatus
|
|
Error string // Текст ошибки (заполняется при StatusFailed)
|
|
}
|
|
|
|
// NewInProgressResult создает результат для операции в процессе выполнения
|
|
func NewInProgressResult() *RecognitionResult {
|
|
return &RecognitionResult{
|
|
Status: RecognitionStatusInProgress,
|
|
}
|
|
}
|
|
|
|
// NewCompletedResult создает результат для успешно завершенной операции
|
|
func NewCompletedResult() *RecognitionResult {
|
|
return &RecognitionResult{
|
|
Status: RecognitionStatusCompleted,
|
|
}
|
|
}
|
|
|
|
// NewFailedResult создает результат для операции, завершенной с ошибкой
|
|
func NewFailedResult(errorText string) *RecognitionResult {
|
|
return &RecognitionResult{
|
|
Status: RecognitionStatusFailed,
|
|
Error: errorText,
|
|
}
|
|
}
|
|
|
|
// IsInProgress проверяет, находится ли операция в процессе выполнения
|
|
func (r *RecognitionResult) IsInProgress() bool {
|
|
return r.Status == RecognitionStatusInProgress
|
|
}
|
|
|
|
// IsCompleted проверяет, завершена ли операция успешно
|
|
func (r *RecognitionResult) IsCompleted() bool {
|
|
return r.Status == RecognitionStatusCompleted
|
|
}
|
|
|
|
// IsFailed проверяет, завершена ли операция с ошибкой
|
|
func (r *RecognitionResult) IsFailed() bool {
|
|
return r.Status == RecognitionStatusFailed
|
|
}
|
|
|
|
// GetError возвращает текст ошибки (только для операций, завершенных с ошибкой)
|
|
func (r *RecognitionResult) GetError() string {
|
|
if r.IsFailed() {
|
|
return r.Error
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Recognition — попытка распознавания у внешнего провайдера.
|
|
//
|
|
// Всё провайдерское живёт здесь, а не колонками записи: идентификатор операции —
|
|
// самое провайдерское, что есть в модели, а копия аудио во внешнем хранилище
|
|
// существует только потому, что сегодняшний провайдер читает запись по адресу.
|
|
// Другой провайдер её не потребует, и смена провайдера не трогает доменную
|
|
// сущность вовсе.
|
|
//
|
|
// Сохранённый ответ провайдера лежит **третьим файлом в подкаталоге записи**, а
|
|
// не колонкой этой строки: шаг опроса читает её раз в несколько секунд, а
|
|
// репозиторий читает строку целиком — ответ на многочасовую запись ехал бы в
|
|
// память при каждом опросе. Хранится он потому, что результат операции у
|
|
// провайдера не переспрашивается.
|
|
type Recognition struct {
|
|
Id string
|
|
RecordID string
|
|
Provider string
|
|
Model string
|
|
// ExternalID — идентификатор операции у провайдера. Заводится **до**
|
|
// обращения к нему: окно между ответом провайдера и записью идентификатора —
|
|
// то место, где теряется оплаченное.
|
|
ExternalID string
|
|
// SourceURI — адрес, по которому провайдер читает аудио.
|
|
SourceURI string
|
|
StartedAt *time.Time
|
|
FinishedAt *time.Time
|
|
}
|
|
|
|
// RecognitionOutcome — доменный результат распознавания, каким его отдаёт
|
|
// адаптер. Формата провайдера здесь нет: разбор потока — обязанность адаптера, и
|
|
// ни один шаг конвейера не знает, каким потоком и какими полями провайдер
|
|
// отвечает.
|
|
type RecognitionOutcome struct {
|
|
// Replicas — реплики со временем от начала записи.
|
|
Replicas []Replica
|
|
// PlainText — плоский текст расшифровки.
|
|
PlainText string
|
|
// Raw — ответ провайдера целиком, как он пришёл, на хранение отдельным файлом.
|
|
Raw []byte
|
|
}
|