169 lines
5.5 KiB
Go
169 lines
5.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// CaptainDocumentRepo provides data access for CaptainDocument.
|
|
type CaptainDocumentRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewCaptainDocumentRepo(db *gorm.DB) *CaptainDocumentRepo {
|
|
return &CaptainDocumentRepo{db: db}
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) DB() *gorm.DB {
|
|
return r.db
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) Create(ctx context.Context, doc *model.CaptainDocument) error {
|
|
return r.db.WithContext(ctx).Create(doc).Error
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) GetByID(ctx context.Context, id uint) (*model.CaptainDocument, error) {
|
|
var doc model.CaptainDocument
|
|
if err := r.db.WithContext(ctx).Preload("Assistant").First(&doc, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) GetByAccountAndID(ctx context.Context, accountID, id uint) (*model.CaptainDocument, error) {
|
|
var doc model.CaptainDocument
|
|
if err := r.db.WithContext(ctx).Preload("Assistant").Where("account_id = ? AND id = ?", accountID, id).First(&doc).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) Update(ctx context.Context, doc *model.CaptainDocument) error {
|
|
return r.db.WithContext(ctx).Save(doc).Error
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) Delete(ctx context.Context, id uint) error {
|
|
return r.db.WithContext(ctx).Delete(&model.CaptainDocument{}, id).Error
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) DeleteByAccount(ctx context.Context, accountID, id uint) error {
|
|
return r.db.WithContext(ctx).Where("account_id = ? AND id = ?", accountID, id).Delete(&model.CaptainDocument{}).Error
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) ListByAssistant(ctx context.Context, assistantID uint, offset, limit int) ([]model.CaptainDocument, int64, error) {
|
|
var docs []model.CaptainDocument
|
|
var count int64
|
|
db := r.db.WithContext(ctx).Model(&model.CaptainDocument{}).Where("assistant_id = ?", assistantID)
|
|
db.Count(&count)
|
|
if err := db.Preload("Assistant").Offset(offset).Limit(limit).Find(&docs).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return docs, count, nil
|
|
}
|
|
|
|
type CaptainDocumentListFilters struct {
|
|
AssistantID uint
|
|
Source string
|
|
Filter string
|
|
SearchKey string
|
|
Sort string
|
|
Offset int
|
|
Limit int
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) ListByAccount(ctx context.Context, accountID uint, filters CaptainDocumentListFilters) ([]model.CaptainDocument, int64, error) {
|
|
var docs []model.CaptainDocument
|
|
var count int64
|
|
db := r.db.WithContext(ctx).Model(&model.CaptainDocument{}).Where("account_id = ?", accountID)
|
|
if filters.AssistantID > 0 {
|
|
db = db.Where("assistant_id = ?", filters.AssistantID)
|
|
}
|
|
switch filters.Source {
|
|
case "web":
|
|
db = db.Where("external_link <> ''")
|
|
case "pdf":
|
|
db = db.Where("external_link = ''")
|
|
}
|
|
switch filters.Filter {
|
|
case "syncing":
|
|
db = db.Where("sync_status = ?", model.DocumentSyncStatusPending)
|
|
case "failed":
|
|
db = db.Where("sync_status = ?", model.DocumentSyncStatusFailed)
|
|
case "synced":
|
|
db = db.Where("sync_status = ?", model.DocumentSyncStatusSynced)
|
|
}
|
|
if filters.SearchKey != "" {
|
|
query := "%" + strings.ToLower(filters.SearchKey) + "%"
|
|
db = db.Where("LOWER(name) LIKE ? OR LOWER(external_link) LIKE ?", query, query)
|
|
}
|
|
if err := db.Count(&count).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
order := "updated_at DESC"
|
|
if filters.Sort == "recently_created" {
|
|
order = "created_at DESC"
|
|
}
|
|
if filters.Limit <= 0 {
|
|
filters.Limit = 25
|
|
}
|
|
if err := db.Preload("Assistant").Order(order).Offset(filters.Offset).Limit(filters.Limit).Find(&docs).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return docs, count, nil
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) FindByExternalLink(ctx context.Context, assistantID uint, externalLink string) (*model.CaptainDocument, error) {
|
|
var doc model.CaptainDocument
|
|
if err := r.db.WithContext(ctx).Where("assistant_id = ? AND external_link = ?", assistantID, externalLink).First(&doc).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *CaptainDocumentRepo) ListDueForAutoSync(ctx context.Context, now time.Time, interval, staleTimeout time.Duration, limit int) ([]model.CaptainDocument, error) {
|
|
if interval <= 0 {
|
|
interval = 24 * time.Hour
|
|
}
|
|
if staleTimeout <= 0 {
|
|
staleTimeout = 10 * time.Minute
|
|
}
|
|
if limit <= 0 {
|
|
limit = 1000
|
|
}
|
|
syncDueBefore := now.Add(-interval / 2).Unix()
|
|
staleCutoff := now.Add(-staleTimeout).Unix()
|
|
|
|
var docs []model.CaptainDocument
|
|
err := r.db.WithContext(ctx).
|
|
Model(&model.CaptainDocument{}).
|
|
Where("status = ?", model.DocumentStatusCompleted).
|
|
Where(
|
|
"(sync_status = ? AND (last_synced_at IS NULL OR last_synced_at < ?)) OR "+
|
|
"(sync_status = ? AND (last_sync_attempted_at IS NULL OR last_sync_attempted_at < ?)) OR "+
|
|
"(sync_status = ? AND last_sync_attempted_at < ?)",
|
|
model.DocumentSyncStatusSynced, syncDueBefore,
|
|
model.DocumentSyncStatusFailed, syncDueBefore,
|
|
model.DocumentSyncStatusPending, staleCutoff,
|
|
).
|
|
Order("last_sync_attempted_at ASC, id ASC").
|
|
Limit(limit).
|
|
Find(&docs).Error
|
|
return docs, err
|
|
}
|
|
|
|
// FindByStatus retrieves documents matching a specific status.
|
|
func (r *CaptainDocumentRepo) FindByStatus(ctx context.Context, assistantID uint, status model.DocumentStatus, offset, limit int) ([]model.CaptainDocument, int64, error) {
|
|
var docs []model.CaptainDocument
|
|
var count int64
|
|
db := r.db.WithContext(ctx).Model(&model.CaptainDocument{}).Where("assistant_id = ? AND status = ?", assistantID, status)
|
|
db.Count(&count)
|
|
if err := db.Offset(offset).Limit(limit).Find(&docs).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return docs, count, nil
|
|
}
|