Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions changelog/unreleased/solr-18410.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: CrossDC Common multivalued params and per-entry params don't survive the serialization round-trip

type: fixed
authors:
- name: Andrzej Bialecki
links:
- name: SOLR-18410
url: https://issues.apache.org/jira/browse/SOLR-18410
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.CollectionUtil;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.common.util.NamedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -84,7 +86,7 @@ public MirroredSolrRequest<?> deserialize(String topic, byte[] data) {
Long.parseLong(String.valueOf(requestMap.getOrDefault("submitTimeNanos", "-1")));
SolrParams params;
if (requestMap.get("params") != null) {
params = new MapSolrParams((Map<String, String>) requestMap.get("params"));
params = new NamedList<>((Map<String, Object>) requestMap.get("params")).toSolrParams();
} else {
params = new ModifiableSolrParams();
}
Expand All @@ -93,15 +95,37 @@ public MirroredSolrRequest<?> deserialize(String topic, byte[] data) {
UpdateRequest updateRequest = (UpdateRequest) request;
List docs = (List) requestMap.get("docs");
if (docs != null) {
updateRequest.add(docs);
List<Map<String, Object>> docsParams =
(List<Map<String, Object>>) requestMap.get("docsParams");
if (docsParams.size() != docs.size()) {
throw new RuntimeException("docs and docsParams size mismatch");
}
for (int i = 0; i < docs.size(); i++) {
Map<String, Object> docParams = docsParams.get(i);
updateRequest.add(
(SolrInputDocument) docs.get(i),
docParams == null ? null : (Integer) docParams.get(UpdateRequest.COMMIT_WITHIN),
docParams == null ? null : (Boolean) docParams.get(UpdateRequest.OVERWRITE));
}
} else {
updateRequest.add("id", "1"); // TODO huh?
updateRequest.getDocumentsMap().clear();
}

List<String> deletes = (List<String>) requestMap.get("deletes");
if (deletes != null) {
updateRequest.deleteById(deletes);
List<Map<String, Object>> deletesParams =
(List<Map<String, Object>>) requestMap.get("deletesParams");
if (deletesParams.size() != deletes.size()) {
throw new RuntimeException("deletes and deletesParams size mismatch");
}
for (int i = 0; i < deletes.size(); i++) {
Map<String, Object> deleteParams = deletesParams.get(i);
updateRequest.deleteById(
deletes.get(i),
deleteParams == null ? null : (String) deleteParams.get(ShardParams._ROUTE_),
deleteParams == null ? null : (Long) deleteParams.get(UpdateRequest.VER));
}
}

List<String> deletesQuery = (List<String>) requestMap.get("deleteQuery");
Expand Down Expand Up @@ -185,8 +209,16 @@ public byte[] serialize(String topic, MirroredSolrRequest<?> request) {
map.put("params", solrRequest.getParams());
map.put("type", request.getType().toString());
if (solrRequest instanceof UpdateRequest update) {
map.put("docs", update.getDocuments());
map.put("deletes", update.getDeleteById());
Map<SolrInputDocument, Map<String, Object>> docsMap = update.getDocumentsMap();
if (docsMap != null && !docsMap.isEmpty()) {
map.put("docs", docsMap.keySet());
map.put("docsParams", update.getDocumentsMap().values());
}
Map<String, Map<String, Object>> deletes = update.getDeleteByIdMap();
if (deletes != null && !deletes.isEmpty()) {
map.put("deletes", deletes.keySet());
map.put("deletesParams", deletes.values());
}
map.put("deleteQuery", update.getDeleteQuery());
} else if (solrRequest instanceof MirroredSolrRequest.MirroredConfigSetRequest config) {
map.put("method", config.getMethod().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
package org.apache.solr.crossdc.common;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.SolrTestCase;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.junit.Test;

public class MirroredSolrRequestSerializerTest extends SolrTestCase {
Expand Down Expand Up @@ -55,4 +60,110 @@ public void testSerializationBufferOptimization() {
assertEquals(fieldValue, deserValue);
}
}

@Test
public void testMultivaluedParamsRoundTrip() {
MirroredSolrRequestSerializer serializer = new MirroredSolrRequestSerializer();
UpdateRequest req = new UpdateRequest();
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "1");
req.add(doc);

ModifiableSolrParams params = new ModifiableSolrParams();
params.set("q", "single-value");
params.add("fq", "a", "b", "c");
req.setParams(params);

MirroredSolrRequest<?> mirroredRequest = new MirroredSolrRequest<>(req);
byte[] data = serializer.serialize("test", mirroredRequest);
MirroredSolrRequest<?> deserialized = serializer.deserialize("test", data);

SolrParams deserializedParams = deserialized.getSolrRequest().getParams();
assertEquals("single-value", deserializedParams.get("q"));
assertArrayEquals(new String[] {"a", "b", "c"}, deserializedParams.getParams("fq"));
}

@Test
public void testDocsParamsRoundTrip() {
MirroredSolrRequestSerializer serializer = new MirroredSolrRequestSerializer();
UpdateRequest req = new UpdateRequest();
SolrInputDocument doc1 = new SolrInputDocument();
doc1.setField("id", "1");
SolrInputDocument doc2 = new SolrInputDocument();
doc2.setField("id", "2");
req.add(doc1, 5000, true);
req.add(doc2, 1000, false);

MirroredSolrRequest<?> mirroredRequest = new MirroredSolrRequest<>(req);
byte[] data = serializer.serialize("test", mirroredRequest);
MirroredSolrRequest<?> deserialized = serializer.deserialize("test", data);

UpdateRequest deserializedReq = (UpdateRequest) deserialized.getSolrRequest();
Map<SolrInputDocument, Map<String, Object>> docsMap = deserializedReq.getDocumentsMap();
assertEquals(2, docsMap.size());
for (Map.Entry<SolrInputDocument, Map<String, Object>> entry : docsMap.entrySet()) {
String id = (String) entry.getKey().getFieldValue("id");
Map<String, Object> docParams = entry.getValue();
if ("1".equals(id)) {
assertEquals(5000, docParams.get(UpdateRequest.COMMIT_WITHIN));
assertEquals(Boolean.TRUE, docParams.get(UpdateRequest.OVERWRITE));
} else if ("2".equals(id)) {
assertEquals(1000, docParams.get(UpdateRequest.COMMIT_WITHIN));
assertEquals(Boolean.FALSE, docParams.get(UpdateRequest.OVERWRITE));
} else {
fail("Unexpected document id: " + id);
}
}
}

@Test
public void testDeletesParamsRoundTrip() {
MirroredSolrRequestSerializer serializer = new MirroredSolrRequestSerializer();
UpdateRequest req = new UpdateRequest();
req.deleteById("1", "shard1", 100L);
req.deleteById("2", "shard2", 200L);

MirroredSolrRequest<?> mirroredRequest = new MirroredSolrRequest<>(req);
byte[] data = serializer.serialize("test", mirroredRequest);
MirroredSolrRequest<?> deserialized = serializer.deserialize("test", data);

UpdateRequest deserializedReq = (UpdateRequest) deserialized.getSolrRequest();
Map<String, Map<String, Object>> deleteByIdMap = deserializedReq.getDeleteByIdMap();
assertEquals(2, deleteByIdMap.size());
Map<String, Object> params1 = deleteByIdMap.get("1");
assertEquals("shard1", params1.get(ShardParams._ROUTE_));
assertEquals(100L, params1.get(UpdateRequest.VER));
Map<String, Object> params2 = deleteByIdMap.get("2");
assertEquals("shard2", params2.get(ShardParams._ROUTE_));
assertEquals(200L, params2.get(UpdateRequest.VER));
}

@Test
public void testBothDocsAndDeletesParamsRoundTrip() {
MirroredSolrRequestSerializer serializer = new MirroredSolrRequestSerializer();
UpdateRequest req = new UpdateRequest();
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "1");
req.add(doc, 2000, true);
req.deleteById("2", "shard1", 50L);
req.deleteByQuery("field:value");

MirroredSolrRequest<?> mirroredRequest = new MirroredSolrRequest<>(req);
byte[] data = serializer.serialize("test", mirroredRequest);
MirroredSolrRequest<?> deserialized = serializer.deserialize("test", data);

UpdateRequest deserializedReq = (UpdateRequest) deserialized.getSolrRequest();
Map<SolrInputDocument, Map<String, Object>> docsMap = deserializedReq.getDocumentsMap();
assertEquals(1, docsMap.size());
Map<String, Object> docParams = docsMap.values().iterator().next();
assertEquals(2000, docParams.get(UpdateRequest.COMMIT_WITHIN));
assertEquals(Boolean.TRUE, docParams.get(UpdateRequest.OVERWRITE));

Map<String, Map<String, Object>> deleteByIdMap = deserializedReq.getDeleteByIdMap();
Map<String, Object> deleteParams = deleteByIdMap.get("2");
assertEquals("shard1", deleteParams.get(ShardParams._ROUTE_));
assertEquals(50L, deleteParams.get(UpdateRequest.VER));

assertEquals(List.of("field:value"), deserializedReq.getDeleteQuery());
}
}
Loading