feat(handlers): integrate ProgressService into media, koreader, kobo, and queue
All four progress write paths now delegate to ProgressService.SaveProgress: - MediaHandler: UpdateMediaReadingProgress uses ProgressService for web saves with richer request body (reading_mode, zoom_level, scroll). GET now uses GetUniversalProgress query that JOINs media_items for format_group, total_characters, chapter_count. - KOReaderHandler: updateProgressForBook delegates to ProgressService. Fixed device ID bug (was using userID, now uses deviceID). Removed duplicate UpdateDeviceLastSync with zero UUID. Added pgtype helper functions (textPtrToPgText, intPtrToPgInt4, int64PtrToPgInt8). - KoboHandler: all four progress write points (Markup ReadingSync, Markup last-read-place, AnalyticsGettests, SyncFromServer) delegate to ProgressService. Fixed empty epubcfi string now correctly set to Valid: false. SyncFromServer preserves last_sync_source=bookhoard and Broadcast: false. - QueueProcessor: syncProgress delegates to ProgressService. - main.go: creates ProgressService after ConnectionManager, injects via SetProgressService() on all handlers and queue processor. Handler tests cover pgtype conversion helpers (textPtrToPgText, etc.) and device icon mapping.
This commit is contained in:
+41
-5
@@ -36,6 +36,7 @@ const (
|
||||
|
||||
type SyncQueueProcessor struct {
|
||||
db *database.Queries
|
||||
progressSvc *ProgressService
|
||||
progressChan chan *ProgressUpdate
|
||||
interval time.Duration
|
||||
batchSize int
|
||||
@@ -79,6 +80,10 @@ func NewSyncQueueProcessor(db *database.Queries) *SyncQueueProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) SetProgressService(svc *ProgressService) {
|
||||
p.progressSvc = svc
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) Start(ctx context.Context) {
|
||||
log.Printf("Starting sync queue processor (interval: %v, batch: %d)", p.interval, p.batchSize)
|
||||
|
||||
@@ -310,6 +315,42 @@ func (p *SyncQueueProcessor) syncProgress(ctx context.Context, userID pgtype.UUI
|
||||
return fmt.Errorf("missing percentage in sync data")
|
||||
}
|
||||
|
||||
source := "queue"
|
||||
if v, ok := syncData["source"].(string); ok {
|
||||
source = v
|
||||
}
|
||||
|
||||
if p.progressSvc != nil {
|
||||
req := SaveProgressRequest{
|
||||
MediaItemID: mediaItemID,
|
||||
UserID: userID,
|
||||
Source: source,
|
||||
Percentage: &percentage,
|
||||
Broadcast: false,
|
||||
}
|
||||
if v, ok := syncData["epubcfi"].(string); ok {
|
||||
req.Epubcfi = &v
|
||||
}
|
||||
if v, ok := syncData["chapter"].(float64); ok {
|
||||
ch := int(v)
|
||||
req.Chapter = &ch
|
||||
}
|
||||
if v, ok := syncData["character"].(float64); ok {
|
||||
co := int64(v)
|
||||
req.CharacterOffset = &co
|
||||
}
|
||||
if v, ok := syncData["page"].(float64); ok {
|
||||
pg := int(v)
|
||||
req.CurrentPage = &pg
|
||||
}
|
||||
if v, ok := syncData["total_pages"].(float64); ok {
|
||||
tp := int(v)
|
||||
req.TotalPages = &tp
|
||||
}
|
||||
_, err := p.progressSvc.SaveProgress(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
var epubcfi pgtype.Text
|
||||
if v, ok := syncData["epubcfi"].(string); ok {
|
||||
epubcfi = pgtype.Text{String: v, Valid: true}
|
||||
@@ -335,11 +376,6 @@ func (p *SyncQueueProcessor) syncProgress(ctx context.Context, userID pgtype.UUI
|
||||
totalPages = pgtype.Int4{Int32: int32(v), Valid: true}
|
||||
}
|
||||
|
||||
source := "queue"
|
||||
if v, ok := syncData["source"].(string); ok {
|
||||
source = v
|
||||
}
|
||||
|
||||
_, err := p.db.UpdateUniversalProgress(ctx, database.UpdateUniversalProgressParams{
|
||||
MediaItemID: mediaItemID,
|
||||
UserID: userID,
|
||||
|
||||
Reference in New Issue
Block a user