You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by jk...@apache.org on 2023/03/07 16:35:00 UTC
[unomi] branch UNOMI-737-indices-reduction-migration updated: UNOMI-737: add integration test
This is an automated email from the ASF dual-hosted git repository.
jkevan pushed a commit to branch UNOMI-737-indices-reduction-migration
in repository https://gitbox.apache.org/repos/asf/unomi.git
The following commit(s) were added to refs/heads/UNOMI-737-indices-reduction-migration by this push:
new 0b5fb09d2 UNOMI-737: add integration test
0b5fb09d2 is described below
commit 0b5fb09d2ca10b6180c5a5d4377c5d2e401b53dc
Author: Kevan <ke...@jahia.com>
AuthorDate: Tue Mar 7 17:34:48 2023 +0100
UNOMI-737: add integration test
---
.../test/java/org/apache/unomi/itests/BaseIT.java | 6 -
.../unomi/itests/migration/Migrate16xTo220IT.java | 25 +--
.../ElasticSearchPersistenceServiceImpl.java | 191 +++++++++++----------
.../unomi/persistence/spi/PersistenceService.java | 24 +--
.../services/impl/profiles/ProfileServiceImpl.java | 46 +----
5 files changed, 117 insertions(+), 175 deletions(-)
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index 1f5ebf1a4..7e4e20cfa 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -214,12 +214,6 @@ public abstract class BaseIT extends KarafTestSupport {
refreshPersistence();
}
- protected void recreateIndex(final String itemType) {
- if (persistenceService.removeIndex(itemType)) {
- persistenceService.createIndex(itemType);
- }
- }
-
protected void refreshPersistence() throws InterruptedException {
persistenceService.refresh();
Thread.sleep(1000);
diff --git a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java
index 9ddbd941a..7dc321268 100644
--- a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java
@@ -38,12 +38,11 @@ public class Migrate16xTo220IT extends BaseIT {
private int eventCount = 0;
private int sessionCount = 0;
- private int systemItemsCount = 0;
private static final int NUMBER_DUPLICATE_SESSIONS = 3;
- private static final List<String> oldSystemItemsIndices = Arrays.asList("actionType", "campaign", "campaignevent", "goal",
- "userList", "propertyType", "scope", "conditionType", "rule", "scoring", "segment", "groovyAction", "topic",
- "patch", "jsonSchema", "importConfig", "exportConfig", "rulestats");
+ private static final List<String> oldSystemItemsIndices = Arrays.asList("context-actiontype", "context-campaign", "context-campaignevent", "context-goal",
+ "context-userlist", "context-propertytype", "context-scope", "context-conditiontype", "context-rule", "context-scoring", "context-segment", "context-groovyaction", "context-topic",
+ "context-patch", "context-jsonschema", "context-importconfig", "context-exportconfig", "context-rulestats");
@Override
@Before
@@ -113,12 +112,12 @@ public class Migrate16xTo220IT extends BaseIT {
int newEventcount = 0;
for (String eventIndex : MigrationUtils.getIndexesPrefixedBy(httpClient, "http://localhost:9400", "context-event-0")) {
- newEventcount += countItems(eventIndex, null);
+ newEventcount += countItems(httpClient, eventIndex, null);
}
int newSessioncount = 0;
for (String sessionIndex : MigrationUtils.getIndexesPrefixedBy(httpClient, "http://localhost:9400", "context-session-0")) {
- newSessioncount += countItems(sessionIndex, null);
+ newSessioncount += countItems(httpClient, sessionIndex, null);
}
Assert.assertEquals(eventCount, newEventcount);
Assert.assertEquals(sessionCount - NUMBER_DUPLICATE_SESSIONS, newSessioncount);
@@ -132,10 +131,6 @@ public class Migrate16xTo220IT extends BaseIT {
for (String oldSystemItemsIndex : oldSystemItemsIndices) {
Assert.assertFalse(MigrationUtils.indexExists(httpClient, "http://localhost:9400", oldSystemItemsIndex));
}
-
- // check counts
- Assert.assertEquals("Expect same number of system items (rules, segments, etc ...) after 2_2_0 migration",
- systemItemsCount, countItems("context-systemitems", null));
}
/**
@@ -319,22 +314,18 @@ public class Migrate16xTo220IT extends BaseIT {
private void initCounts(CloseableHttpClient httpClient) {
try {
for (String eventIndex : MigrationUtils.getIndexesPrefixedBy(httpClient, "http://localhost:9400", "context-event-date")) {
- eventCount += countItems(eventIndex, resourceAsString("migration/must_not_match_some_eventype_body.json"));
+ eventCount += countItems(httpClient, eventIndex, resourceAsString("migration/must_not_match_some_eventype_body.json"));
}
for (String sessionIndex : MigrationUtils.getIndexesPrefixedBy(httpClient, "http://localhost:9400", "context-session-date")) {
- sessionCount += countItems(sessionIndex, null);
- }
-
- for (String oldSystemItemsIndex : oldSystemItemsIndices) {
- systemItemsCount += countItems(oldSystemItemsIndex, null);
+ sessionCount += countItems(httpClient, sessionIndex, null);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
- private int countItems(String index, String requestBody) throws IOException {
+ private int countItems(CloseableHttpClient httpClient, String index, String requestBody) throws IOException {
if (requestBody == null) {
requestBody = resourceAsString("migration/must_not_match_some_eventype_body.json");
}
diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
index 381f1a139..f0929887b 100644
--- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
+++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
@@ -151,8 +151,6 @@ import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
@@ -1256,78 +1254,81 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
public <T extends Item> boolean removeByQuery(final Condition query, final Class<T> clazz) {
Boolean result = new InClassLoaderExecute<Boolean>(metricsService, this.getClass().getName() + ".removeByQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
protected Boolean execute(Object... args) throws Exception {
- try {
- String itemType = Item.getItemType(clazz);
- QueryBuilder queryBuilder = conditionESQueryBuilderDispatcher.getQueryBuilder(query);
- final DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(getIndexNameForQuery(itemType))
- .setQuery(isItemTypeSharingIndex(itemType) ? wrapWithItemTypeQuery(itemType, queryBuilder) : queryBuilder)
- // Setting slices to auto will let Elasticsearch choose the number of slices to use.
- // This setting will use one slice per shard, up to a certain limit.
- // The delete request will be more efficient and faster than no slicing.
- .setSlices(AbstractBulkByScrollRequest.AUTO_SLICES)
- // Elasticsearch takes a snapshot of the index when you hit delete by query request and uses the _version of the documents to process the request.
- // If a document gets updated in the meantime, it will result in a version conflict error and the delete operation will fail.
- // So we explicitly set the conflict strategy to proceed in case of version conflict.
- .setAbortOnVersionConflict(false)
- // Remove by Query is mostly used for purge and cleaning up old data
- // It's mostly used in jobs/timed tasks so we don't really care about long request
- // So we increase default timeout of 1min to 10min
- .setTimeout(TimeValue.timeValueMinutes(removeByQueryTimeoutInMinutes));
-
- BulkByScrollResponse bulkByScrollResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
-
- if (bulkByScrollResponse == null) {
- logger.error("Remove by query: no response returned for query: {}", query);
- return false;
- }
+ QueryBuilder queryBuilder = conditionESQueryBuilderDispatcher.getQueryBuilder(query);
+ return removeByQuery(queryBuilder, clazz);
+ }
+ }.catchingExecuteInClassLoader(true);
+ if (result == null) {
+ return false;
+ } else {
+ return result;
+ }
+ }
- if (bulkByScrollResponse.isTimedOut()) {
- logger.warn("Remove by query: timed out because took more than {} minutes for query: {}", removeByQueryTimeoutInMinutes, query);
- }
+ public <T extends Item> boolean removeByQuery(QueryBuilder queryBuilder, final Class<T> clazz) throws Exception {
+ try {
+ String itemType = Item.getItemType(clazz);
+ final DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(getIndexNameForQuery(itemType))
+ .setQuery(isItemTypeSharingIndex(itemType) ? wrapWithItemTypeQuery(itemType, queryBuilder) : queryBuilder)
+ // Setting slices to auto will let Elasticsearch choose the number of slices to use.
+ // This setting will use one slice per shard, up to a certain limit.
+ // The delete request will be more efficient and faster than no slicing.
+ .setSlices(AbstractBulkByScrollRequest.AUTO_SLICES)
+ // Elasticsearch takes a snapshot of the index when you hit delete by query request and uses the _version of the documents to process the request.
+ // If a document gets updated in the meantime, it will result in a version conflict error and the delete operation will fail.
+ // So we explicitly set the conflict strategy to proceed in case of version conflict.
+ .setAbortOnVersionConflict(false)
+ // Remove by Query is mostly used for purge and cleaning up old data
+ // It's mostly used in jobs/timed tasks so we don't really care about long request
+ // So we increase default timeout of 1min to 10min
+ .setTimeout(TimeValue.timeValueMinutes(removeByQueryTimeoutInMinutes));
+
+ BulkByScrollResponse bulkByScrollResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
+
+ if (bulkByScrollResponse == null) {
+ logger.error("Remove by query: no response returned for query: {}", queryBuilder);
+ return false;
+ }
- if ((bulkByScrollResponse.getSearchFailures() != null && bulkByScrollResponse.getSearchFailures().size() > 0) ||
- bulkByScrollResponse.getBulkFailures() != null && bulkByScrollResponse.getBulkFailures().size() > 0) {
- logger.warn("Remove by query: we found some failure during the process of query: {}", query);
+ if (bulkByScrollResponse.isTimedOut()) {
+ logger.warn("Remove by query: timed out because took more than {} minutes for query: {}", removeByQueryTimeoutInMinutes, queryBuilder);
+ }
- if (bulkByScrollResponse.getSearchFailures() != null && bulkByScrollResponse.getSearchFailures().size() > 0) {
- for (ScrollableHitSource.SearchFailure searchFailure : bulkByScrollResponse.getSearchFailures()) {
- logger.warn("Remove by query, search failure: {}", searchFailure.toString());
- }
- }
+ if ((bulkByScrollResponse.getSearchFailures() != null && bulkByScrollResponse.getSearchFailures().size() > 0) ||
+ bulkByScrollResponse.getBulkFailures() != null && bulkByScrollResponse.getBulkFailures().size() > 0) {
+ logger.warn("Remove by query: we found some failure during the process of query: {}", queryBuilder);
- if (bulkByScrollResponse.getBulkFailures() != null && bulkByScrollResponse.getBulkFailures().size() > 0) {
- for (BulkItemResponse.Failure bulkFailure : bulkByScrollResponse.getBulkFailures()) {
- logger.warn("Remove by query, bulk failure: {}", bulkFailure.toString());
- }
- }
+ if (bulkByScrollResponse.getSearchFailures() != null && bulkByScrollResponse.getSearchFailures().size() > 0) {
+ for (ScrollableHitSource.SearchFailure searchFailure : bulkByScrollResponse.getSearchFailures()) {
+ logger.warn("Remove by query, search failure: {}", searchFailure.toString());
}
+ }
- if (logger.isDebugEnabled()) {
- logger.debug("Remove by query: took {}, deleted docs: {}, batches executed: {}, skipped docs: {}, version conflicts: {}, search retries: {}, bulk retries: {}, for query: {}",
- bulkByScrollResponse.getTook().toHumanReadableString(1),
- bulkByScrollResponse.getDeleted(),
- bulkByScrollResponse.getBatches(),
- bulkByScrollResponse.getNoops(),
- bulkByScrollResponse.getVersionConflicts(),
- bulkByScrollResponse.getSearchRetries(),
- bulkByScrollResponse.getBulkRetries(),
- query);
+ if (bulkByScrollResponse.getBulkFailures() != null && bulkByScrollResponse.getBulkFailures().size() > 0) {
+ for (BulkItemResponse.Failure bulkFailure : bulkByScrollResponse.getBulkFailures()) {
+ logger.warn("Remove by query, bulk failure: {}", bulkFailure.toString());
}
-
- return true;
- } catch (Exception e) {
- throw new Exception("Cannot remove by query", e);
}
}
- }.catchingExecuteInClassLoader(true);
- if (result == null) {
- return false;
- } else {
- return result;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Remove by query: took {}, deleted docs: {}, batches executed: {}, skipped docs: {}, version conflicts: {}, search retries: {}, bulk retries: {}, for query: {}",
+ bulkByScrollResponse.getTook().toHumanReadableString(1),
+ bulkByScrollResponse.getDeleted(),
+ bulkByScrollResponse.getBatches(),
+ bulkByScrollResponse.getNoops(),
+ bulkByScrollResponse.getVersionConflicts(),
+ bulkByScrollResponse.getSearchRetries(),
+ bulkByScrollResponse.getBulkRetries(),
+ queryBuilder);
+ }
+
+ return true;
+ } catch (Exception e) {
+ throw new Exception("Cannot remove by query", e);
}
}
-
public boolean indexTemplateExists(final String templateName) {
Boolean result = new InClassLoaderExecute<Boolean>(metricsService, this.getClass().getName() + ".indexTemplateExists", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
protected Boolean execute(Object... args) throws IOException {
@@ -1415,8 +1416,8 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
}
}
- public boolean removeIndex(final String itemType, boolean addPrefix){
- String index = addPrefix ? getIndex(itemType) : itemType;
+ public boolean removeIndex(final String itemType) {
+ String index = getIndex(itemType);
Boolean result = new InClassLoaderExecute<Boolean>(metricsService, this.getClass().getName() + ".removeIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
protected Boolean execute(Object... args) throws IOException {
@@ -1436,9 +1437,6 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
return result;
}
}
- public boolean removeIndex(final String itemType) {
- return removeIndex(itemType, true);
- }
private void internalCreateRolloverTemplate(String itemName) throws IOException {
String rolloverAlias = indexPrefix + "-" + itemName;
@@ -1890,29 +1888,6 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
}
}
- @Override
- public Map<String, Long> docCountPerIndex(String... indexes) {
- return new InClassLoaderExecute<Map<String, Long>>(metricsService, this.getClass().getName() + ".docCountPerIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
- @Override
- protected Map<String, Long> execute(Object... args) throws IOException {
- List<String> indexesForQuery = Stream.of(indexes).map(index -> getIndexNameForQuery(index)).collect(Collectors.toList());
- String[] itemsArray = new String[indexesForQuery.size()];
- itemsArray = indexesForQuery.toArray(itemsArray);
- GetIndexRequest request = new GetIndexRequest(itemsArray);
- GetIndexResponse getIndexResponse = client.indices().get(request, RequestOptions.DEFAULT);
-
- Map<String, Long> countPerIndex = new HashMap<>();
-
- for (String index : getIndexResponse.getIndices()) {
- CountRequest countRequest = new CountRequest(index);
- CountResponse response = client.count(countRequest, RequestOptions.DEFAULT);
- countPerIndex.put(index, response.getCount());
- }
- return countPerIndex;
- }
- }.catchingExecuteInClassLoader(true);
- }
-
private long queryCount(final QueryBuilder filter, final String itemType) {
return new InClassLoaderExecute<Long>(metricsService, this.getClass().getName() + ".queryCount", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
@@ -2392,6 +2367,42 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
@Override
public void purge(final Date date) {
+ // nothing, this method is deprecated since 2.2.0
+ }
+
+ @Override
+ public <T extends Item> void purgeTimeBasedItems(int existsNumberOfDays, Class<T> clazz) {
+ new InClassLoaderExecute<Boolean>(metricsService, this.getClass().getName() + ".purgeTimeBasedItems", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) {
+ protected Boolean execute(Object... args) throws Exception {
+ String itemType = Item.getItemType(clazz);
+
+ if (existsNumberOfDays > 0 && isItemTypeRollingOver(itemType)) {
+ // First we purge the documents
+ removeByQuery(QueryBuilders.rangeQuery("timeStamp").lte("now-" + existsNumberOfDays + "d"), clazz);
+
+ // get count per index for those time based data
+ TreeMap<String, Long> countsPerIndex = new TreeMap<>();
+ GetIndexResponse getIndexResponse = client.indices().get(new GetIndexRequest(getIndexNameForQuery(itemType)), RequestOptions.DEFAULT);
+ for (String index : getIndexResponse.getIndices()) {
+ countsPerIndex.put(index, client.count(new CountRequest(index), RequestOptions.DEFAULT).getCount());
+ }
+
+ // Check for count=0 and remove them
+ if (countsPerIndex.size() >= 1) {
+ // do not check the last index, because it's the one used to write documents
+ countsPerIndex.pollLastEntry();
+
+ for (Map.Entry<String, Long> indexCount : countsPerIndex.entrySet()) {
+ if (indexCount.getValue() == 0) {
+ client.indices().delete(new DeleteIndexRequest(indexCount.getKey()), RequestOptions.DEFAULT);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }.catchingExecuteInClassLoader(true);
}
@Override
diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
index 0e29bd299..29c196a2b 100644
--- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
+++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
@@ -677,22 +677,19 @@ public interface PersistenceService {
<T extends Item> void refreshIndex(Class<T> clazz, Date dateHint);
/**
- * Purges all data in the context server up to the specified date, not included.
- *
- * @param date the date (not included) before which we want to erase all data
+ * deprecated: (use: purgeTimeBasedItems instead)
*/
@Deprecated
void purge(Date date);
/**
- * Retrieves the number of document per indexes.
- * If the index is a rollover index, each rollover index will be return with its own number of document
- * For example: with "event" as parameter, the indexes named ...-event-000001, ...-event-000002 and so one will be returned
+ * Purges time based data in the context server up to the specified days number of existence.
+ * (This only works for time based data stored in rolling over indices, it have no effect on other types)
*
- * @param indexes names of the indexes to count the documents
- * @return Map where the key in the index name and the value is the number of document for this index
+ * @param existsNumberOfDays the number of days
+ * @param clazz the item type to be purged
*/
- Map<String, Long> docCountPerIndex(String... indexes);
+ <T extends Item> void purgeTimeBasedItems(int existsNumberOfDays, Class<T> clazz);
/**
* Retrieves all items of the specified Item subclass which specified ranged property is within the specified bounds, ordered according to the specified {@code sortBy} String
@@ -745,15 +742,6 @@ public interface PersistenceService {
*/
boolean removeIndex(final String itemType);
- /**
- * Removes the index for the specified item type.
- *
- * @param itemType the item type
- * @param addPrefix should add the index prefix to the itemType passed as parameter
- * @return {@code true} if the operation was successful, {@code false} otherwise
- */
- boolean removeIndex(final String itemType, boolean addPrefix);
-
/**
* Removes all data associated with the provided scope.
*
diff --git a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
index 7912cc6de..8221f19ff 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
@@ -370,40 +370,11 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
}
}
- private <T extends Item> void purgeRolloverItems(int existsNumberOfDays, Class<T> clazz) {
- if (existsNumberOfDays > 0) {
- String conditionType = null;
- String itemType = null;
-
- if (clazz.getName().equals(Event.class.getName())) {
- conditionType = "eventPropertyCondition";
- itemType = Event.ITEM_TYPE;
- } else if (clazz.getName().equals(Session.class.getName())) {
- conditionType = "sessionPropertyCondition";
- itemType = Session.ITEM_TYPE;
- }
-
- ConditionType propertyConditionType = definitionsService.getConditionType(conditionType);
- if (propertyConditionType == null) {
- // definition service not yet fully instantiate
- return;
- }
-
- Condition condition = new Condition(propertyConditionType);
-
- condition.setParameter("propertyName", "timeStamp");
- condition.setParameter("comparisonOperator", "lessThanOrEqualTo");
- condition.setParameter("propertyValueDateExpr", "now-" + existsNumberOfDays + "d");
- persistenceService.removeByQuery(condition, clazz);
- deleteEmptyRolloverIndex(itemType);
- }
- }
-
@Override
public void purgeSessionItems(int existsNumberOfDays) {
if (existsNumberOfDays > 0) {
logger.info("Purging: Sessions created since more than {} days", existsNumberOfDays);
- purgeRolloverItems(existsNumberOfDays, Session.class);
+ persistenceService.purgeTimeBasedItems(existsNumberOfDays, Session.class);
}
}
@@ -411,7 +382,7 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
public void purgeEventItems(int existsNumberOfDays) {
if (existsNumberOfDays > 0) {
logger.info("Purging: Events created since more than {} days", existsNumberOfDays);
- purgeRolloverItems(existsNumberOfDays, Event.class);
+ persistenceService.purgeTimeBasedItems(existsNumberOfDays, Event.class);
}
}
@@ -421,19 +392,6 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
}
- public void deleteEmptyRolloverIndex(String indexName) {
- TreeMap<String, Long> countsPerIndex = new TreeMap<>(persistenceService.docCountPerIndex(indexName));
- if (countsPerIndex.size() >= 1) {
- // do not check the last index, because it's the one used to write documents
- countsPerIndex.pollLastEntry();
- countsPerIndex.forEach((index, count) -> {
- if (count == 0) {
- persistenceService.removeIndex(index, false);
- }
- });
- }
- }
-
private void initializePurge() {
logger.info("Purge: Initializing");