feat(sync): plumb context_text through SaveProgress and sync queue

- SaveProgressRequest: add ContextText field
- SaveProgress: carry existing ContextText from DB, overwrite when provided
- ProgressUpdate: add ContextText field for checkpoint sync
- SyncQueueProcessor: serialize/deserialize context_text in sync data
- buildProgressSnapshot: include context_text in snapshot data
This commit is contained in:
2026-06-02 19:44:38 -04:00
parent c82f20c3f2
commit b2b1804aa3
2 changed files with 39 additions and 20 deletions
+19 -7
View File
@@ -288,6 +288,7 @@ type SaveProgressRequest struct {
Percentage *float64
Epubcfi *string
ContextText *string
CharacterOffset *int64
Chapter *int
ChapterProgress *float64
@@ -334,6 +335,7 @@ func (s *ProgressService) SaveProgress(ctx context.Context, req SaveProgressRequ
params.Percentage = existing.Percentage
params.CharacterOffset = existing.CharacterOffset
params.Epubcfi = existing.Epubcfi
params.ContextText = existing.ContextText
params.Chapter = existing.Chapter
params.ChapterProgress = existing.ChapterProgress
params.ViewportX = existing.ViewportX
@@ -355,6 +357,9 @@ func (s *ProgressService) SaveProgress(ctx context.Context, req SaveProgressRequ
if req.Epubcfi != nil {
params.Epubcfi = pgtype.Text{String: *req.Epubcfi, Valid: *req.Epubcfi != ""}
}
if req.ContextText != nil {
params.ContextText = pgtype.Text{String: *req.ContextText, Valid: *req.ContextText != ""}
}
if req.CharacterOffset != nil {
params.CharacterOffset = pgtype.Int8{Int64: *req.CharacterOffset, Valid: true}
}
@@ -430,11 +435,17 @@ func (s *ProgressService) SaveProgress(ctx context.Context, req SaveProgressRequ
diff = -diff
}
if diff > 0.01 {
recentlyResolved, _ := s.db.HasRecentConflictResolution(ctx, database.HasRecentConflictResolutionParams{
MediaItemID: req.MediaItemID,
UserID: req.UserID,
})
if !recentlyResolved {
conflictDetected = true
}
}
}
}
}
result, err := s.db.UpdateUniversalProgress(ctx, params)
if err != nil {
@@ -442,12 +453,13 @@ func (s *ProgressService) SaveProgress(ctx context.Context, req SaveProgressRequ
}
if conflictDetected {
newData := map[string]interface{}{
conflictData := map[string]interface{}{
req.Source: map[string]interface{}{
"source": req.Source,
"timestamp": time.Now().Format(time.RFC3339),
"data": buildProgressSnapshot(req),
}
existingData := map[string]interface{}{
},
existing.LastSyncSource.String: map[string]interface{}{
"source": existing.LastSyncSource.String,
"timestamp": existing.LastSyncTimestamp.Time.Format(time.RFC3339),
"data": map[string]interface{}{
@@ -458,10 +470,7 @@ func (s *ProgressService) SaveProgress(ctx context.Context, req SaveProgressRequ
"page": int32Ptr(existing.CurrentPage),
"total_pages": int32Ptr(existing.TotalPages),
},
}
conflictData := map[string]interface{}{
"new": newData,
"existing": existingData,
},
}
conflictJSON, _ := json.Marshal(conflictData)
_, err := s.db.CreateSyncConflict(ctx, database.CreateSyncConflictParams{
@@ -508,6 +517,9 @@ func buildProgressSnapshot(req SaveProgressRequest) map[string]interface{} {
if req.Epubcfi != nil {
data["epubcfi"] = *req.Epubcfi
}
if req.ContextText != nil {
data["context_text"] = *req.ContextText
}
if req.Chapter != nil {
data["chapter"] = *req.Chapter
}
+7
View File
@@ -48,6 +48,7 @@ type ProgressUpdate struct {
UserID pgtype.UUID
Percentage float64
Epubcfi *string
ContextText *string
Chapter *int
Character *int64
Page *int
@@ -122,6 +123,9 @@ func (p *SyncQueueProcessor) enqueueProgressUpdate(ctx context.Context, update *
if update.Epubcfi != nil {
syncData["epubcfi"] = *update.Epubcfi
}
if update.ContextText != nil {
syncData["context_text"] = *update.ContextText
}
if update.Chapter != nil {
syncData["chapter"] = *update.Chapter
}
@@ -331,6 +335,9 @@ func (p *SyncQueueProcessor) syncProgress(ctx context.Context, userID pgtype.UUI
if v, ok := syncData["epubcfi"].(string); ok {
req.Epubcfi = &v
}
if v, ok := syncData["context_text"].(string); ok {
req.ContextText = &v
}
if v, ok := syncData["chapter"].(float64); ok {
ch := int(v)
req.Chapter = &ch