自从升级到 spring-data-elasticsearch 5.x 以来,由于 seq_no+primary_term 冲突而无法索引文档

问题描述 投票:0回答:0

我已从 spring-data-elasticsearch 4.x 升级到 5.x,并从 REST 高级客户端切换到 Elastic 的新客户端。从那时起,我得到了很多

org.springframework.dao.OptimisticLockingFailureException: Cannot index a document due to seq_no+primary_term conflict

我的测试中的错误(至少对我来说)没有明显的原因。我无法弄清楚是什么发生了变化并且现在导致了这些异常。我这里缺少一些配置吗?

编辑:我认为这可以归结为一些具有 @BeforeEach 和 @AfterEach 的测试,它们都通过 Query.findAll() 删除索引,并且我认为 before 方法被触发,而索引仍在通过 after 方法更新由于某种原因,旧客户端没有发生这种情况,因为……新客户端速度更快?我不知道

以下代码模拟了这种行为,并且(至少对我来说)在第二次删除时可靠地失败:

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.Query;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;

import lombok.Data;

@SpringBootTest
@Testcontainers
class RandomTest {

    @Container
    @ServiceConnection
    private static ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.7.0");

    static {
        elasticsearchContainer.getEnvMap().put("xpack.security.enabled", "false");
    }

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    @Test
    void test()  {
        for (int i = 0; i < 10; i++) {
            final TestDocument testDocument = new TestDocument();
            testDocument.setContent(RandomStringUtils.randomAlphanumeric(32));
            elasticsearchOperations.save(testDocument);
        }

        elasticsearchOperations.delete(Query.findAll(), TestDocument.class, IndexCoordinates.of("test-*"));
        elasticsearchOperations.delete(Query.findAll(), TestDocument.class, IndexCoordinates.of("test-*"));
        elasticsearchOperations.delete(Query.findAll(), TestDocument.class, IndexCoordinates.of("test-*"));
    }

    @Document(indexName = "<test-{now/d}>")
    @Setting(useServerConfiguration = true)
    @Data
    public static class TestDocument {
        private String content;
    }
}

我们有几个测试,其中有 @AfterEach 清理添加的数据,这些数据往往会失败。在删除操作“修复”它们之后添加 Thread.sleep(1000) 但我仍然不明白为什么这个问题只出现在新客户端中。

最终编辑:问题是,在 spring-data-es 4.4 中,ElasticsearchOperations#delete 的行为与 5.1 的行为完全不同,它默认发送很多附加参数,包括冲突=继续,它只是跳过现在发生的问题。我不知道为什么有人会完全改变一个原本不变的 API 的底层、不可见的行为,但是没关系。

elasticsearch spring-data-elasticsearch
© www.soinside.com 2019 - 2024. All rights reserved.