feat: Implement video workflow repository and related services

- Added videoWorkflowRepository with methods to manage video and user interactions.
- Introduced catalog_mapper for converting database models to protobuf representations.
- Created domain_helpers for normalizing domain and ad format values.
- Defined service interfaces for payment, account, notification, domain, ad template, player config, video, and user management.
- Implemented OAuth helpers for generating state and caching keys.
- Developed payment_proto_helpers for mapping payment-related models to protobuf.
- Added service policy helpers to enforce plan requirements and user permissions.
- Created user_mapper for converting user payloads to protobuf format.
- Implemented value_helpers for handling various value conversions and nil checks.
- Developed video_helpers for normalizing video statuses and managing storage types.
- Created video_mapper for mapping video models to protobuf format.
- Implemented render workflow for managing video creation and job processing.
This commit is contained in:
2026-03-26 18:38:47 +07:00
parent fbbecd7674
commit a0ae2b681a
55 changed files with 3464 additions and 13091 deletions

View File

@@ -0,0 +1,102 @@
package repository
import (
"context"
"strconv"
"strings"
"time"
"gorm.io/gorm"
"stream.api/internal/database/model"
"stream.api/internal/database/query"
)
type jobRepository struct {
db *gorm.DB
}
func NewJobRepository(db *gorm.DB) *jobRepository {
return &jobRepository{db: db}
}
func (r *jobRepository) ListByOffset(ctx context.Context, agentID string, offset int, limit int) ([]*model.Job, int64, error) {
q := query.Job.WithContext(ctx).Order(query.Job.CreatedAt.Desc(), query.Job.ID.Desc())
if trimmedAgentID := strings.TrimSpace(agentID); trimmedAgentID != "" {
agentNumeric, err := strconv.ParseInt(trimmedAgentID, 10, 64)
if err != nil {
return []*model.Job{}, 0, nil
}
q = q.Where(query.Job.AgentID.Eq(agentNumeric))
}
jobs, total, err := q.FindByPage(offset, limit)
if err != nil {
return nil, 0, err
}
items := make([]*model.Job, 0, len(jobs))
for _, job := range jobs {
items = append(items, job)
}
return items, total, nil
}
func (r *jobRepository) ListByCursor(ctx context.Context, agentID string, cursorTime time.Time, cursorID string, limit int) ([]*model.Job, bool, error) {
q := query.Job.WithContext(ctx).Order(query.Job.CreatedAt.Desc(), query.Job.ID.Desc())
if trimmedAgentID := strings.TrimSpace(agentID); trimmedAgentID != "" {
agentNumeric, err := strconv.ParseInt(trimmedAgentID, 10, 64)
if err != nil {
return []*model.Job{}, false, nil
}
q = q.Where(query.Job.AgentID.Eq(agentNumeric))
}
queryDB := q.UnderlyingDB()
if !cursorTime.IsZero() && strings.TrimSpace(cursorID) != "" {
queryDB = queryDB.Where("(created_at < ?) OR (created_at = ? AND id < ?)", cursorTime, cursorTime, strings.TrimSpace(cursorID))
}
var jobs []*model.Job
if err := queryDB.Limit(limit + 1).Find(&jobs).Error; err != nil {
return nil, false, err
}
hasMore := len(jobs) > limit
if hasMore {
jobs = jobs[:limit]
}
return jobs, hasMore, nil
}
func (r *jobRepository) Create(ctx context.Context, job *model.Job) error {
return query.Job.WithContext(ctx).Create(job)
}
func (r *jobRepository) GetByID(ctx context.Context, id string) (*model.Job, error) {
return query.Job.WithContext(ctx).Where(query.Job.ID.Eq(strings.TrimSpace(id))).First()
}
func (r *jobRepository) Save(ctx context.Context, job *model.Job) error {
return query.Job.WithContext(ctx).Save(job)
}
func (r *jobRepository) UpdateVideoStatus(ctx context.Context, videoID string, statusValue string, processingStatus string) error {
videoID = strings.TrimSpace(videoID)
if videoID == "" {
return nil
}
_, err := query.Video.WithContext(ctx).
Where(query.Video.ID.Eq(videoID)).
Updates(map[string]any{"status": statusValue, "processing_status": processingStatus})
return err
}
func (r *jobRepository) GetLatestByVideoID(ctx context.Context, videoID string) (*model.Job, error) {
var job model.Job
if err := r.db.WithContext(ctx).
Where("config::jsonb ->> 'video_id' = ?", strings.TrimSpace(videoID)).
Order("created_at DESC").
First(&job).Error; err != nil {
return nil, err
}
return &job, nil
}