diff --git a/NOTICE b/NOTICE
index 121425b665c270d20637483071524fa8a324ffae..60b4118a46591bfa65113b5bb1ca7e3039c55b93 100644
--- a/NOTICE
+++ b/NOTICE
@@ -374,7 +374,7 @@ The following software have components provided under the terms of this license:
 - Byte Buddy Java agent (from https://repo1.maven.org/maven2/net/bytebuddy/byte-buddy-agent)
 - ClassMate (from http://github.com/cowtowncoder/java-classmate)
 - Cloud Key Management Service (KMS) API (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-cloudkms)
-- Cloud Storage JSON API (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-storage)
+- Cloud Storage JSON API v1-rev20230301-2.0.0 (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-storage)
 - CloudWatch Metrics for AWS Java SDK (from https://aws.amazon.com/sdkforjava)
 - Cobertura (from http://cobertura.sourceforge.net)
 - Cobertura Limited Runtime (from http://cobertura.sourceforge.net)
diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java
index c804c056b87c5689f9c7dc203e303ae4801d21bd..8e2895fc2b0807e9ad6fedcc2a09f7b060ab27af 100644
--- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java
+++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java
@@ -125,7 +125,7 @@ public class IndexerServiceImpl implements IndexerService {
             // get upsert records
             Map<String, Map<String, OperationType>> upsertRecordMap = RecordInfo.getUpsertRecordIds(recordInfos);
             if (upsertRecordMap != null && !upsertRecordMap.isEmpty()) {
-                List<String> upsertFailureRecordIds = processUpsertRecords(upsertRecordMap);
+                List<String> upsertFailureRecordIds = processUpsertRecords(upsertRecordMap, recordInfos);
                 retryRecordIds.addAll(upsertFailureRecordIds);
             }
 
@@ -191,7 +191,7 @@ public class IndexerServiceImpl implements IndexerService {
         }
     }
 
-    private List<String> processUpsertRecords(Map<String, Map<String, OperationType>> upsertRecordMap) throws Exception {
+    private List<String> processUpsertRecords(Map<String, Map<String, OperationType>> upsertRecordMap, List<RecordInfo> recordChangedInfos) throws Exception {
         // get schema for kind
         Map<String, IndexSchema> schemas = this.getSchema(upsertRecordMap);
 
@@ -203,7 +203,7 @@ public class IndexerServiceImpl implements IndexerService {
         if (recordIds.isEmpty()) return new LinkedList<>();
 
         // get records via storage api
-        Records storageRecords = this.storageService.getStorageRecords(recordIds);
+        Records storageRecords = this.storageService.getStorageRecords(recordIds, recordChangedInfos);
         List<String> failedOrRetryRecordIds = new LinkedList<>(storageRecords.getMissingRetryRecords());
 
         // map storage records to indexer payload
diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java
index bfbb5c6d5a0faf2cf1b62ec031697141f0f649ef..54a19e807079d6076b855e89ea2707f88308e038 100644
--- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java
+++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java
@@ -15,6 +15,7 @@
 package org.opengroup.osdu.indexer.service;
 
 import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
 import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
 import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
 import org.opengroup.osdu.core.common.model.indexer.Records;
@@ -25,7 +26,7 @@ import java.util.List;
 
 public interface StorageService {
 
-    Records getStorageRecords(List<String> ids) throws AppException, URISyntaxException;
+    Records getStorageRecords(List<String> ids, List<RecordInfo> recordChangedInfos) throws AppException, URISyntaxException;
 
     RecordQueryResponse getRecordsByKind(RecordReindexRequest request) throws URISyntaxException;
 
diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java
index e9e3328eea0cb9df4f2691b901cbf62fabc22165..1b20cfb14cd9128dcb1595d9a608d6c4ed1da4b1 100644
--- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java
+++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java
@@ -20,23 +20,28 @@ import com.google.api.client.http.HttpMethods;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.gson.Gson;
-
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+import org.apache.http.HttpStatus;
 import org.opengroup.osdu.core.common.http.FetchServiceHttpRequest;
-import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.http.IUrlFetchService;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
 import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
 import org.opengroup.osdu.core.common.model.http.HttpResponse;
 import org.opengroup.osdu.core.common.model.http.RequestStatus;
-import org.opengroup.osdu.core.common.model.indexer.*;
+import org.opengroup.osdu.core.common.model.indexer.IndexingStatus;
+import org.opengroup.osdu.core.common.model.indexer.JobStatus;
+import org.opengroup.osdu.core.common.model.indexer.OperationType;
+import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
+import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
+import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
+import org.opengroup.osdu.core.common.model.indexer.Records;
+import org.opengroup.osdu.core.common.model.search.RecordMetaAttribute;
 import org.opengroup.osdu.core.common.model.storage.ConversionStatus;
 import org.opengroup.osdu.core.common.model.storage.RecordIds;
-import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
-import org.opengroup.osdu.core.common.http.IUrlFetchService;
-import org.opengroup.osdu.core.common.model.search.RecordMetaAttribute;
 import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo;
-import org.apache.http.HttpStatus;
 import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties;
 import org.springframework.stereotype.Component;
 
@@ -52,8 +57,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-import static org.opengroup.osdu.core.common.model.http.DpsHeaders.FRAME_OF_REFERENCE;
 import static org.opengroup.osdu.core.common.Constants.SLB_FRAME_OF_REFERENCE_VALUE;
+import static org.opengroup.osdu.core.common.model.http.DpsHeaders.FRAME_OF_REFERENCE;
 
 @Component
 public class StorageServiceImpl implements StorageService {
@@ -74,15 +79,17 @@ public class StorageServiceImpl implements StorageService {
     private IndexerConfigurationProperties configurationProperties;
 
     @Override
-    public Records getStorageRecords(List<String> ids) throws AppException, URISyntaxException {
+    public Records getStorageRecords(List<String> ids, List<RecordInfo> recordChangedInfos) throws AppException, URISyntaxException {
         List<Records.Entity> valid = new ArrayList<>();
         List<String> notFound = new ArrayList<>();
         List<ConversionStatus> conversionStatuses = new ArrayList<>();
         List<String> missingRetryRecordIds = new ArrayList<>();
+        Map<String, String> recordChangedMap = recordChangedInfos.stream().collect(Collectors.toMap(RecordInfo::getId, RecordInfo::getKind, (a, b) -> b));
+        Map<String, String> validRecordKindPatchMap = getValidRecordKindPatchMap(recordChangedInfos);
 
         List<List<String>> batch = Lists.partition(ids, configurationProperties.getStorageRecordsBatchSize());
         for (List<String> recordsBatch : batch) {
-            Records storageOut = this.getRecords(recordsBatch);
+            Records storageOut = this.getRecords(recordsBatch, recordChangedMap, validRecordKindPatchMap);
             valid.addAll(storageOut.getRecords());
             notFound.addAll(storageOut.getNotFound());
             conversionStatuses.addAll(storageOut.getConversionStatuses());
@@ -91,11 +98,10 @@ public class StorageServiceImpl implements StorageService {
         return Records.builder().records(valid).notFound(notFound).conversionStatuses(conversionStatuses).missingRetryRecords(missingRetryRecordIds).build();
     }
 
-    protected Records getRecords(List<String> ids) throws URISyntaxException {
+    protected Records getRecords(List<String> ids, Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap) throws URISyntaxException {
         // e.g. {"records":["test:10"]}
         String body = this.gson.toJson(RecordIds.builder().records(ids).build());
 
-//        Map<String, String> headers = this.requestInfo.getHeadersMap();
         DpsHeaders headers = this.requestInfo.getHeaders();
         headers.put(FRAME_OF_REFERENCE, SLB_FRAME_OF_REFERENCE_VALUE);
         FetchServiceHttpRequest request = FetchServiceHttpRequest
@@ -105,10 +111,10 @@ public class StorageServiceImpl implements StorageService {
                 .headers(headers)
                 .body(body).build();
         HttpResponse response = this.urlFetchService.sendRequest(request);
-        return this.validateStorageResponse(response, ids);
+        return this.validateStorageResponse(response, ids, recordChangedMap, validRecordKindPatchMap);
     }
 
-    private Records validateStorageResponse(HttpResponse response, List<String> ids) {
+    private Records validateStorageResponse(HttpResponse response, List<String> ids, Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap) {
         String bulkStorageData = response.getBody();
 
         // retry entire payload -- storage service returned empty response
@@ -145,8 +151,13 @@ public class StorageServiceImpl implements StorageService {
             throw new AppException(HttpStatus.SC_NOT_FOUND, "Invalid request", "Storage service error");
         }
 
+        // validate kind to avoid data duplication
+        List<String> staleRecords = getStaleRecordsUpdate(recordChangedMap, validRecordKindPatchMap, validRecords);
+        List<Records.Entity> indexableRecords = validateKind(validRecords, staleRecords);
+        records.setRecords(indexableRecords);
+
         Map<String, List<String>> conversionStatus = getConversionErrors(records.getConversionStatuses());
-        for (Records.Entity storageRecord : validRecords) {
+        for (Records.Entity storageRecord : indexableRecords) {
             String recordId = storageRecord.getId();
             if (conversionStatus.get(recordId) == null) {
                 continue;
@@ -157,8 +168,8 @@ public class StorageServiceImpl implements StorageService {
         }
 
         // retry missing records -- storage did not return response for all RecordChangeMessage record-ids
-        if (records.getTotalRecordCount() != ids.size()) {
-            List<String> missingRecords = this.getMissingRecords(records, ids);
+        if ((records.getRecords().size() + records.getNotFound().size() + staleRecords.size()) != ids.size()) {
+            List<String> missingRecords = this.getMissingRecords(records, ids, staleRecords);
             records.setMissingRetryRecords(missingRecords);
             this.jobStatus.addOrUpdateRecordStatus(missingRecords, IndexingStatus.FAIL, HttpStatus.SC_NOT_FOUND, "Partial response received from Storage service - missing records", String.format("Partial response received from Storage service: %s", String.join(",", missingRecords)));
         }
@@ -166,12 +177,13 @@ public class StorageServiceImpl implements StorageService {
         return records;
     }
 
-    private List<String> getMissingRecords(Records records, List<String> ids) {
+    private List<String> getMissingRecords(Records records, List<String> ids, List<String> staleRecords) {
         List<String> validRecordIds = records.getRecords().stream().map(Records.Entity::getId).collect(Collectors.toList());
         List<String> invalidRecordsIds = records.getNotFound();
         List<String> requestedIds = new ArrayList<>(ids);
         requestedIds.removeAll(validRecordIds);
         requestedIds.removeAll(invalidRecordsIds);
+        requestedIds.removeAll(staleRecords);
         return requestedIds;
     }
 
@@ -188,6 +200,54 @@ public class StorageServiceImpl implements StorageService {
         return errorsByRecordId;
     }
 
+    private List<Records.Entity> validateKind(List<Records.Entity> validRecords, List<String> staleRecords) {
+        List<Records.Entity> indexableRecords = new ArrayList<>();
+        if (!staleRecords.isEmpty()) {
+            for (Records.Entity record : validRecords) {
+                if (staleRecords.contains(record.getId())) {
+                    continue;
+                }
+                indexableRecords.add(record);
+            }
+            jaxRsDpsLog.warning(String.format("stale records found with older kind, skipping indexing | record ids: %s", String.join(" | ", staleRecords)));
+        } else {
+            indexableRecords.addAll(validRecords);
+        }
+        return indexableRecords;
+    }
+
+    private List<String> getStaleRecordsUpdate(Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap, List<Records.Entity> validRecords) {
+        List<String> staleRecords = new ArrayList<>();
+        for (Records.Entity storageRecord : validRecords) {
+            String kindOnStorage = storageRecord.getKind();
+            String kindOnMessage = recordChangedMap.get(storageRecord.getId());
+            if (validRecordKindPatchMap.containsKey(storageRecord.getId())) {
+                continue;
+            }
+            if (!kindOnStorage.equals(kindOnMessage)) {
+                staleRecords.add(storageRecord.getId());
+            }
+        }
+        return staleRecords;
+    }
+
+    /*
+    * Gets valid  kind patch map, previousVersionKind is included on the record update message in such cases
+    * */
+    private Map<String, String> getValidRecordKindPatchMap(List<RecordInfo> recordChangedInfos) {
+        Map<String, String> out = new HashMap<>();
+        for (RecordInfo msg : recordChangedInfos) {
+            OperationType op = OperationType.valueOf(msg.getOp());
+            if (op != OperationType.update) {
+                continue;
+            }
+            if (!Strings.isNullOrEmpty(msg.getPreviousVersionKind())) {
+                out.put(msg.getId(), msg.getPreviousVersionKind());
+            }
+        }
+        return out;
+    }
+
     @Override
     public RecordQueryResponse getRecordsByKind(RecordReindexRequest reindexRequest) throws URISyntaxException {
         Map<String, String> queryParams = new HashMap<>();
@@ -197,8 +257,8 @@ public class StorageServiceImpl implements StorageService {
             queryParams.put("cursor", reindexRequest.getCursor());
         }
 
-        if(requestInfo == null)
-            throw  new AppException(HttpStatus.SC_NO_CONTENT, "Invalid header", "header can't be null");
+        if (requestInfo == null)
+            throw new AppException(HttpStatus.SC_NO_CONTENT, "Invalid header", "header can't be null");
 
         FetchServiceHttpRequest request = FetchServiceHttpRequest.builder()
                 .httpMethod(HttpMethods.GET)
@@ -234,6 +294,6 @@ public class StorageServiceImpl implements StorageService {
         HttpResponse response = this.urlFetchService.sendRequest(request);
         JsonObject asJsonObject = new JsonParser().parse(response.getBody()).getAsJsonObject();
         JsonElement results = asJsonObject.get("results");
-        return response.getResponseCode() != HttpStatus.SC_OK ? null : this.gson.fromJson(results,List.class);
+        return response.getResponseCode() != HttpStatus.SC_OK ? null : this.gson.fromJson(results, List.class);
     }
 }
diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java
index 285b384a017b4eefd044dc3e58e1434b1ad0543c..194fdab46f77aa9ca67834f640a3ba13337e25c7 100644
--- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java
+++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java
@@ -142,7 +142,7 @@ public class IndexerServiceImplTest {
             validRecords.add(Records.Entity.builder().id(recordId2).kind(kind2).data(storageData).build());
             List<ConversionStatus> conversionStatus = new LinkedList<>();
             Records storageRecords = Records.builder().records(validRecords).conversionStatuses(conversionStatus).build();
-            when(this.storageService.getStorageRecords(any())).thenReturn(storageRecords);
+            when(this.storageService.getStorageRecords(any(), any())).thenReturn(storageRecords);
 
             // setup elastic, index and mapped document
             when(this.indicesService.createIndex(any(), any(), any(), any(), any())).thenReturn(true);
diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java
index 42791ea57c2541a2073ee87df7033bb6da3758f1..e64574d7a6452f704361f80ea66884232b506c0a 100644
--- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java
+++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java
@@ -1,54 +1,313 @@
+// Copyright 2017-2023, Schlumberger
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.opengroup.osdu.indexer.service;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
-import org.mockito.junit.MockitoJUnitRunner;
 import org.opengroup.osdu.core.common.http.IUrlFetchService;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.AppException;
 import org.opengroup.osdu.core.common.model.http.DpsHeaders;
 import org.opengroup.osdu.core.common.model.http.HttpResponse;
+import org.opengroup.osdu.core.common.model.indexer.IndexingStatus;
+import org.opengroup.osdu.core.common.model.indexer.JobStatus;
+import org.opengroup.osdu.core.common.model.indexer.OperationType;
+import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
+import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
+import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
 import org.opengroup.osdu.core.common.model.indexer.Records;
 import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo;
 import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
 
+import java.lang.reflect.Type;
 import java.net.URISyntaxException;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
+import static java.util.Collections.singletonList;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-@RunWith(MockitoJUnitRunner.class)
+@RunWith(SpringRunner.class)
 public class StorageServiceImplTest {
-
-    @Spy
-    private ObjectMapper objectMapper = new ObjectMapper();
     @Mock
     private IUrlFetchService urlFetchService;
     @Mock
+    private JobStatus jobStatus;
+    @Mock
+    private JaxRsDpsLog log;
+    @Mock
     private IRequestInfo requestInfo;
     @Mock
     private IndexerConfigurationProperties configurationProperties;
+    @Spy
+    private ObjectMapper objectMapper = new ObjectMapper();
     @InjectMocks
     private StorageServiceImpl sut;
 
+    private List<String> ids;
+    private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465";
+    private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813";
+
+    @Before
+    public void setup() {
+
+        String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," +
+                "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]";
+
+        when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>());
+        when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders());
+
+        Type listType = new TypeToken<List<RecordInfo>>() {
+        }.getType();
+
+        List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType);
+        jobStatus.initialize(msgs);
+        ids = Arrays.asList(RECORD_ID1, RECORDS_ID2);
+
+        when(configurationProperties.getStorageRecordsBatchSize()).thenReturn(20);
+    }
+
     @Test
     public void should_parse_long_integer_values_as_integer_types() throws URISyntaxException {
         when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders());
 
-        String body = "{\"records\":[{\"id\":\"id1\",\"version\":0,\"data\":{\"long_int\":1000000000000000000000000,\"int\":123}}],\"notFound\":[],\"conversionStatuses\":[],\"missingRetryRecords\":[]}";
+        String body = "{\"records\":[{\"id\":\"id1\",\"kind\":\"tenant:test:test:1.0.0\",\"version\":0,\"data\":{\"long_int\":1000000000000000000000000,\"int\":123}}],\"notFound\":[],\"conversionStatuses\":[],\"missingRetryRecords\":[]}";
+        Map<String, String> recordChangedMap = new HashMap<>();
+        Map<String, String> validRecordKindPatchMap = new HashMap<>();
+        recordChangedMap.put("id1", "tenant:test:test:1.0.0");
 
         HttpResponse httpResponse = mock(HttpResponse.class);
         when(httpResponse.getBody()).thenReturn(body);
         when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
 
-        Records rec = sut.getRecords(Collections.singletonList("id1"));
+        Records rec = sut.getRecords(Collections.singletonList("id1"), recordChangedMap, validRecordKindPatchMap);
         assertEquals(1, rec.getRecords().size());
         assertEquals("1000000000000000000000000", rec.getRecords().get(0).getData().get("long_int").toString());
         assertEquals("123", rec.getRecords().get(0).getData().get("int").toString());
     }
+
+    @Test
+    public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException {
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(null);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+
+        should_return404_getValidStorageRecordsTest();
+    }
+
+    @Test
+    public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException {
+
+        String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}";
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(emptyDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+
+        should_return404_getValidStorageRecordsTest();
+    }
+
+    @Test
+    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException {
+
+        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"], \"conversionStatuses\": []}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.create.getValue()).build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos);
+
+        assertEquals(1, storageRecords.getRecords().size());
+    }
+
+    @Test
+    public void should_returnOneValidRecords_givenRecord_withValidKindUpdate_getStorageRecordsTest() throws URISyntaxException {
+
+        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.2.0\"}],\"notFound\":[], \"conversionStatuses\": []}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.2.0").op(OperationType.update.getValue()).previousVersionKind("tenant:test:test:1.1.0").build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos);
+
+        assertEquals(1, storageRecords.getRecords().size());
+    }
+
+    @Test
+    public void should_returnZeroRecords_givenStaleMessage_getStorageRecordsTest() throws URISyntaxException {
+
+        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.2.0\"}],\"notFound\":[], \"conversionStatuses\": []}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.1.0").op(OperationType.update.getValue()).build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos);
+
+        assertEquals(0, storageRecords.getRecords().size());
+        verify(this.log).warning("stale records found with older kind, skipping indexing | record ids: testid");
+    }
+
+    @Test
+    public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException {
+
+        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos);
+
+        assertEquals(1, storageRecords.getRecords().size());
+        verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, HttpStatus.NOT_FOUND.value(), "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813");
+    }
+
+    @Test
+    public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException {
+        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("tenant1:doc:15e790a69beb4d789b1f979e2af2e813").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(singletonList(RECORDS_ID2), recordChangeInfos);
+
+        assertEquals(1, storageRecords.getRecords().size());
+        verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed"));
+    }
+
+    @Test
+    public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception {
+
+        RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build();
+
+        HttpResponse httpResponse = new HttpResponse();
+        httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class));
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+
+        RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest);
+
+        assertEquals("100", recordQueryResponse.getCursor());
+        assertNull(recordQueryResponse.getResults());
+    }
+
+    @Test
+    public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception {
+
+        String validSchemaFromStorage = "{" +
+                "  \"kind\": \"tenant:test:test:1.0.0\"," +
+                "  \"schema\": [" +
+                "    {" +
+                "      \"path\": \"msg\"," +
+                "      \"kind\": \"string\"" +
+                "    }," +
+                "    {" +
+                "      \"path\": \"references.entity\"," +
+                "      \"kind\": \"string\"" +
+                "    }" +
+                "  ]," +
+                "  \"ext\": null" +
+                "}";
+        String kind = "tenant:test:test:1.0.0";
+
+        HttpResponse httpResponse = new HttpResponse();
+        httpResponse.setResponseCode(HttpStatus.OK.value());
+        httpResponse.setBody(validSchemaFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+
+        String recordSchemaResponse = this.sut.getStorageSchema(kind);
+
+        assertNotNull(recordSchemaResponse);
+    }
+
+    @Test
+    public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception {
+
+        String kind = "tenant:test:test:1.0.0";
+
+        HttpResponse httpResponse = new HttpResponse();
+        httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+
+        String recordSchemaResponse = this.sut.getStorageSchema(kind);
+
+        assertNull(recordSchemaResponse);
+    }
+
+    @Test
+    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException {
+
+        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}";
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build());
+
+        HttpResponse httpResponse = mock(HttpResponse.class);
+        when(httpResponse.getBody()).thenReturn(validDataFromStorage);
+
+        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
+        Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos);
+
+        assertEquals(1, storageRecords.getRecords().size());
+
+        assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size());
+
+        assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0));
+    }
+
+    private void should_return404_getValidStorageRecordsTest() {
+        List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build());
+        try {
+            this.sut.getStorageRecords(ids, recordChangeInfos);
+            fail("Should throw exception");
+        } catch (AppException e) {
+            assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode());
+        } catch (Exception e) {
+            fail("Should not throw this exception" + e.getMessage());
+        }
+    }
 }
\ No newline at end of file
diff --git a/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java b/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java
deleted file mode 100644
index 218488386affee78476390c4ba1081774ce6a3a5..0000000000000000000000000000000000000000
--- a/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright 2017-2019, Schlumberger
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.opengroup.osdu.indexer.azure.service;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.opengroup.osdu.core.common.model.indexer.IndexingStatus;
-import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
-import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
-import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
-import org.opengroup.osdu.core.common.model.indexer.Records;
-import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
-import org.opengroup.osdu.indexer.service.StorageServiceImpl;
-import org.opengroup.osdu.core.common.model.indexer.JobStatus;
-import org.opengroup.osdu.core.common.model.http.HttpResponse;
-import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo;
-import org.opengroup.osdu.core.common.http.IUrlFetchService;
-import org.opengroup.osdu.core.common.model.http.AppException;
-import org.springframework.http.HttpStatus;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import java.lang.reflect.Type;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-import static java.util.Collections.singletonList;
-import static org.junit.Assert.*;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.when;
-
-@Ignore
-@RunWith(SpringRunner.class)
-public class StorageServiceTest {
-
-    @Mock
-    private IUrlFetchService urlFetchService;
-    @Mock
-    private JobStatus jobStatus;
-    @Mock
-    private JaxRsDpsLog log;
-    @Mock
-    private IRequestInfo requestInfo;
-    @InjectMocks
-    private StorageServiceImpl sut;
-
-    private List<String> ids;
-    private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465";
-    private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813";
-
-    @Before
-    public void setup() {
-
-        String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," +
-                "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]";
-
-        when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>());
-
-        Type listType = new TypeToken<List<RecordInfo>>() {}.getType();
-
-        List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType);
-        jobStatus.initialize(msgs);
-        ids = Arrays.asList(RECORD_ID1, RECORDS_ID2);
-    }
-
-    @Test
-    public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(null);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-    }
-
-    @Test
-    public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-        verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, org.apache.http.HttpStatus.SC_NOT_FOUND, "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813");
-    }
-
-    @Test
-    public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException {
-        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(singletonList("tenant1:doc:15e790a69beb4d789b1f979e2af2e813"));
-
-        assertEquals(1, storageRecords.getRecords().size());
-        verify(this.jobStatus).addOrUpdateRecordStatus("tenant1:doc:15e790a69beb4d789b1f979e2af2e813", IndexingStatus.WARN, org.apache.http.HttpStatus.SC_BAD_REQUEST, "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed"));
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception {
-
-        RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build();
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class));
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest);
-
-        assertEquals("100", recordQueryResponse.getCursor());
-        assertNull(recordQueryResponse.getResults());
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception {
-
-        String validSchemaFromStorage = "{" +
-                "  \"kind\": \"tenant:test:test:1.0.0\"," +
-                "  \"schema\": [" +
-                "    {" +
-                "      \"path\": \"msg\"," +
-                "      \"kind\": \"string\"" +
-                "    }," +
-                "    {" +
-                "      \"path\": \"references.entity\"," +
-                "      \"kind\": \"string\"" +
-                "    }" +
-                "  ]," +
-                "  \"ext\": null" +
-                "}";
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.OK.value());
-        httpResponse.setBody(validSchemaFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNotNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception {
-
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-
-        assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size());
-
-        assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0));
-    }
-
-    private void should_return404_getValidStorageRecordsTest() {
-        try {
-            this.sut.getStorageRecords(ids);
-            fail("Should throw exception");
-        } catch (AppException e) {
-            assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode());
-        } catch (Exception e) {
-            fail("Should not throw this exception" + e.getMessage());
-        }
-    }
-}
diff --git a/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java b/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java
deleted file mode 100644
index 3ff767ebe5c4f5cb638cef9eeb8e440eecd7db19..0000000000000000000000000000000000000000
--- a/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2017-2019, Schlumberger
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.opengroup.osdu.indexer.service;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.Spy;
-import org.opengroup.osdu.core.common.model.http.DpsHeaders;
-import org.opengroup.osdu.core.common.model.http.AppException;
-import org.opengroup.osdu.core.common.model.indexer.IndexingStatus;
-import org.opengroup.osdu.core.common.model.indexer.JobStatus;
-import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
-import org.opengroup.osdu.core.common.model.http.HttpResponse;
-import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
-import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo;
-import org.opengroup.osdu.core.common.http.IUrlFetchService;
-import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
-import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
-import org.opengroup.osdu.core.common.model.indexer.Records;
-import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties;
-import org.springframework.http.HttpStatus;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import java.lang.reflect.Type;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-import static java.util.Collections.singletonList;
-import static org.junit.Assert.*;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.when;
-
-@RunWith(SpringRunner.class)
-public class StorageServiceTest {
-
-    @Mock
-    private IUrlFetchService urlFetchService;
-    @Mock
-    private JobStatus jobStatus;
-    @Mock
-    private JaxRsDpsLog log;
-    @Mock
-    private IRequestInfo requestInfo;
-    @Mock
-    private IndexerConfigurationProperties configurationProperties;
-    @Spy
-    private ObjectMapper objectMapper = new ObjectMapper();
-    @InjectMocks
-    private StorageServiceImpl sut;
-
-    private List<String> ids;
-    private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465";
-    private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813";
-
-    @Before
-    public void setup() {
-
-        String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," +
-                "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]";
-
-        when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>());
-        when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders());
-
-        Type listType = new TypeToken<List<RecordInfo>>() {}.getType();
-
-        List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType);
-        jobStatus.initialize(msgs);
-        ids = Arrays.asList(RECORD_ID1, RECORDS_ID2);
-
-        when(configurationProperties.getStorageRecordsBatchSize()).thenReturn(20);
-    }
-
-    @Test
-    public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(null);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"], \"conversionStatuses\": []}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-    }
-
-    @Test
-    public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-        verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, HttpStatus.NOT_FOUND.value(), "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813");
-    }
-
-    @Test
-    public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException {
-        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(singletonList(RECORDS_ID2));
-
-        assertEquals(1, storageRecords.getRecords().size());
-        verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed"));
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception {
-
-        RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build();
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class));
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest);
-
-        assertEquals("100", recordQueryResponse.getCursor());
-        assertNull(recordQueryResponse.getResults());
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception {
-
-        String validSchemaFromStorage = "{" +
-                "  \"kind\": \"tenant:test:test:1.0.0\"," +
-                "  \"schema\": [" +
-                "    {" +
-                "      \"path\": \"msg\"," +
-                "      \"kind\": \"string\"" +
-                "    }," +
-                "    {" +
-                "      \"path\": \"references.entity\"," +
-                "      \"kind\": \"string\"" +
-                "    }" +
-                "  ]," +
-                "  \"ext\": null" +
-                "}";
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.OK.value());
-        httpResponse.setBody(validSchemaFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNotNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception {
-
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-
-        assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size());
-
-        assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0));
-    }
-
-    private void should_return404_getValidStorageRecordsTest() {
-        try {
-            this.sut.getStorageRecords(ids);
-            fail("Should throw exception");
-        } catch (AppException e) {
-            assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode());
-        } catch (Exception e) {
-            fail("Should not throw this exception" + e.getMessage());
-        }
-    }
-}
diff --git a/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java b/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java
deleted file mode 100644
index dfbdb4396509ef1678d845fa12f1b9515654c120..0000000000000000000000000000000000000000
--- a/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/* Licensed Materials - Property of IBM              */		
-/* (c) Copyright IBM Corp. 2020. All Rights Reserved.*/
-
-package org.opengroup.osdu.indexer.ibm.service;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.opengroup.osdu.core.common.model.indexer.IndexingStatus;
-import org.opengroup.osdu.core.common.model.indexer.RecordInfo;
-import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse;
-import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest;
-import org.opengroup.osdu.core.common.model.indexer.Records;
-import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
-import org.opengroup.osdu.indexer.service.StorageServiceImpl;
-import org.opengroup.osdu.core.common.model.indexer.JobStatus;
-import org.opengroup.osdu.core.common.model.http.HttpResponse;
-import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo;
-import org.opengroup.osdu.core.common.http.IUrlFetchService;
-import org.opengroup.osdu.core.common.model.http.AppException;
-import org.springframework.http.HttpStatus;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import java.lang.reflect.Type;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-import static java.util.Collections.singletonList;
-import static org.junit.Assert.*;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.when;
-
-@Ignore
-@RunWith(SpringRunner.class)
-public class StorageServiceTest {
-
-    @Mock
-    private IUrlFetchService urlFetchService;
-    @Mock
-    private JobStatus jobStatus;
-    @Mock
-    private JaxRsDpsLog log;
-    @Mock
-    private IRequestInfo requestInfo;
-    @InjectMocks
-    private StorageServiceImpl sut;
-
-    private List<String> ids;
-    private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465";
-    private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813";
-
-    @Before
-    public void setup() {
-
-        String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," +
-                "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]";
-
-        when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>());
-
-        Type listType = new TypeToken<List<RecordInfo>>() {}.getType();
-
-        List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType);
-        jobStatus.initialize(msgs);
-        ids = Arrays.asList(RECORD_ID1, RECORDS_ID2);
-    }
-
-    @Test
-    public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(null);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        should_return404_getValidStorageRecordsTest();
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception {
-
-        RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build();
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class));
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest);
-
-        assertEquals("100", recordQueryResponse.getCursor());
-        assertNull(recordQueryResponse.getResults());
-    }
-
-    @Test
-    public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException {
-        String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(singletonList("tenant1:doc:15e790a69beb4d789b1f979e2af2e813"));
-
-        assertEquals(1, storageRecords.getRecords().size());
-        verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed"));
-    }
-
-    @Test
-    public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception {
-
-        String validSchemaFromStorage = "{" +
-                "  \"kind\": \"tenant:test:test:1.0.0\"," +
-                "  \"schema\": [" +
-                "    {" +
-                "      \"path\": \"msg\"," +
-                "      \"kind\": \"string\"" +
-                "    }," +
-                "    {" +
-                "      \"path\": \"references.entity\"," +
-                "      \"kind\": \"string\"" +
-                "    }" +
-                "  ]," +
-                "  \"ext\": null" +
-                "}";
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.OK.value());
-        httpResponse.setBody(validSchemaFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNotNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception {
-
-        String kind = "tenant:test:test:1.0.0";
-
-        HttpResponse httpResponse = new HttpResponse();
-        httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-
-        String recordSchemaResponse = this.sut.getStorageSchema(kind);
-
-        assertNull(recordSchemaResponse);
-    }
-
-    @Test
-    public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException {
-
-        String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}";
-
-        HttpResponse httpResponse = mock(HttpResponse.class);
-        Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage);
-
-        when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse);
-        Records storageRecords = this.sut.getStorageRecords(ids);
-
-        assertEquals(1, storageRecords.getRecords().size());
-
-        assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size());
-
-        assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0));
-    }
-
-    private void should_return404_getValidStorageRecordsTest() {
-        try {
-            this.sut.getStorageRecords(ids);
-            fail("Should throw exception");
-        } catch (AppException e) {
-            assertEquals(HttpStatus.NOT_FOUND, e.getError().getCode());
-        } catch (Exception e) {
-            fail("Should not throw this exception" + e.getMessage());
-        }
-    }
-}