package sqlite import ( "database/sql" "fmt" "time" "git.vakhrushev.me/av/transcriber/internal/entity" "github.com/doug-martin/goqu/v9" ) type TranscriptJobRepository struct { db *sql.DB gq *goqu.Database } func NewTranscriptJobRepository(db *sql.DB, gq *goqu.Database) *TranscriptJobRepository { return &TranscriptJobRepository{db, gq} } func (repo *TranscriptJobRepository) Create(job *entity.TranscribeJob) error { record := goqu.Record{ "id": job.Id, "state": job.State, "file_id": job.FileID, "is_error": job.IsError, "error_text": job.ErrorText, "acquisition_id": job.AcquisitionID, "acquire_time": job.AcquireTime, "delay_time": job.DelayTime, "recognition_op_id": job.RecognitionOpID, "transcription_text": job.TranscriptionText, "created_at": job.CreatedAt, "updated_at": job.UpdatedAt, } query := repo.gq.Insert("transcribe_jobs").Rows(record) sql, args, err := query.ToSQL() if err != nil { return fmt.Errorf("failed to build query: %w", err) } _, err = repo.db.Exec(sql, args...) if err != nil { return fmt.Errorf("failed to insert transcribe job: %w", err) } return nil } func (repo *TranscriptJobRepository) Save(job *entity.TranscribeJob) error { record := goqu.Record{ "state": job.State, "file_id": job.FileID, "is_error": job.IsError, "error_text": job.ErrorText, "acquisition_id": job.AcquisitionID, "acquire_time": job.AcquireTime, "delay_time": job.DelayTime, "recognition_op_id": job.RecognitionOpID, "transcription_text": job.TranscriptionText, "updated_at": job.UpdatedAt, } query := repo.gq.Update("transcribe_jobs").Set(record).Where(goqu.C("id").Eq(job.Id)) sql, args, err := query.ToSQL() if err != nil { return fmt.Errorf("failed to build query: %w", err) } _, err = repo.db.Exec(sql, args...) if err != nil { return fmt.Errorf("failed to update transcribe job: %w", err) } return nil } func (repo *TranscriptJobRepository) GetByID(id string) (*entity.TranscribeJob, error) { query := repo.gq.From("transcribe_jobs").Select( "id", "state", "file_id", "is_error", "error_text", "acquisition_id", "acquire_time", "delay_time", "recognition_op_id", "transcription_text", "created_at", "updated_at", ).Where(goqu.C("id").Eq(id)) sql, args, err := query.ToSQL() if err != nil { return nil, fmt.Errorf("failed to build query: %w", err) } var job entity.TranscribeJob err = repo.db.QueryRow(sql, args...).Scan( &job.Id, &job.State, &job.FileID, &job.IsError, &job.ErrorText, &job.AcquisitionID, &job.AcquireTime, &job.DelayTime, &job.RecognitionOpID, &job.TranscriptionText, &job.CreatedAt, &job.UpdatedAt, ) if err != nil { return nil, fmt.Errorf("failed to get transcribe job: %w", err) } return &job, nil } func (repo *TranscriptJobRepository) FindAndAcquire(state, acquisitionId string, rottingTime time.Time) (*entity.TranscribeJob, error) { updateQuery := repo.gq.Update("transcribe_jobs"). Set( goqu.Record{ "acquisition_id": acquisitionId, "acquire_time": time.Now(), }, ). Where( goqu.C("id").Eq( repo.gq.From("transcribe_jobs").Select("id"). Where( goqu.And( goqu.C("state").Eq(state), goqu.C("is_error").Eq(0), goqu.Or( goqu.C("delay_time").IsNull(), goqu.C("delay_time").Lt(time.Now()), ), goqu.Or( goqu.C("acquisition_id").IsNull(), goqu.C("acquire_time").Lt(rottingTime), ), ), ). Limit(1), ), ) sql, args, err := updateQuery.ToSQL() if err != nil { return nil, fmt.Errorf("failed to build query: %w", err) } // log.Printf("aquire sql: %s", sql) result, err := repo.db.Exec(sql, args...) if err != nil { return nil, fmt.Errorf("failed to aquire job with state %s: %w", state, err) } rowsAffected, err := result.RowsAffected() if err != nil { return nil, fmt.Errorf("failed check affected rows: %w", err) } if rowsAffected != 1 { return nil, fmt.Errorf("unexpected affected rows count: %d", rowsAffected) } selectQuery := repo.gq.From("transcribe_jobs").Select( "id", "state", "file_id", "is_error", "error_text", "acquisition_id", "acquire_time", "delay_time", "recognition_op_id", "transcription_text", "created_at", "updated_at", ).Where(goqu.C("acquisition_id").Eq(acquisitionId)) sql, args, err = selectQuery.ToSQL() if err != nil { return nil, fmt.Errorf("failed to build query: %w", err) } var job entity.TranscribeJob err = repo.db.QueryRow(sql, args...).Scan( &job.Id, &job.State, &job.FileID, &job.IsError, &job.ErrorText, &job.AcquisitionID, &job.AcquireTime, &job.DelayTime, &job.RecognitionOpID, &job.TranscriptionText, &job.CreatedAt, &job.UpdatedAt, ) if err != nil { return nil, fmt.Errorf("failed to get transcribe job: %w", err) } return &job, nil }