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
+88
-170
@@ -26,12 +26,8 @@ type KoboHandler struct {
|
||||
bookResolver *services.BookResolver
|
||||
}
|
||||
|
||||
func NewKoboHandler(db *database.Queries, connManager *wsync.ConnectionManager, progressSvc *wsync.ProgressService) *KoboHandler {
|
||||
return &KoboHandler{db: db, connManager: connManager, progressSvc: progressSvc, bookResolver: services.NewBookResolver(db)}
|
||||
}
|
||||
|
||||
func (h *KoboHandler) SetAnnotationService(svc *wsync.AnnotationService) {
|
||||
h.annotationSvc = svc
|
||||
func NewKoboHandler(db *database.Queries, connManager *wsync.ConnectionManager, progressSvc *wsync.ProgressService, annotationSvc *wsync.AnnotationService) *KoboHandler {
|
||||
return &KoboHandler{db: db, connManager: connManager, progressSvc: progressSvc, annotationSvc: annotationSvc, bookResolver: services.NewBookResolver(db)}
|
||||
}
|
||||
|
||||
func (h *KoboHandler) SetLibraryService(svc LibraryPathResolver) {
|
||||
@@ -475,65 +471,43 @@ func (h *KoboHandler) Markup(c *echo.Context) error {
|
||||
switch bookmarkSync.BookmarkType {
|
||||
case "annotation":
|
||||
if bookmarkSync.BookmarkText != "" {
|
||||
if h.annotationSvc != nil {
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: bookmarkSync.BookmarkId,
|
||||
EndPosition: bookmarkSync.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
NoteText: bookmarkSync.BookmarkTitle,
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaHighlight(c.Request().Context(), database.CreateMediaHighlightParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
EndPosition: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
Color: pgtype.Text{String: "#ffff00", Valid: true},
|
||||
})
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: bookmarkSync.BookmarkId,
|
||||
EndPosition: bookmarkSync.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
NoteText: bookmarkSync.BookmarkTitle,
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
}
|
||||
case "bookmark":
|
||||
if bookmarkSync.BookmarkText != "" {
|
||||
if h.annotationSvc != nil {
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmarkSync.BookmarkText,
|
||||
Position: bookmarkSync.BookmarkId,
|
||||
ChapterNumber: int32(bookmarkSync.Chapter),
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaNote(c.Request().Context(), database.CreateMediaNoteParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Content: bookmarkSync.BookmarkText,
|
||||
Position: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
})
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmarkSync.BookmarkText,
|
||||
Position: bookmarkSync.BookmarkId,
|
||||
ChapterNumber: int32(bookmarkSync.Chapter),
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
}
|
||||
@@ -600,7 +574,7 @@ func (h *KoboHandler) Markup(c *echo.Context) error {
|
||||
BookmarksSynced: bookmarksSynced,
|
||||
}
|
||||
|
||||
if h.annotationSvc != nil && len(processedBooks) > 0 {
|
||||
if len(processedBooks) > 0 {
|
||||
cutoff := pgtype.Timestamptz{Time: time.Now().Add(-h.annotationSvc.ActiveTombstoneTTL()), Valid: true}
|
||||
for mediaItemID, contentId := range processedBooks {
|
||||
tombstones, _ := h.db.GetTombstonedAnnotationsForBook(c.Request().Context(), database.GetTombstonedAnnotationsForBookParams{
|
||||
@@ -668,65 +642,43 @@ func (h *KoboHandler) Bookmark(c *echo.Context) error {
|
||||
switch bookmarkSync.BookmarkType {
|
||||
case "annotation":
|
||||
if bookmarkSync.BookmarkText != "" {
|
||||
if h.annotationSvc != nil {
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: bookmarkSync.BookmarkId,
|
||||
EndPosition: bookmarkSync.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
NoteText: bookmarkSync.BookmarkTitle,
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaHighlight(c.Request().Context(), database.CreateMediaHighlightParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
EndPosition: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
Color: pgtype.Text{String: "#ffff00", Valid: true},
|
||||
})
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmarkSync.BookmarkText,
|
||||
StartPosition: bookmarkSync.BookmarkId,
|
||||
EndPosition: bookmarkSync.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
NoteText: bookmarkSync.BookmarkTitle,
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
}
|
||||
case "bookmark":
|
||||
if bookmarkSync.BookmarkText != "" {
|
||||
if h.annotationSvc != nil {
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
deviceData, _ := json.Marshal(map[string]interface{}{
|
||||
"bookmark_id": bookmarkSync.BookmarkId,
|
||||
"date_created": bookmarkSync.DateCreated,
|
||||
})
|
||||
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmarkSync.BookmarkText,
|
||||
Position: bookmarkSync.BookmarkId,
|
||||
ChapterNumber: int32(bookmarkSync.Chapter),
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaNote(c.Request().Context(), database.CreateMediaNoteParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Content: bookmarkSync.BookmarkText,
|
||||
Position: pgtype.Text{String: bookmarkSync.BookmarkId, Valid: true},
|
||||
})
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmarkSync.BookmarkText,
|
||||
Position: bookmarkSync.BookmarkId,
|
||||
ChapterNumber: int32(bookmarkSync.Chapter),
|
||||
Source: "kobo",
|
||||
DeviceSyncData: deviceData,
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSynced++
|
||||
}
|
||||
}
|
||||
@@ -842,77 +794,43 @@ func (h *KoboHandler) SyncFromServer(c *echo.Context) error {
|
||||
|
||||
for _, bookmark := range syncData.Bookmarks {
|
||||
if bookmark.BookmarkType == "bookmark" {
|
||||
if h.annotationSvc != nil {
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmark.BookmarkText,
|
||||
Position: bookmark.BookmarkId,
|
||||
Source: "kobo",
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSent++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaNote(c.Request().Context(), database.CreateMediaNoteParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Content: bookmark.BookmarkText,
|
||||
Position: pgtype.Text{String: bookmark.BookmarkId, Valid: true},
|
||||
})
|
||||
result, err := h.annotationSvc.SaveBookmark(c.Request().Context(), wsync.SaveBookmarkRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
Title: bookmark.BookmarkText,
|
||||
Position: bookmark.BookmarkId,
|
||||
Source: "kobo",
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
bookmarksSent++
|
||||
}
|
||||
} else if bookmark.BookmarkType == "annotation" {
|
||||
if h.annotationSvc != nil {
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmark.BookmarkText,
|
||||
StartPosition: bookmark.BookmarkId,
|
||||
EndPosition: bookmark.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
Source: "kobo",
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
highlightsSent++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaHighlight(c.Request().Context(), database.CreateMediaHighlightParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: bookmark.BookmarkText,
|
||||
StartPosition: pgtype.Text{String: bookmark.BookmarkId, Valid: true},
|
||||
EndPosition: pgtype.Text{String: bookmark.BookmarkId, Valid: true},
|
||||
Color: pgtype.Text{String: "#ffff00", Valid: true},
|
||||
})
|
||||
highlightsSent++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, highlight := range syncData.Highlights {
|
||||
if h.annotationSvc != nil {
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: highlight.BookmarkText,
|
||||
StartPosition: highlight.BookmarkId,
|
||||
EndPosition: highlight.BookmarkId,
|
||||
SelectionText: bookmark.BookmarkText,
|
||||
StartPosition: bookmark.BookmarkId,
|
||||
EndPosition: bookmark.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
Source: "kobo",
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
highlightsSent++
|
||||
}
|
||||
} else {
|
||||
h.db.CreateMediaHighlight(c.Request().Context(), database.CreateMediaHighlightParams{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: highlight.BookmarkText,
|
||||
StartPosition: pgtype.Text{String: highlight.BookmarkId, Valid: true},
|
||||
EndPosition: pgtype.Text{String: highlight.BookmarkId, Valid: true},
|
||||
Color: pgtype.Text{String: "#ffff00", Valid: true},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, highlight := range syncData.Highlights {
|
||||
result, err := h.annotationSvc.SaveHighlight(c.Request().Context(), wsync.SaveHighlightRequest{
|
||||
MediaItemID: pgMediaUUID,
|
||||
UserID: pgUserID,
|
||||
SelectionText: highlight.BookmarkText,
|
||||
StartPosition: highlight.BookmarkId,
|
||||
EndPosition: highlight.BookmarkId,
|
||||
Color: "#ffff00",
|
||||
Source: "kobo",
|
||||
})
|
||||
if err == nil && result.Outcome != wsync.SaveOutcomeDeleted {
|
||||
highlightsSent++
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user