Spring Data Stream и оптимизация c блокировка - PullRequest
0 голосов
/ 06 февраля 2020

Задание

У нас есть ученики и учитель. Как только учитель обновлен (например, мягко удален), мы хотим назначить учеников. Прежде чем они были назначены на учителя. Как мне это сделать?

Я обновляю учителя и отправляю сообщение TeacherUpdatedMessage. Затем у меня есть потребитель, который принимает сообщения и обновляет студентов.

Наш технический стек

Java, Spring Data Mongodb, MongoDB, архитектура микро-сервисов. Мы также реализовали оптимистическую блокировку c.

Вопрос

Когда я транслирую несколько студентов, может случиться так, что во время потока t1 userEntiy извлекается из базы данных в момент t2 он обновляется в транзакции извне. Следовательно, это поле версии будет увеличено. Тогда в момент t3 наш findAndModify метод, который вызывает mongoTmplate.doFindAndReplace(), потерпит неудачу (поскольку он не нашел документ с заданным идентификатором и версией).

Как мне правильно с этим обращаться?

Наш код

TeacherUpdatedConsumer

@Consumer // Consumer asynchornnous message that the teacher had been already changed
class TeacherUpdatedConsumer {

    public void consume(final TeacherUpdatedMessage techerMessage) {
        switch (teacherMessage.getEventType()) {
            // Similar to other cases.
            // In my case removed means it is marked as removed - soft-removal.
            case REMOVED:
            // Un-assign students from the teacher.  
            studentService.unassignedStudentsFromTeacher(teacherMessage.getPayload().getId());
            // break;
            // Next code...
        }
    }
}

StudentService

class StudentService {

    @Transactional
    public void unassignedStudentsFromTeacher(final ObjectId teacherId) {
        try (Stream<Student> students = studentRepository.streamAllByTeacherIdAndRemovedFalse(teacherId)) {
            studentRepository.findAndModify(student, buildQueryDocumentToSetTeacherIdNull());

        }
    }
}

StudentRepository использует пружину MongoTemplate

class StudentReository {

    Student findAndModify(Student student, Document query) {
        mongoTemplate.doFindAndReplace(convertStudentToDocument(student), query);
    }
}
...