Optimize query endpoint so that it applies all deletion requests in one SQL query rather than having a 1-n pattern

This commit is contained in:
David Dworken 2023-10-15 10:19:30 -07:00
parent 211c9fb6b7
commit 151dfb4009
No known key found for this signature in database
2 changed files with 22 additions and 9 deletions

View File

@ -182,11 +182,26 @@ func (db *DB) DumpRequestDeleteForUserAndDevice(ctx context.Context, userID, dev
return nil return nil
} }
func (db *DB) ApplyDeletionRequestsToBackend(ctx context.Context, request *shared.DeletionRequest) (int64, error) { func (db *DB) ApplyDeletionRequestsToBackend(ctx context.Context, requests []*shared.DeletionRequest) (int64, error) {
if len(requests) == 0 {
return 0, nil
}
deletedMessages := make([]shared.MessageIdentifier, 0)
userId := requests[0].UserId
for _, request := range requests {
deletedMessages = append(deletedMessages, request.Messages.Ids...)
if request.UserId != userId {
return 0, fmt.Errorf("deletion requests contain mismatched user IDs: %s vs %s", request.UserId, userId)
}
}
return db.DeleteMessagesFromBackend(ctx, userId, deletedMessages)
}
func (db *DB) DeleteMessagesFromBackend(ctx context.Context, userId string, deletedMessages []shared.MessageIdentifier) (int64, error) {
tx := db.WithContext(ctx).Where("false") tx := db.WithContext(ctx).Where("false")
for _, message := range request.Messages.Ids { for _, message := range deletedMessages {
// Note that we do an OR with date or the ID matching since the ID is not always recorded for older history entries. // Note that we do an OR with date or the ID matching since the ID is not always recorded for older history entries.
tx = tx.Or(db.WithContext(ctx).Where("user_id = ? AND device_id = ? AND (date = ? OR encrypted_id = ?)", request.UserId, message.DeviceId, message.EndTime, message.EntryId)) tx = tx.Or(db.WithContext(ctx).Where("user_id = ? AND device_id = ? AND (date = ? OR encrypted_id = ?)", userId, message.DeviceId, message.EndTime, message.EntryId))
} }
result := tx.Delete(&shared.EncHistoryEntry{}) result := tx.Delete(&shared.EncHistoryEntry{})
if tx.Error != nil { if tx.Error != nil {
@ -237,9 +252,9 @@ func (db *DB) DeletionRequestCreate(ctx context.Context, request *shared.Deletio
} }
} }
numDeleted, err := db.ApplyDeletionRequestsToBackend(ctx, request) numDeleted, err := db.DeleteMessagesFromBackend(ctx, userID, request.Messages.Ids)
if err != nil { if err != nil {
return fmt.Errorf("db.ApplyDeletionRequestsToBackend: %w", err) return fmt.Errorf("db.DeleteMessagesFromBackend: %w", err)
} }
fmt.Printf("addDeletionRequestHandler: Deleted %d rows in the backend\n", numDeleted) fmt.Printf("addDeletionRequestHandler: Deleted %d rows in the backend\n", numDeleted)

View File

@ -105,10 +105,8 @@ func (s *Server) apiQueryHandler(w http.ResponseWriter, r *http.Request) {
// Delete any entries that match a pending deletion request // Delete any entries that match a pending deletion request
deletionRequests, err := s.db.DeletionRequestsForUserAndDevice(r.Context(), userId, deviceId) deletionRequests, err := s.db.DeletionRequestsForUserAndDevice(r.Context(), userId, deviceId)
checkGormError(err) checkGormError(err)
checkGormError(shared.ForEach(deletionRequests, 4, func(delRequest *shared.DeletionRequest) error { _, err = s.db.ApplyDeletionRequestsToBackend(r.Context(), deletionRequests)
_, err := s.db.ApplyDeletionRequestsToBackend(r.Context(), delRequest) checkGormError(err)
return err
}))
// Then retrieve // Then retrieve
historyEntries, err := s.db.HistoryEntriesForDevice(r.Context(), deviceId, 5) historyEntries, err := s.db.HistoryEntriesForDevice(r.Context(), deviceId, 5)