More granular error handling

+ task queue refactoring
This commit is contained in:
2025-08-17 15:26:59 +03:00
parent 8eddab4455
commit 12b16b3749
10 changed files with 262 additions and 157 deletions

View File

@@ -40,7 +40,7 @@ func (h *TranscribeHandler) CreateTranscribeJob(c *gin.Context) {
}
defer file.Close()
job, err := h.trsService.CreateTranscribeJob(file, header.Filename)
job, err := h.trsService.CreateJobFromApi(file, header.Filename)
if err != nil {
log.Printf("Err: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create transcibe job"})

View File

@@ -69,7 +69,16 @@ func setupTestRouter(t *testing.T) (*gin.Engine, *TranscribeHandler) {
Level: slog.LevelError, // Только ошибки в тестах
}))
trsService := service.NewTranscribeService(jobRepo, fileRepo, metaviewer, converter, recognizer, "data/files", logger)
trsService := service.NewTranscribeService(
jobRepo,
fileRepo,
metaviewer,
converter,
recognizer,
&TestTgSender{},
"data/files",
logger,
)
handler := NewTranscribeHandler(jobRepo, trsService)
@@ -374,3 +383,9 @@ func TestGetTranscribeJobStatus_NotFound(t *testing.T) {
assert.Equal(t, "Job not found", response["error"])
}
type TestTgSender struct{}
func (s *TestTgSender) Send(msg string, chatId int64, replyMsgId *int) error {
return nil
}

View File

@@ -7,7 +7,6 @@ import (
"net/http"
"slices"
"strings"
"time"
"git.vakhrushev.me/av/transcriber/internal/contract"
"git.vakhrushev.me/av/transcriber/internal/service"
@@ -170,7 +169,7 @@ func (c *TelegramController) handleAudioMessage(message *tgbotapi.Message) {
defer fileReader.Close()
// Обрабатываем файл
job, err := c.transcribeService.CreateTranscribeJob(fileReader, fileName)
job, err := c.transcribeService.CreateJobFromTelegram(fileReader, fileName, message.Chat.ID, sentProgressMsg.MessageID)
if err != nil {
c.logger.Error("Failed to create transcribe job", "error", err)
errorMsg := tgbotapi.NewMessage(message.Chat.ID, "Ошибка при создании задачи на расшифровку. Попробуйте еще раз.")
@@ -182,9 +181,6 @@ func (c *TelegramController) handleAudioMessage(message *tgbotapi.Message) {
successMsg := tgbotapi.NewMessage(message.Chat.ID, fmt.Sprintf("Задача на расшифровку создана. ID задачи: %s", job.Id))
successMsg.ReplyToMessageID = message.MessageID
c.send(successMsg)
// Отправляем результат расшифровки (асинхронно)
go c.sendTranscriptionResult(job.Id, message.Chat.ID, sentProgressMsg.MessageID)
}
func (c *TelegramController) handleVoiceMessage(message *tgbotapi.Message) {
@@ -208,7 +204,7 @@ func (c *TelegramController) handleVoiceMessage(message *tgbotapi.Message) {
defer fileReader.Close()
// Обрабатываем файл
job, err := c.transcribeService.CreateTranscribeJob(fileReader, fileName)
job, err := c.transcribeService.CreateJobFromTelegram(fileReader, fileName, message.Chat.ID, sentProgressMsg.MessageID)
if err != nil {
c.logger.Error("Failed to create transcribe job", "error", err)
errorMsg := tgbotapi.NewMessage(message.Chat.ID, "Ошибка при создании задачи на расшифровку. Попробуйте еще раз.")
@@ -220,9 +216,6 @@ func (c *TelegramController) handleVoiceMessage(message *tgbotapi.Message) {
successMsg := tgbotapi.NewMessage(message.Chat.ID, fmt.Sprintf("Задача на расшифровку создана. ID задачи: %s", job.Id))
successMsg.ReplyToMessageID = message.MessageID
c.send(successMsg)
// Отправляем результат расшифровки (асинхронно)
go c.sendTranscriptionResult(job.Id, message.Chat.ID, sentProgressMsg.MessageID)
}
func (c *TelegramController) handleDocumentMessage(message *tgbotapi.Message) {
@@ -251,7 +244,7 @@ func (c *TelegramController) handleDocumentMessage(message *tgbotapi.Message) {
defer fileReader.Close()
// Обрабатываем файл
job, err := c.transcribeService.CreateTranscribeJob(fileReader, fileName)
job, err := c.transcribeService.CreateJobFromTelegram(fileReader, fileName, message.Chat.ID, sentProgressMsg.MessageID)
if err != nil {
c.logger.Error("Failed to create transcribe job", "error", err)
errorMsg := tgbotapi.NewMessage(message.Chat.ID, "Ошибка при создании задачи на расшифровку. Попробуйте еще раз.")
@@ -263,9 +256,6 @@ func (c *TelegramController) handleDocumentMessage(message *tgbotapi.Message) {
successMsg := tgbotapi.NewMessage(message.Chat.ID, fmt.Sprintf("Задача на расшифровку создана. ID задачи: %s", job.Id))
successMsg.ReplyToMessageID = message.MessageID
c.send(successMsg)
// Отправляем результат расшифровки (асинхронно)
go c.sendTranscriptionResult(job.Id, message.Chat.ID, sentProgressMsg.MessageID)
}
func (c *TelegramController) downloadAudioFile(fileID string) (io.ReadCloser, string, error) {
@@ -291,59 +281,6 @@ func (c *TelegramController) downloadAudioFile(fileID string) (io.ReadCloser, st
return resp.Body, fileName, nil
}
func (c *TelegramController) sendTranscriptionResult(jobID string, chatID int64, progressMessageID int) {
// Периодически проверяем статус задачи
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
timeout := time.After(10 * time.Minute) // Максимальное время ожидания 10 минут
for {
select {
case <-ticker.C:
// Проверяем статус задачи
job, err := c.jobRepo.GetByID(jobID)
if err != nil {
c.logger.Error("Failed to get job", "job_id", jobID, "error", err)
continue
}
switch job.State {
case "done":
// Отправляем результат
if job.TranscriptionText != nil {
resultMsg := tgbotapi.NewMessage(chatID, *job.TranscriptionText)
resultMsg.ReplyToMessageID = progressMessageID
c.send(resultMsg)
} else {
resultMsg := tgbotapi.NewMessage(chatID, "Расшифровка завершена, но текст пуст.")
resultMsg.ReplyToMessageID = progressMessageID
c.send(resultMsg)
}
return
case "failed":
// Отправляем сообщение об ошибке
var errorMsg string
if job.ErrorText != nil {
errorMsg = fmt.Sprintf("Ошибка при расшифровке: %s", *job.ErrorText)
} else {
errorMsg = "Ошибка при расшифровке аудиофайла."
}
resultMsg := tgbotapi.NewMessage(chatID, errorMsg)
resultMsg.ReplyToMessageID = progressMessageID
c.send(resultMsg)
return
}
case <-timeout:
// Время ожидания истекло
resultMsg := tgbotapi.NewMessage(chatID, "Время ожидания результата расшифровки истекло. Попробуйте позже проверить статус задачи.")
resultMsg.ReplyToMessageID = progressMessageID
c.send(resultMsg)
return
}
}
}
func (c *TelegramController) isAudioDocument(document *tgbotapi.Document) bool {
// Проверяем MIME-тип документа
if document.MimeType != "" {