Правильное использование изменяемых сущностей mongodb в реактивном (webflux) приложении - PullRequest
0 голосов
/ 06 декабря 2018

Текущий проект spring-data-mongodb использует изменяемые объекты для загрузки состояния из базы данных даже в реактивном приложении.Это считается плохой практикой, и я могу найти некоторые проблемы даже в самом проекте spring-data-mongodb.Например, фрагмент кода из ReactiveMongoTemplate:

protected <T> Mono<T> doSave(String collectionName, T objectToSave, MongoWriter<Object> writer) {

    assertUpdateableIdIfNotSet(objectToSave);

    return createMono(collectionName, collection -> {

        T toSave = maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName)).getSource();

        AdaptibleEntity<T> entity = operations.forEntity(toSave, mongoConverter.getConversionService());
        Document dbDoc = entity.toMappedDocument(writer).getDocument();
        maybeEmitEvent(new BeforeSaveEvent<T>(toSave, dbDoc, collectionName));

        return saveDocument(collectionName, dbDoc, toSave.getClass()).map(id -> {

            T saved = entity.populateIdIfNecessary(id);
            return maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName)).getSource();
        });
    });
}

Как вы можете видеть, entity.populateIdIfNeeded (id) является мутирующим объектом-сущностью в другом потоке, что считается ошибкой в ​​многопоточном приложении, если только вы не используете entity, где все сеттерысинхронизированы.

Какова правильная и рекомендуемая практика для решения проблем параллелизма с использованием изменяемых объектов с реактивным интерфейсом mongodb?Рассмотрим следующий пример:

reactiveMongoOperations.findById("id2", Customer.class) // calls Customer setters on thread1
  .zipWith(reactiveMongoOperations.findById("id2", Account.class)) // calls Account setters on thread2
  .map(t -> perform(t.getT1(), t.getT2())); // access objects on thread2

Чтобы сделать этот код безопасным, вам нужно иметь неизменяемые классы Customer и Account (которые поддерживает пружина data mongodb) или все сеттеры должны быть синхронизированы / volatile делает ваш код оченьс поддержкой потоков и ошибок.

1 Ответ

0 голосов
/ 08 декабря 2018

Я только что нашел похожий вопрос с ответами о проектном реакторе и модели памяти Project Reactor и модель памяти Java .Таким образом, кажется, что если вы не используете параллельный оператор, согласованность памяти гарантируется использованием барьеров памяти (изменяемые ключевые слова).

...