113 lines
3.2 KiB
Go
113 lines
3.2 KiB
Go
// Package dao 提供 transcribe 模块的数据库访问操作
|
||
package dao
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"time"
|
||
|
||
"github.com/echochat/backend/app/transcribe/model"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// TranscriptDAO 转写记录数据访问对象(PostgreSQL 主库)
|
||
type TranscriptDAO struct {
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewTranscriptDAO 创建实例
|
||
func NewTranscriptDAO(db *gorm.DB) *TranscriptDAO {
|
||
return &TranscriptDAO{db: db}
|
||
}
|
||
|
||
// GetByRecordingID 按 recording_id 获取转写记录(不存在返回 nil, nil)
|
||
//
|
||
// 之所以 nil 不视为错误:调用方常见模式是"取不到 → 创建新行",避免 ErrRecordNotFound 包装
|
||
func (d *TranscriptDAO) GetByRecordingID(ctx context.Context, recordingID int64) (*model.Transcript, error) {
|
||
var t model.Transcript
|
||
err := d.db.WithContext(ctx).
|
||
Where("recording_id = ?", recordingID).
|
||
First(&t).Error
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
return &t, nil
|
||
}
|
||
|
||
// ListByRoomID 拉取一场会议下所有转写(按 recording_id 升序)
|
||
// 用于会议详情页一次性带回多段录制的转写状态
|
||
func (d *TranscriptDAO) ListByRoomID(ctx context.Context, roomID int64) ([]model.Transcript, error) {
|
||
var list []model.Transcript
|
||
err := d.db.WithContext(ctx).
|
||
Where("room_id = ?", roomID).
|
||
Order("recording_id ASC").
|
||
Find(&list).Error
|
||
return list, err
|
||
}
|
||
|
||
// Upsert 插入或更新(按 recording_id unique 索引)
|
||
// 用于"重新转写"路径:保留同一行 ID,状态/文本就地刷新
|
||
func (d *TranscriptDAO) Upsert(ctx context.Context, t *model.Transcript) error {
|
||
existing, err := d.GetByRecordingID(ctx, t.RecordingID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if existing == nil {
|
||
return d.db.WithContext(ctx).Create(t).Error
|
||
}
|
||
t.ID = existing.ID
|
||
return d.db.WithContext(ctx).Save(t).Error
|
||
}
|
||
|
||
// MarkRunning 把指定 transcript 置为 running 状态,并填 started_at = now
|
||
//
|
||
// 用于异步任务起跑时的状态翻转,保证后端重启时 running 行不会卡死
|
||
// (配合 RescueStuckRunning 兜底)。
|
||
func (d *TranscriptDAO) MarkRunning(ctx context.Context, id int64) error {
|
||
now := time.Now()
|
||
return d.db.WithContext(ctx).
|
||
Model(&model.Transcript{}).
|
||
Where("id = ?", id).
|
||
Updates(map[string]any{
|
||
"status": model.TranscriptStatusRunning,
|
||
"started_at": now,
|
||
"error_msg": "",
|
||
}).Error
|
||
}
|
||
|
||
// MarkReady 转写成功
|
||
func (d *TranscriptDAO) MarkReady(ctx context.Context, id int64, text, segments, language string, durationSec int) error {
|
||
now := time.Now()
|
||
return d.db.WithContext(ctx).
|
||
Model(&model.Transcript{}).
|
||
Where("id = ?", id).
|
||
Updates(map[string]any{
|
||
"status": model.TranscriptStatusReady,
|
||
"text": text,
|
||
"segments": segments,
|
||
"language": language,
|
||
"duration_sec": durationSec,
|
||
"finished_at": now,
|
||
"error_msg": "",
|
||
}).Error
|
||
}
|
||
|
||
// MarkFailed 转写失败
|
||
func (d *TranscriptDAO) MarkFailed(ctx context.Context, id int64, errorMsg string) error {
|
||
now := time.Now()
|
||
if len(errorMsg) > 500 {
|
||
errorMsg = errorMsg[:500]
|
||
}
|
||
return d.db.WithContext(ctx).
|
||
Model(&model.Transcript{}).
|
||
Where("id = ?", id).
|
||
Updates(map[string]any{
|
||
"status": model.TranscriptStatusFailed,
|
||
"error_msg": errorMsg,
|
||
"finished_at": now,
|
||
}).Error
|
||
}
|