package filemanager import ( "context" "errors" "strings" "time" "gorm.io/gorm" "wucher/internal/shared/pkg/uuidv7" ) type FileStatusRealtimeEventInput struct { FileID []byte UserID []byte Status string Name string FailureReason string OccurredAt time.Time } type FileStatusRealtimeEventWriter interface { CreateFileStatusRealtimeEvent(ctx context.Context, input FileStatusRealtimeEventInput) error } type FileStatusRealtimeEvent struct { ID []byte `gorm:"type:binary(16);primaryKey;column:id"` FileID []byte `gorm:"type:binary(16);index;not null;column:file_id"` UserID []byte `gorm:"type:binary(16);index;not null;column:user_id"` Status string `gorm:"type:varchar(32);index;not null;column:status"` Name string `gorm:"type:varchar(255);not null;column:name"` FailureReason string `gorm:"type:text;column:failure_reason"` OccurredAt time.Time `gorm:"index;not null;column:occurred_at"` DeliveredAt *time.Time `gorm:"index;column:delivered_at"` CreatedAt time.Time `gorm:"column:created_at"` UpdatedAt time.Time `gorm:"column:updated_at"` } func (FileStatusRealtimeEvent) TableName() string { return "file_status_realtime_events" } func (e *FileStatusRealtimeEvent) BeforeCreate(_ *gorm.DB) error { if len(e.ID) == 0 { e.ID = uuidv7.MustBytes() } if e.OccurredAt.IsZero() { e.OccurredAt = time.Now().UTC() } return nil } func NewFileStatusRealtimeEvent(input FileStatusRealtimeEventInput) (*FileStatusRealtimeEvent, error) { if len(input.FileID) != 16 { return nil, errors.New("file id must be uuid bytes") } if len(input.UserID) != 16 { return nil, errors.New("user id must be uuid bytes") } status := NormalizeFileStatus(input.Status) if !IsKnownFileStatus(status) { return nil, errors.New("invalid status") } occurredAt := input.OccurredAt.UTC() if input.OccurredAt.IsZero() { occurredAt = time.Now().UTC() } return &FileStatusRealtimeEvent{ FileID: append([]byte(nil), input.FileID...), UserID: append([]byte(nil), input.UserID...), Status: status, Name: strings.TrimSpace(input.Name), FailureReason: strings.TrimSpace(input.FailureReason), OccurredAt: occurredAt, }, nil }