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:
2026-04-25 21:16:29 -04:00
parent f699899408
commit 283b2f2ed7
6 changed files with 415 additions and 237 deletions
+6 -3
View File
@@ -62,8 +62,10 @@ func main() {
// Create WebSocket connection manager
connManager := sync.NewConnectionManager()
// Create sync queue processor
progressService := sync.NewProgressService(queries, connManager)
queueProcessor := sync.NewSyncQueueProcessor(queries)
queueProcessor.SetProgressService(progressService)
// Create library service
libraryService := services.NewLibraryService(queries)
@@ -73,21 +75,21 @@ func main() {
services.WorkerInstance = worker
koreaderHandler := handlers.NewKOReaderHandler(queries, connManager, queueProcessor)
koreaderHandler.SetProgressService(progressService)
wsHandler := handlers.NewWSHandler(queries, connManager, cfg.JWTSecret, deviceAuthMiddleware)
conflictHandler := handlers.NewConflictHandler(queries, connManager)
analyticsHandler := handlers.NewAnalyticsHandler(queries)
queueHandler := handlers.NewQueueHandler(queries, queueProcessor)
// Create conversion service for EPUB→KEPUB conversion
conversionService := services.NewConversionService(queries, "/var/bookhoard/cache/kepub")
opdsHandler := handlers.NewOPDSHandler(queries, libraryService, conversionService)
// NEW: Create refactored handlers
collectionHandler := handlers.NewCollectionHandler(queries, libraryService, connManager)
dashboardService := services.NewDashboardService(queries)
dashboardHandler := handlers.NewDashboardHandler(queries)
filtersHandler := handlers.NewFiltersHandler(queries)
mediaHandler := handlers.NewMediaHandler(queries, libraryService, worker)
mediaHandler.SetProgressService(progressService)
matchingHandler := handlers.NewMatchingHandler(queries, connManager)
jobsHandler := handlers.NewJobsHandler(queries, worker)
@@ -153,6 +155,7 @@ func main() {
SidecarHandler: sidecarHandler,
ConnManager: connManager,
QueueProcessor: queueProcessor,
ProgressService: progressService,
DeviceAuthMiddleware: deviceAuthMiddleware,
JobsHandler: jobsHandler,
LoginTracker: loginAttemptTracker,