gerlowskija commented on code in PR #1620:
URL: https://github.com/apache/solr/pull/1620#discussion_r1192313804


##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -798,6 +777,38 @@ private void getFileList(SolrParams solrParams, 
SolrQueryResponse rsp) {
     }
   }
 
+  public CoreReplicationAPI.IndexVersionResponse getIndexVersionResponse() 
throws IOException {

Review Comment:
   [0] I know we're reliant on a few fields (`indexCommitPoint`, 
`replicationEnabled`, `reserveCommitDuration`) in this class, but IMO we'd be 
better off moving this method over to CoreReplicationAPI and creating getters 
for any ReplicationHandler fields that we need.
   
   From an abstraction perspective it leaks some ReplicationHandler details, 
which isn't ideal.  But that's a temporary situation as we move the remaining 
api's/commands out of the RH here and into CoreReplicationAPI.
   
   (This is largely opinion though - if you'd rather keep this here for now 
that's also fine.)



##########
solr/core/src/java/org/apache/solr/core/CoreContainer.java:
##########
@@ -813,6 +814,7 @@ public void load() {
       registerV2ApiIfEnabled(packageLoader.getPackageAPI().readAPI);
       registerV2ApiIfEnabled(ZookeeperReadAPI.class);
     }
+    registerV2ApiIfEnabled(CoreReplicationAPI.class);

Review Comment:
   [-1] Typically we only register "container-level" APIs (i.e. those APIs that 
aren't specific to an individual core) here in CoreContainer.  So we can 
probably drop this line here.
   
   For core-level APIs, it's sufficient to mention them in the 
`getJerseyResources` method on the RequestHandler itself, as I can see you 
already did below 👍 



##########
solr/core/src/java/org/apache/solr/handler/replication/package-info.java:
##########
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+/** V2 API implementations for "replication" APIs. */
+package org.apache.solr.handler.replication;

Review Comment:
   [0] If you want to create a package specifically for the APIs we're pulling 
out of ReplicationHandler, that's fine by me.  But:
   
   1.  Could you add 'api' to the package name somewhere?  (e.g. 
`o.a.s.handler.api.replication`). That's the convention I've tried to follow 
elsewhere.
   2. Do you envision each ReplicationHandler API/command its own class, or do 
you imagine multiple of them going into CoreReplicationAPI?  If the former, 
maybe we should rename CoreReplicationAPI to be more specific (e.g. 
`GetIndexVersionAPI`?). If the latter, maybe we don't need a separate package 
for this code after all?



##########
solr/solr-ref-guide/modules/deployment-guide/pages/user-managed-index-replication.adoc:
##########
@@ -378,9 +378,26 @@ 
http://_leader_host:port_/solr/_core_name_/replication?command=disablereplicatio
 `indexversion`::
 Return the version of the latest replicatable index on the specified leader or 
follower.
 +
+====
+[.tab-label]*V1 API*
+
 [source,bash]
+----
 http://_host:port_/solr/_core_name_/replication?command=indexversion
 
+----
+====
++
+====
+[.tab-label]*V2 API*
+
+[source,bash]
+----
+http://_host:port_/api/_core_name_/replication/indexversion

Review Comment:
   [-1] L396 should be 
`http://_host:port_/api/cores/_core_name_/replication/indexversion` I think. 
(The "/cores" segment is missing)



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -1464,6 +1475,11 @@ public void inform(SolrCore core) {
     log.info("Commits will be reserved for {} ms", reserveCommitDuration);
   }
 
+  @Override

Review Comment:
   [0] This method itself is great, but we also need to enable v2 APIs by 
overriding `registerV2` to return true.  (Currently, ReplicationHandler is 
inheriting a `registerV2` implementation from `RequestHandlerBase` that returns 
false.)
   
   The method impl here should just be:
   
   ```
     @Override
     public Boolean registerV2() {
       return Boolean.TRUE;
     }
   ```



##########
solr/core/src/java/org/apache/solr/handler/replication/CoreReplicationAPI.java:
##########
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.solr.handler.replication;
+
+import static 
org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+import static 
org.apache.solr.security.PermissionNameProvider.Name.CORE_READ_PERM;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import java.io.IOException;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+
+@Path("/core/{coreName}/replication")
+public class CoreReplicationAPI extends ReplicationAPIBase {
+
+  @Inject
+  public CoreReplicationAPI(
+      CoreContainer coreContainer, SolrQueryRequest req, SolrQueryResponse 
rsp) {

Review Comment:
   [-1] We can inject the `SolrCore` directly in the constructor here, which 
should save us from having to look it up from the CoreContainer later on.  See 
`SchemaNameAPI` as an example.



##########
solr/core/src/java/org/apache/solr/handler/replication/CoreReplicationAPI.java:
##########
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.solr.handler.replication;
+
+import static 
org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+import static 
org.apache.solr.security.PermissionNameProvider.Name.CORE_READ_PERM;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import java.io.IOException;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+
+@Path("/core/{coreName}/replication")

Review Comment:
   [-1] The pattern we've established for collection/core APIs is 
`/cores/{coreName}/....`.  (Note that 'cores' in the first path segment is 
plural.)  Looks like we need an 's' at the end of the first path segment for us 
to stick with that pattern. 



##########
solr/core/src/test/org/apache/solr/handler/replication/CoreReplicationAPITest.java:
##########
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.solr.handler.replication;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import io.opentracing.noop.NoopSpan;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.ReplicationHandler;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Unit tests for {@link CoreReplicationAPI} */
+public class CoreReplicationAPITest extends SolrTestCaseJ4 {
+
+  private CoreReplicationAPI coreReplicationAPI;
+  private CoreContainer mockCoreContainer;
+  private ReplicationHandler mockReplicationHandler;
+  private static final String coreName = "test";
+  private SolrQueryRequest mockQueryRequest;
+  private SolrQueryResponse queryResponse;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    setUpMocks();
+    mockQueryRequest = mock(SolrQueryRequest.class);
+    when(mockQueryRequest.getSpan()).thenReturn(NoopSpan.INSTANCE);
+    queryResponse = new SolrQueryResponse();
+    coreReplicationAPI = new CoreReplicationAPI(mockCoreContainer, 
mockQueryRequest, queryResponse);
+  }
+
+  @Test
+  public void testGetIndexVersion() throws Exception {
+    CoreReplicationAPI.IndexVersionResponse expected =
+        new CoreReplicationAPI.IndexVersionResponse(123L, 123L, 
"testGeneration");
+    
when(mockReplicationHandler.getIndexVersionResponse()).thenReturn(expected);
+
+    CoreReplicationAPI.IndexVersionResponse response =
+        coreReplicationAPI.IndexVersionResponse(coreName);
+    assertEquals(response.indexVersion, expected.indexVersion);
+    assertEquals(response.generation, expected.generation);
+    assertEquals(response.status, expected.status);

Review Comment:
   [0] Tiny nit, but I think the "expected" value is supposed to be the first 
argument to `assertEquals`.  (Otherwise the error message that gets produced on 
assertion-failure has the actual/expected values backwards.)



##########
solr/core/src/java/org/apache/solr/handler/replication/ReplicationAPIBase.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.solr.handler.replication;
+
+import java.io.IOException;
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.ReplicationHandler;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+
+/** A common parent for "replication" (i.e. replication-level) APIs. */
+public abstract class ReplicationAPIBase extends JerseyResource {
+
+  protected final CoreContainer coreContainer;
+  protected final SolrQueryRequest solrQueryRequest;
+  protected final SolrQueryResponse solrQueryResponse;
+
+  public ReplicationAPIBase(
+      CoreContainer coreContainer,
+      SolrQueryRequest solrQueryRequest,
+      SolrQueryResponse solrQueryResponse) {
+    this.coreContainer = coreContainer;
+    this.solrQueryRequest = solrQueryRequest;
+    this.solrQueryResponse = solrQueryResponse;
+  }
+
+  protected CoreReplicationAPI.GetIndexResponse fetchIndexVersion(String 
coreName)
+      throws IOException {
+
+    if (coreContainer.getCore(coreName) == null) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST, "Solr core " + coreName + " 
does not exist");
+    }
+
+    ReplicationHandler replicationHandler =
+        (ReplicationHandler)
+            
coreContainer.getCore(coreName).getRequestHandler(ReplicationHandler.PATH);

Review Comment:
   I couldn't find a viable alternative here to the approach you chose, so LGTM 
for now.
   
   Longer term I think we can refactor some of the logic out of 
ReplicationHandler so that we can make do here without looking it up, but 
that'll take more time and isn't something we should target for this PR.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to