В какой момент оповещать пользователя об изменении текущего документа
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Уведомление пользователя об изменении документа: правильный момент
Время и механизм уведомления пользователя об изменении документа зависит от требований приложения. Рассмотрим различные подходы и когда их использовать.
Сценарий: Совместное редактирование документа
Задача: несколько пользователей редактируют документ одновременно, и нужно оповещать их об изменениях друг друга.
1. Немедленное уведомление (Real-time)
Когда: Для синхронных операций редактирования, когда нужна мгновенная реакция
// WebSocket подход для real-time уведомлений
@Component
public class DocumentWebSocketHandler extends TextWebSocketHandler {
private final DocumentService documentService;
private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.add(session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
// Получаем изменение от пользователя
DocumentChange change = parseChange(message.getPayload());
// Сохраняем в БД
documentService.applyChange(change);
// Немедленно оповещаем ДРУГИХ пользователей
broadcastToOthers(session, change);
}
private void broadcastToOthers(WebSocketSession sender, DocumentChange change) {
String notification = createNotification(change);
for (WebSocketSession s : sessions) {
if (!s.getId().equals(sender.getId()) && s.isOpen()) {
try {
s.sendMessage(new TextMessage(notification));
} catch (IOException e) {
// Handle error
}
}
}
}
}
Преимущества: Мгновенная синхронизация, лучший UX Недостатки: Высокие требования к серверу, сложнее масштабировать
2. Отложенное уведомление (После сохранения в БД)
Когда: Для асинхронных операций, когда нужна гарантия сохранения
@RestController
@RequestMapping("/api/v1/documents")
public class DocumentController {
@PostMapping("/{id}/update")
public ResponseEntity<DocumentDTO> updateDocument(
@PathVariable String id,
@RequestBody DocumentUpdateRequest request) {
// 1. Сохраняем в БД
Document document = documentService.update(id, request.getContent());
// 2. ПОСЛЕ сохранения оповещаем пользователей
notificationService.notifyDocumentChanged(id, document);
return ResponseEntity.ok(DocumentDTO.from(document));
}
}
@Service
public class NotificationService {
@Async // Асинхронно, не блокируя HTTP ответ
public void notifyDocumentChanged(String documentId, Document document) {
// Отправляем уведомления:
// - Email
// - Push-notification
// - WebSocket
// - Обновляем версию документа
}
}
Преимущества: Гарантия сохранения, проще реализовать Недостатки: Некоторая задержка, может быть асинхронность
3. Уведомление при открытии документа (Polling)
Когда: Для периодического обновления статуса
@RestController
@RequestMapping("/api/v1/documents")
public class DocumentController {
@GetMapping("/{id}/status")
public ResponseEntity<DocumentStatusDTO> getDocumentStatus(
@PathVariable String id) {
Document document = documentService.getById(id);
// Возвращаем информацию об изменениях
return ResponseEntity.ok(DocumentStatusDTO.builder()
.id(id)
.version(document.getVersion())
.lastModified(document.getLastModified())
.modifiedBy(document.getModifiedBy())
.hasUnreadChanges(true) // Были ли изменения
.build());
}
}
// Frontend: Периодический опрос
setInterval(() => {
fetch(`/api/v1/documents/${docId}/status`)
.then(res => res.json())
.then(data => {
if (data.hasUnreadChanges) {
showNotification(`Document updated by ${data.modifiedBy}`);
reloadDocument();
}
});
}, 5000); // Каждые 5 секунд
Преимущества: Просто реализовать, работает везде Недостатки: Задержка, нагрузка на сервер
4. Уведомление на основе событий (Event-driven)
Когда: Для сложных систем с множеством действий
@Service
public class DocumentService {
private final ApplicationEventPublisher eventPublisher;
public void updateDocument(String id, String content) {
Document document = documentRepository.findById(id).orElseThrow();
document.setContent(content);
document.setLastModified(LocalDateTime.now());
document.setModifiedBy(getCurrentUser());
documentRepository.save(document);
// Публикуем событие
eventPublisher.publishEvent(
new DocumentChangedEvent(this, id, content, getCurrentUser())
);
}
}
@Component
public class DocumentChangeListener {
private final NotificationService notificationService;
private final WebSocketService webSocketService;
@EventListener
public void onDocumentChanged(DocumentChangedEvent event) {
// Обработаем событие несколькими способами
notificationService.notifyViaEmail(event);
webSocketService.broadcastChange(event);
// Логирование, аналитика, кэширование и т.д.
}
}
Преимущества: Гибкость, расширяемость, разделение ответственности Недостатки: Сложнее реализовать
5. Уведомление при конкретных изменениях
Когда: Нужно уведомлять только при критичных изменениях
@Service
public class DocumentChangeDetectionService {
public void detectAndNotify(Document oldDoc, Document newDoc) {
// Уведомляем только если изменился статус
if (!oldDoc.getStatus().equals(newDoc.getStatus())) {
notificationService.notifyStatusChange(
newDoc.getId(),
oldDoc.getStatus(),
newDoc.getStatus()
);
}
// Уведомляем, если изменена важная информация
if (!oldDoc.getTitle().equals(newDoc.getTitle())) {
notificationService.notifyTitleChange(
newDoc.getId(),
newDoc.getTitle()
);
}
// Но НЕ уведомляем при каждом нажатии Enter
}
}
Рекомендации
Для Google Docs-подобного приложения:
- WebSocket для мгновенных изменений (real-time)
- Отправляй после каждого действия или с debounce (500ms)
- Версионирование документа для отслеживания изменений
@PostMapping("/{id}/edit")
@Debounce(delay = 500) // Custom аннотация
public void editDocument(@PathVariable String id, @RequestBody String content) {
documentService.update(id, content);
// Уведомление отправится один раз за 500ms всех изменений
}
Для внутренних приложений:
- Polling каждые 5-10 секунд
- Или уведомления при критичных изменениях
Для социальных сетей:
- Push-notification при упоминаниях
- Email уведомления одно в день
- WebSocket для чатов
Вывод
Правильный момент уведомления зависит от:
- Типа приложения (real-time / асинхронное)
- Критичности данных (важны ли мелкие изменения?)
- Требований к UX (быстрый отклик или ресурсоэффективность?)
- Масштабируемости (сколько пользователей одновременно?)
Не всегда нужен real-time — часто достаточно уведомления после сохранения в БД или периодического polling'а!