внутренняя модель перестроена вокруг аудиозаписи

- audiorecords вместо transcribe_jobs: приложения (texts, structures,
  recognitions, record_events, topics) живут своими коллекциями, ссылки на
  исходник и на приведённую копию перестали переставляться
- рубеж называет достигнутое, отказ стал признаком остановки с причиной, а
  сторожей стало двое: число отказов и время в рубеже
- воркеры потеряли специализацию, их число задаётся [pipeline] workers, шаг
  выбирается по рубежу, а захват отдаёт идентификатор и признак захвата
This commit is contained in:
av
2026-08-14 20:20:33 +03:00
parent d079f03350
commit 1576d06735
84 changed files with 8973 additions and 2865 deletions
+30 -28
View File
@@ -68,6 +68,14 @@ func main() {
os.Exit(1)
}
// Числа конвейера проверяются здесь же: ноль воркеров — объявленный режим, а
// отрицательное число и нулевой предел простоя — опечатка, и подниматься с
// ней значит остановить всякую запись первым же захватом.
if err := cfg.Pipeline.Validate(); err != nil {
logger.Error("Unable to start with incorrect pipeline settings", "error", err)
os.Exit(1)
}
// Загружаем переменные окружения из .env файла
if err := godotenv.Load(); err != nil {
logger.Warn("Warning: .env file not found, using system environment variables")
@@ -90,8 +98,15 @@ func main() {
pbrepo.BindPanelRules(storage)
// Создаем репозитории
fileRepo := pbrepo.NewFileRepository(storage)
jobRepo := pbrepo.NewTranscriptJobRepository(storage)
recordRepo := pbrepo.NewAudioRecordRepository(storage)
repos := service.Repositories{
Records: recordRepo,
Files: pbrepo.NewFileRepository(storage),
Texts: pbrepo.NewTextRepository(storage),
Structures: pbrepo.NewStructureRepository(storage),
Recognitions: pbrepo.NewRecognitionRepository(storage),
Events: pbrepo.NewRecordEventRepository(storage),
}
// Создаем адаптеры
metaviewer := ffmpegmv.NewFfmpegMetaViewer()
@@ -128,12 +143,12 @@ func main() {
// Создаем сервисы
transcribeService := service.NewTranscribeService(
jobRepo,
fileRepo,
repos,
metaviewer,
converter,
recognizer,
tgSender,
cfg.Pipeline.StuckLimits(),
logger,
)
@@ -154,7 +169,7 @@ func main() {
// же факте.
var tgController *tgcontroller.TelegramController
if tgBot != nil {
tgController, err = tgcontroller.NewTelegramController(tgConfig, tgBot, transcribeService, jobRepo, logger)
tgController, err = tgcontroller.NewTelegramController(tgConfig, tgBot, transcribeService, logger)
if err != nil {
logger.Error("Failed to create Telegram controller", "error", err)
os.Exit(1)
@@ -170,26 +185,14 @@ func main() {
}()
}
// Создаем воркеры
conversionWorker := worker.NewCallbackWorker("conversion_worker", transcribeService.FindAndRunConversionJob, logger)
transcribeWorker := worker.NewCallbackWorker("transcribe_worker", transcribeService.FindAndRunTranscribeJob, logger)
checkWorker := worker.NewCallbackWorker("check_worker", transcribeService.FindAndRunTranscribeCheckJob, logger)
workers := []worker.Worker{
conversionWorker,
transcribeWorker,
checkWorker,
}
// Запускаем воркеры в отдельных горутинах
for _, w := range workers {
wg.Add(1)
go func(worker worker.Worker) {
defer wg.Done()
worker.Start(ctx)
logger.Info("Worker stopped gracefully", "worker", worker.Name())
}(w)
}
// Пул одинаковых воркеров: специализации у них нет, шаг выбирается по рубежу
// самой записи. Число приходит настройкой, ноль — законное значение.
pool := worker.NewPool(cfg.Pipeline.Workers, transcribeService.RunStep, logger)
wg.Add(1)
go func() {
defer wg.Done()
pool.Start(ctx)
}()
// Вход по HTTP поднимается всегда: он основной, и отдельного разреза у него
// нет. Признак ставится рядом с признаком Telegram, чтобы владелец судил об
@@ -198,7 +201,7 @@ func main() {
// Наши маршруты живут на роутере хранилища: панель отдаётся тем же портом,
// и второму серверу на нём взяться неоткуда.
transcribeHandler := httpcontroller.NewTranscribeHandler(jobRepo, transcribeService, logger)
transcribeHandler := httpcontroller.NewTranscribeHandler(recordRepo, repos.Texts, transcribeService, logger)
authHandler := httpcontroller.NewAuthHandler(storage, httpcontroller.AuthHandlerConfig{
AuthURL: cfg.Auth.AuthURL,
RedirectURL: cfg.Auth.RedirectURL,
@@ -291,8 +294,7 @@ func main() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
logger.Info("Transcriber service started with background workers")
logger.Info("Workers: ConversionWorker, TranscribeWorker, CheckWorker")
logger.Info("Transcriber service started", "pipeline_workers", pool.Size())
logger.Info("Press Ctrl+C to stop...")
// Ждем сигнал завершения либо отказ сервера