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 }