Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
764e68a
Add reindex entity
SammiChong Jul 17, 2025
8eae7a8
Add unit tests and metadata exception
SammiChong Jul 31, 2025
6c0017e
Add GET
SammiChong Aug 8, 2025
db33162
Add case_type
SammiChong Aug 8, 2025
c186109
Cleanup
SammiChong Aug 8, 2025
9e4eaa1
Add IT and clean up
SammiChong Aug 11, 2025
434db9c
Format error message
SammiChong Aug 11, 2025
0cb50c5
Revert testing
SammiChong Aug 11, 2025
46b8b3f
Cleanup
SammiChong Aug 11, 2025
8cecdf1
Merge branch 'master' into CME-239
SammiChong Aug 11, 2025
6d27919
Cleanup
SammiChong Aug 11, 2025
1b1835e
Add ActiveProfile to IT
SammiChong Aug 11, 2025
41708b4
Update ElasticsearchBaseTest.java
SammiChong Aug 11, 2025
b14b75b
Update ElasticsearchBaseTest.java
SammiChong Aug 12, 2025
36c9bb7
testing
SammiChong Aug 20, 2025
c9e1768
Add findByIndexName
SammiChong Aug 20, 2025
e3be5a6
Add ReindexPersistService
SammiChong Aug 20, 2025
aa1716a
Fix async transaction issue
SammiChong Aug 20, 2025
29a26fa
Clean up
SammiChong Aug 20, 2025
64d0e22
Replace overwrite with insert to DB
SammiChong Aug 22, 2025
2e585ef
Cleanup - rename and add tests
SammiChong Aug 22, 2025
d4aa313
Add reindex_response
SammiChong Aug 22, 2025
60fbf84
More cleanup
SammiChong Aug 29, 2025
3297c20
Merge branch 'master' into CME-239
SammiChong Aug 29, 2025
6ece42a
Add h2database
SammiChong Sep 2, 2025
3e773cd
Use testcontainers
SammiChong Sep 2, 2025
0d84d90
Add back ElasticsearchContainerInitializer
SammiChong Sep 2, 2025
1061029
Merge branch 'master' into CME-239
SammiChong Sep 3, 2025
6d68668
Return ReindexDTO instead of ReindexEntity
SammiChong Sep 3, 2025
c8bf2a9
Merge branch 'CME-239' of https://github.com/hmcts/ccd-definition-sto…
SammiChong Sep 3, 2025
b57eecb
Fix code smells
SammiChong Sep 3, 2025
d15f5d9
Revert !reindex
SammiChong Sep 3, 2025
3044cf3
Merge branch 'master' into CME-239
SammiChong Sep 8, 2025
a4aafd0
Remove null check
SammiChong Sep 8, 2025
453c3af
Address review comments
SammiChong Sep 10, 2025
5246cf8
Rename ReindexDTO
SammiChong Sep 11, 2025
aa5a82f
Merge branch 'master' into CME-239
SammiChong Sep 11, 2025
f2358dd
Merge branch 'master' into CME-239
SammiChong Sep 16, 2025
54b7265
Merge branch 'CME-238-patch' into CME-239
SammiChong Sep 30, 2025
4046b65
Cleanup, add tests
SammiChong Oct 1, 2025
956fa6b
Merge ReindexTaskService with ReindexService
SammiChong Oct 3, 2025
4ccb25b
Checkstyle
SammiChong Oct 3, 2025
35dbf88
Remove transactional
SammiChong Oct 6, 2025
3deab9b
Update ReindexServiceImpl.java
SammiChong Oct 6, 2025
20c2ffc
Merge branch 'CME-238-patch' into CME-239
SammiChong Oct 8, 2025
f7c1d3d
Fix tests, add reindexResponse
SammiChong Oct 8, 2025
576425f
Merge branch 'master' into CME-239
SammiChong Oct 8, 2025
283f295
Merge branch 'master' into CME-239
SammiChong Oct 8, 2025
82d0749
Merge branch 'CME-238-patch' into CME-239
kiran-yenigala-hmcts Oct 8, 2025
1a7d8bb
Clean import
SammiChong Oct 8, 2025
00e5241
Remove buildResponse, add logging
SammiChong Oct 28, 2025
73b2e5c
Remove reindex column
SammiChong Oct 30, 2025
29710b8
Merge remote-tracking branch 'origin' into CME-239
SammiChong Dec 29, 2025
3adcd7d
Merge branch 'CME-238-patch' into CME-239
SammiChong Dec 30, 2025
7797ff1
Revert "Merge remote-tracking branch 'origin' into CME-239"
SammiChong Dec 30, 2025
aed98a0
Merge branch 'CME-238-patch' into CME-239
SammiChong Dec 30, 2025
783a467
Reapply "Merge remote-tracking branch 'origin' into CME-239"
SammiChong Dec 30, 2025
4470a57
Revert
SammiChong Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'CME-238-patch' into CME-239
  • Loading branch information
