|
|
@@ -21,17 +21,15 @@ func sessionPreloads(db *gorm.DB) *gorm.DB {
|
|
|
}).Preload("Assets")
|
|
|
}
|
|
|
|
|
|
-// GetSessions supports cursor-like incremental pulls with updatedAfter and can
|
|
|
-// include deletion tombstones for multi-device reconciliation.
|
|
|
+// GetSessions is the lightweight first phase of synchronization. It supports
|
|
|
+// cursor-like incremental pulls and deletion tombstones without preloading
|
|
|
+// concrete event or asset content.
|
|
|
func (h *SessionHandler) GetSessions(c *gin.Context) {
|
|
|
userID := c.GetString("userID")
|
|
|
- query := sessionPreloads(h.DB).Where("user_id = ?", userID)
|
|
|
+ query := h.DB.Where("user_id = ?", userID)
|
|
|
if c.Query("includeDeleted") != "true" {
|
|
|
query = query.Where("deleted_at IS NULL")
|
|
|
}
|
|
|
- if search := c.Query("search"); search != "" {
|
|
|
- query = query.Where("title ILIKE ?", "%"+search+"%")
|
|
|
- }
|
|
|
if value := c.Query("updatedAfter"); value != "" {
|
|
|
updatedAfter, err := time.Parse(time.RFC3339Nano, value)
|
|
|
if err != nil {
|
|
|
@@ -45,7 +43,11 @@ func (h *SessionHandler) GetSessions(c *gin.Context) {
|
|
|
respondError(c, http.StatusInternalServerError, 500, "failed to query field records")
|
|
|
return
|
|
|
}
|
|
|
- respondSuccess(c, sessions)
|
|
|
+ index := make([]models.SessionSyncIndexItem, 0, len(sessions))
|
|
|
+ for _, session := range sessions {
|
|
|
+ index = append(index, session.SyncIndexItem())
|
|
|
+ }
|
|
|
+ respondSuccess(c, index)
|
|
|
}
|
|
|
|
|
|
func (h *SessionHandler) GetSessionDetail(c *gin.Context) {
|
|
|
@@ -152,6 +154,12 @@ func (h *SessionHandler) CreateSession(c *gin.Context) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Events belong to the session's sync unit, so advance its timestamp
|
|
|
+ // after all event upserts/deletions have completed.
|
|
|
+ if err := tx.Model(&session).Update("updated_at", gorm.Expr("NOW()")).Error; err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
return nil
|
|
|
})
|
|
|
if isConflict {
|
|
|
@@ -238,7 +246,10 @@ func (h *SessionHandler) AddEventToSession(c *gin.Context) {
|
|
|
respondError(c, http.StatusInternalServerError, 500, "failed to add event")
|
|
|
return
|
|
|
}
|
|
|
- h.DB.Model(&session).Updates(map[string]interface{}{"revision": gorm.Expr("revision + 1")})
|
|
|
+ h.DB.Model(&session).Updates(map[string]interface{}{
|
|
|
+ "revision": gorm.Expr("revision + 1"),
|
|
|
+ "updated_at": gorm.Expr("NOW()"),
|
|
|
+ })
|
|
|
respondSuccess(c, event)
|
|
|
}
|
|
|
|
|
|
@@ -249,7 +260,11 @@ func (h *SessionHandler) DeleteSession(c *gin.Context) {
|
|
|
now := time.Now().UTC()
|
|
|
result := h.DB.Model(&models.CelestiaSession{}).
|
|
|
Where("id = ? AND user_id = ? AND deleted_at IS NULL", sessionID, userID).
|
|
|
- Updates(map[string]interface{}{"deleted_at": &now, "revision": gorm.Expr("revision + 1")})
|
|
|
+ Updates(map[string]interface{}{
|
|
|
+ "deleted_at": &now,
|
|
|
+ "revision": gorm.Expr("revision + 1"),
|
|
|
+ "updated_at": gorm.Expr("NOW()"),
|
|
|
+ })
|
|
|
if result.Error != nil {
|
|
|
respondError(c, http.StatusInternalServerError, 500, "failed to delete record")
|
|
|
return
|