refactor(annotations): AnnotationService is a required constructor dependency
H1's doctrine applied to the annotation service, which had been left on setters: NewMediaHandler/NewKoboHandler/NewKOReaderHandler/ NewSyncQueueProcessor(WithConfig) now take it as a parameter; the four SetAnnotationService setters are deleted; wiring updated (main.go, router/sync.go, test harness). With the service unskippable, the 18 nil-guards and their plain-query fallbacks die: - media.go: the create fallbacks for notes/highlights/bookmarks (the bookmark one was the H3 census's Bug #1 — it dropped percentage/chapter_reference the sync path carries), the highlight PUT fallback, and the three delete-path plain deletes (tombstone is now the only delete semantics). - kobo.go: both markup-ingest annotation loops (the bookmark fallback wrote the text into media_notes — a category error the fallback never should have had). - koreader.go: all three push-stack guards. - queue.go: the three "annotation service not available" errors in syncNote/syncHighlight/syncBookmark. Behavior note: the deleted highlight create/PUT fallbacks were the only paths passing note_id to the plain query — the sync service has no NoteID field, so the web's highlight→note link was already being dropped on the live path; this commit makes that pre-existing limitation explicit rather than papering it over (surfacing note_id on SaveHighlightRequest is left for a behavior commit that needs it). Pins (now 20 incl. the 3 annotation CRUD suites) + H1 tests + both unit suites green.
This commit is contained in:
1 parent
ff029f1ad5
commit
c579179fee
9 files changed
+290
-564
No files matched your search
+9
-24
@@ -76,27 +76,24 @@ type SyncQueueItem struct {
|
||||
// NewSyncQueueProcessor requires the shared ProgressService — queue
|
||||
// progress entries flush through SaveProgress (the LWW-seeded canonical
|
||||
// writer); a nil service has nowhere to fall back to and must not be wired.
|
||||
func NewSyncQueueProcessor(db *database.Queries, progressSvc *ProgressService) *SyncQueueProcessor {
|
||||
return NewSyncQueueProcessorWithConfig(db, progressSvc, 5*time.Second, 50)
|
||||
func NewSyncQueueProcessor(db *database.Queries, progressSvc *ProgressService, annotationSvc *AnnotationService) *SyncQueueProcessor {
|
||||
return NewSyncQueueProcessorWithConfig(db, progressSvc, annotationSvc, 5*time.Second, 50)
|
||||
}
|
||||
|
||||
// NewSyncQueueProcessorWithConfig constructs a processor with the given flush
|
||||
// interval and batch size. Used at startup to source values from the settings
|
||||
// registry.
|
||||
func NewSyncQueueProcessorWithConfig(db *database.Queries, progressSvc *ProgressService, interval time.Duration, batchSize int) *SyncQueueProcessor {
|
||||
func NewSyncQueueProcessorWithConfig(db *database.Queries, progressSvc *ProgressService, annotationSvc *AnnotationService, interval time.Duration, batchSize int) *SyncQueueProcessor {
|
||||
return &SyncQueueProcessor{
|
||||
db: db,
|
||||
progressSvc: progressSvc,
|
||||
progressChan: make(chan *ProgressUpdate, 100),
|
||||
interval: interval,
|
||||
batchSize: batchSize,
|
||||
db: db,
|
||||
progressSvc: progressSvc,
|
||||
annotationSvc: annotationSvc,
|
||||
progressChan: make(chan *ProgressUpdate, 100),
|
||||
interval: interval,
|
||||
batchSize: batchSize,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) SetAnnotationService(svc *AnnotationService) {
|
||||
p.annotationSvc = svc
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) Start(ctx context.Context) {
|
||||
log.Printf("Starting sync queue processor (interval: %v, batch: %d)", p.interval, p.batchSize)
|
||||
|
||||
@@ -461,10 +458,6 @@ func (p *SyncQueueProcessor) syncProgress(ctx context.Context, userID pgtype.UUI
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) syncNote(ctx context.Context, userID pgtype.UUID, mediaItemID pgtype.UUID, syncData map[string]interface{}) error {
|
||||
if p.annotationSvc == nil {
|
||||
return fmt.Errorf("annotation service not available")
|
||||
}
|
||||
|
||||
req := SaveNoteRequest{
|
||||
MediaItemID: mediaItemID,
|
||||
UserID: userID,
|
||||
@@ -497,10 +490,6 @@ func (p *SyncQueueProcessor) syncNote(ctx context.Context, userID pgtype.UUID, m
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) syncHighlight(ctx context.Context, userID pgtype.UUID, mediaItemID pgtype.UUID, syncData map[string]interface{}) error {
|
||||
if p.annotationSvc == nil {
|
||||
return fmt.Errorf("annotation service not available")
|
||||
}
|
||||
|
||||
req := SaveHighlightRequest{
|
||||
MediaItemID: mediaItemID,
|
||||
UserID: userID,
|
||||
@@ -548,10 +537,6 @@ func (p *SyncQueueProcessor) syncHighlight(ctx context.Context, userID pgtype.UU
|
||||
}
|
||||
|
||||
func (p *SyncQueueProcessor) syncBookmark(ctx context.Context, userID pgtype.UUID, mediaItemID pgtype.UUID, syncData map[string]interface{}) error {
|
||||
if p.annotationSvc == nil {
|
||||
return fmt.Errorf("annotation service not available")
|
||||
}
|
||||
|
||||
req := SaveBookmarkRequest{
|
||||
MediaItemID: mediaItemID,
|
||||
UserID: userID,
|
||||
|
||||
Reference in new issue
Block a user