SammiChong committed Sep 30, 2025
commit 54b7265d85b44777b7e8d6e92afcc7e6ba225728
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ public AsynchronousElasticDefinitionImportListener(CcdElasticSearchProperties co
CaseMappingGenerator mappingGenerator,
ObjectFactory<HighLevelCCDElasticClient> clientFactory,
ElasticsearchErrorHandler elasticsearchErrorHandler,
ReindexService reindexService,
ReindexTaskService reindexTaskService) {
super(config, mappingGenerator, clientFactory, elasticsearchErrorHandler, reindexTaskService);
super(config, mappingGenerator, clientFactory, elasticsearchErrorHandler, reindexService, reindexTaskService);
}

@Async
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import uk.gov.hmcts.ccd.definition.store.elastic.service.ReindexTaskService;
import uk.gov.hmcts.ccd.definition.store.event.DefinitionImportedEvent;
import uk.gov.hmcts.ccd.definition.store.repository.entity.CaseTypeEntity;
import uk.gov.hmcts.ccd.definition.store.repository.entity.ReindexEntity;

import java.io.IOException;
import java.util.List;
Expand All @@ -30,16 +29,20 @@ public abstract class ElasticDefinitionImportListener {

private final ElasticsearchErrorHandler elasticsearchErrorHandler;

private final ReindexService reindexService;

private final ReindexTaskService reindexTaskService;


public ElasticDefinitionImportListener(CcdElasticSearchProperties config, CaseMappingGenerator mappingGenerator,
ObjectFactory<HighLevelCCDElasticClient> clientFactory,
ElasticsearchErrorHandler elasticsearchErrorHandler,
ElasticsearchErrorHandler elasticsearchErrorHandler, ReindexService reindexService,
ReindexTaskService reindexTaskService) {
this.config = config;
this.mappingGenerator = mappingGenerator;
this.clientFactory = clientFactory;
this.elasticsearchErrorHandler = elasticsearchErrorHandler;
this.reindexService = reindexService;
this.reindexTaskService = reindexTaskService;
}

Expand All @@ -54,7 +57,6 @@ public ElasticDefinitionImportListener(CcdElasticSearchProperties config, CaseMa
public void initialiseElasticSearch(DefinitionImportedEvent event) {
List<CaseTypeEntity> caseTypes = event.getContent();
boolean reindex = event.isReindex();
boolean deleteOldIndex = event.isDeleteOldIndex();
boolean reindexStarted = false;
String newIndexName = null;
String caseMapping = null;
Expand All @@ -70,31 +72,7 @@ public void initialiseElasticSearch(DefinitionImportedEvent event) {
elasticClient.createIndex(actualIndexName, baseIndexName);
}
if (reindex) {
//get current alias index
GetAliasesResponse aliasResponse = elasticClient.getAlias(baseIndexName);
String indexName = aliasResponse.getAliases().keySet().iterator().next();
newIndexName = incrementIndexNumber(indexName);

//prepare for db
ReindexEntity reindexEntity = reindexTaskService.saveEntity(reindex,
deleteOldIndex, caseType, newIndexName);

//create new index with generated mapping and incremented case type name (no alias update yet)
caseMapping = mappingGenerator.generateMapping(caseType);
log.debug("case mapping: {}", caseMapping);

//update index name for db
elasticClient.setIndexReadOnly(baseIndexName, true);
elasticClient.createIndexAndMapping(newIndexName, caseMapping);

//initiate reindexing
reindexStarted = true;
handleReindexing(baseIndexName, indexName, newIndexName,
deleteOldIndex);
//dummy value for phase 1
event.setTaskId("taskID");
log.info("reindexing successful for case type: {}", caseType.getReference());
log.info("task id returned from the import: {}", event.getTaskId());
reindexService.asyncReindex(event, baseIndexName, caseType, reindexStarted);
} else {
caseMapping = mappingGenerator.generateMapping(caseType);
log.debug("case mapping: {}", caseMapping);
Expand All @@ -116,75 +94,6 @@ public void initialiseElasticSearch(DefinitionImportedEvent event) {
}
}

private void handleReindexing(String baseIndexName,
String oldIndexName, String newIndexName,
boolean deleteOldIndex) {
HighLevelCCDElasticClient elasticClient = clientFactory.getObject();
elasticClient.reindexData(oldIndexName, newIndexName, new ActionListener<>() {
@Override
public void onResponse(BulkByScrollResponse bulkByScrollResponse) {
try (elasticClient; HighLevelCCDElasticClient asyncElasticClient = clientFactory.getObject()) {
//if success set writable and update alias to new index
log.info("updating alias from {} to {}", oldIndexName, newIndexName);
asyncElasticClient.setIndexReadOnly(baseIndexName, false);
asyncElasticClient.updateAlias(baseIndexName, oldIndexName, newIndexName);
if (deleteOldIndex) {
log.info("deleting old index {}", oldIndexName);
asyncElasticClient.removeIndex(oldIndexName);
}
//set success status and end time for db
reindexTaskService.updateEntity(newIndexName, bulkByScrollResponse.toString());
log.info("saved reindex entity"
+ " metadata for case type {} to DB", baseIndexName);

} catch (IOException e) {
log.error("failed to clean up after reindexing success", e);
reindexTaskService.updateEntity(newIndexName, e);
throw new CompletionException(e);
}
}

@Override
public void onFailure(Exception ex) {
try (elasticClient; HighLevelCCDElasticClient asyncElasticClient = clientFactory.getObject()) {
//set failure status, end time and ex for db
reindexTaskService.updateEntity(newIndexName, ex);

//if failed delete new index, set old index writable
log.error("reindexing failed", ex);
asyncElasticClient.removeIndex(newIndexName);
log.info("{} deleted", newIndexName);
asyncElasticClient.setIndexReadOnly(oldIndexName, false);
log.info("{} set to writable", oldIndexName);
} catch (IOException e) {
log.error("failed to clean up after reindexing failure", e);
reindexTaskService.updateEntity(newIndexName, e);
throw new CompletionException(e);
}
throw new CompletionException(ex);
}
});
}

String incrementIndexNumber(String indexName) {
Pattern pattern = Pattern.compile("(.+_cases-)(\\d+)$");
Matcher matcher = pattern.matcher(indexName);

if (!matcher.matches() || matcher.groupCount() < 2) {
throw new IllegalArgumentException("invalid index name format: " + indexName);
}

String prefix = matcher.group(1);
String numberStr = matcher.group(2);

int incremented = Integer.parseInt(numberStr) + 1;
String formattedNumber = StringUtils.leftPad(String.valueOf(incremented), numberStr.length(), '0');

String incrementedIndexName = prefix + formattedNumber;
log.info("incremented index name: {}", incrementedIndexName);
return incrementedIndexName;
}

private String baseIndexName(CaseTypeEntity caseType) {
String caseTypeId = caseType.getReference();
return String.format(config.getCasesIndexNameFormat(), caseTypeId.toLowerCase());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,116 +1,4 @@
package uk.gov.hmcts.ccd.definition.store.elastic;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import uk.gov.hmcts.ccd.definition.store.elastic.client.HighLevelCCDElasticClient;
import uk.gov.hmcts.ccd.definition.store.elastic.mapping.CaseMappingGenerator;
import uk.gov.hmcts.ccd.definition.store.event.DefinitionImportedEvent;
import uk.gov.hmcts.ccd.definition.store.repository.entity.CaseTypeEntity;

import java.io.IOException;
import java.util.concurrent.CompletionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
public class ReindexService {

private final CaseMappingGenerator mappingGenerator;

private final ObjectFactory<HighLevelCCDElasticClient> clientFactory;

public ReindexService(CaseMappingGenerator mappingGenerator,
ObjectFactory<HighLevelCCDElasticClient> clientFactory) {
this.mappingGenerator = mappingGenerator;
this.clientFactory = clientFactory;
}

@Async("reindexExecutor")
public void asyncReindex(DefinitionImportedEvent event,
String baseIndexName,
CaseTypeEntity caseType) throws IOException {
HighLevelCCDElasticClient elasticClient = clientFactory.getObject();
GetAliasesResponse aliasResponse = elasticClient.getAlias(baseIndexName);
String caseTypeName = aliasResponse.getAliases().keySet().iterator().next();

//create new index with generated mapping and incremented case type name (no alias update yet)
String caseMapping = mappingGenerator.generateMapping(caseType);
log.debug("case mapping: {}", caseMapping);
String incrementedCaseTypeName = incrementIndexNumber(caseTypeName);
elasticClient.setIndexReadOnly(baseIndexName, true);
elasticClient.createIndexAndMapping(incrementedCaseTypeName, caseMapping);

//initiate reindexing
handleReindexing(elasticClient, baseIndexName, caseTypeName, incrementedCaseTypeName,
event.isDeleteOldIndex());
//dummy value for phase 1
event.setTaskId("taskID");
log.debug("reindexing successful for case type: {}", caseType.getReference());
log.debug("task id returned from the import: {}", event.getTaskId());
}

private void handleReindexing(HighLevelCCDElasticClient elasticClient, String baseIndexName,
String oldIndex, String newIndex,
boolean deleteOldIndex) {
elasticClient.reindexData(oldIndex, newIndex, new ActionListener<>() {
@Override
public void onResponse(BulkByScrollResponse bulkByScrollResponse) {
try (elasticClient; HighLevelCCDElasticClient highLevelCCDElasticClient = clientFactory.getObject()) {
//if success set writable and update alias to new index
log.debug("updating alias from {} to {}", oldIndex, newIndex);
highLevelCCDElasticClient.setIndexReadOnly(baseIndexName, false);
highLevelCCDElasticClient.updateAlias(baseIndexName, oldIndex, newIndex);
if (deleteOldIndex) {
log.debug("deleting old index {}", oldIndex);
highLevelCCDElasticClient.removeIndex(oldIndex);
}
} catch (IOException e) {
log.error("failed to clean up after reindexing success", e);
throw new CompletionException(e);
}
}

@Override
public void onFailure(Exception ex) {
try (elasticClient; HighLevelCCDElasticClient highLevelCCDElasticClient = clientFactory.getObject()) {
//if failed delete new index, set old index writable
log.debug("reindexing failed", ex);
highLevelCCDElasticClient.removeIndex(newIndex);
log.debug("{} deleted", newIndex);
highLevelCCDElasticClient.setIndexReadOnly(oldIndex, false);
log.debug("{} set to writable", oldIndex);
} catch (IOException e) {
log.error("failed to clean up after reindexing failure", e);
throw new CompletionException(e);
}
throw new CompletionException(ex);
}
});
}

String incrementIndexNumber(String indexName) {
Pattern pattern = Pattern.compile("(.+_cases-)(\\d+)$");
Matcher matcher = pattern.matcher(indexName);

if (!matcher.matches() || matcher.groupCount() < 2) {
throw new IllegalArgumentException("invalid index name format: " + indexName);
}

String prefix = matcher.group(1);
String numberStr = matcher.group(2);

int incremented = Integer.parseInt(numberStr) + 1;
String formattedNumber = StringUtils.leftPad(String.valueOf(incremented), numberStr.length(), '0');

String incrementedIndexName = prefix + formattedNumber;
return incrementedIndexName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ public SynchronousElasticDefinitionImportListener(CcdElasticSearchProperties con
CaseMappingGenerator mappingGenerator,
ObjectFactory<HighLevelCCDElasticClient> clientFactory,
ElasticsearchErrorHandler elasticsearchErrorHandler,
ReindexService reindexService,
ReindexTaskService reindexTaskService) {
super(config, mappingGenerator, clientFactory, elasticsearchErrorHandler, reindexTaskService);
super(config, mappingGenerator, clientFactory, elasticsearchErrorHandler, reindexService, reindexTaskService);
}

@EventListener
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.