-
Notifications
You must be signed in to change notification settings - Fork 686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SOLR-17187: make replica poll interval configurable #3144
base: main
Are you sure you want to change the base?
Changes from all commits
4419d28
fa9f4bc
2070049
3a6f77f
a5cd579
07f8767
f5cc010
f659ded
89f48ff
2a547d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,16 +75,9 @@ public void startReplication(boolean switchTransactionLog) { | |
"SolrCore not found:" + coreName + " in " + CloudUtil.getLoadedCoreNamesAsString(cc)); | ||
} | ||
} | ||
SolrConfig.UpdateHandlerInfo uinfo = core.getSolrConfig().getUpdateHandlerInfo(); | ||
String pollIntervalStr = "00:00:03"; | ||
if (System.getProperty("jetty.testMode") != null) { | ||
pollIntervalStr = "00:00:01"; | ||
} | ||
|
||
String calculatedPollIntervalString = determinePollInterval(uinfo); | ||
if (calculatedPollIntervalString != null) { | ||
pollIntervalStr = calculatedPollIntervalString; | ||
} | ||
final SolrConfig.UpdateHandlerInfo uinfo = core.getSolrConfig().getUpdateHandlerInfo(); | ||
final String pollIntervalStr = determinePollInterval(uinfo); | ||
log.info("Will start replication from leader with poll interval: {}", pollIntervalStr); | ||
|
||
NamedList<Object> followerConfig = new NamedList<>(); | ||
|
@@ -134,18 +127,25 @@ public static String getCommitVersion(SolrCore solrCore) { | |
} | ||
|
||
/** | ||
* Determine the poll interval for replicas based on the auto soft/hard commit schedule | ||
* Determine the poll interval for replicas based on the auto soft/hard commit schedule or | ||
* configured commit poll interval | ||
* | ||
* @param uinfo the update handler info containing soft/hard commit configuration | ||
* @return a poll interval string representing a cadence of polling frequency in the form of | ||
* hh:mm:ss | ||
* hh:mm:ss, never <code>null</code> | ||
*/ | ||
public static String determinePollInterval(SolrConfig.UpdateHandlerInfo uinfo) { | ||
int hardCommitMaxTime = uinfo.autoCommmitMaxTime; | ||
int softCommitMaxTime = uinfo.autoSoftCommmitMaxTime; | ||
boolean hardCommitNewSearcher = uinfo.openSearcher; | ||
String pollIntervalStr = null; | ||
if (hardCommitMaxTime != -1) { | ||
String customCommitPollInterval = uinfo.commitPollInterval; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with the comment about the never null, do we need some sort of |
||
String pollIntervalStr = "00:00:03"; | ||
|
||
if (System.getProperty("jetty.testMode") != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we still doing System.getProperty? I thought we had something else that abstracted this away? So you could use a system property or a config file? Maybe my imagination! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are thinking of EnvUtils but that's for real/operational settings a user might set. That doesn't apply here. |
||
pollIntervalStr = "00:00:01"; | ||
} else if (customCommitPollInterval != null) { | ||
pollIntervalStr = customCommitPollInterval; | ||
} else if (hardCommitMaxTime != -1) { | ||
// configured hardCommit places a ceiling on the interval at which new segments will be | ||
// available to replicate | ||
if (softCommitMaxTime != -1 | ||
|
@@ -168,6 +168,8 @@ public static String determinePollInterval(SolrConfig.UpdateHandlerInfo uinfo) { | |
pollIntervalStr = toPollIntervalStr(softCommitMaxTime / 2); | ||
} | ||
|
||
// validate poll interval and fail early | ||
ReplicationHandler.readIntervalNs(pollIntervalStr); | ||
return pollIntervalStr; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ | |
import static org.apache.solr.handler.admin.api.ReplicationAPIBase.STATUS; | ||
import static org.apache.solr.handler.admin.api.ReplicationAPIBase.TLOG_FILE; | ||
|
||
import com.google.common.annotations.VisibleForTesting; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
@@ -1485,7 +1486,8 @@ private Long readIntervalMs(String interval) { | |
return TimeUnit.MILLISECONDS.convert(readIntervalNs(interval), TimeUnit.NANOSECONDS); | ||
} | ||
|
||
private Long readIntervalNs(String interval) { | ||
@VisibleForTesting | ||
public static Long readIntervalNs(String interval) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed; it explains why it's more open than it otherwise needs to be |
||
if (interval == null) return null; | ||
int result = 0; | ||
Matcher m = INTERVAL_PATTERN.matcher(interval.trim()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,54 +18,105 @@ | |
package org.apache.solr.cloud; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertThrows; | ||
|
||
import org.apache.solr.common.SolrException; | ||
import org.apache.solr.core.SolrConfig; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
public class ReplicateFromLeaderTest { | ||
|
||
private String jettyTestMode; | ||
|
||
@Before | ||
public void setUp() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't we have some sort of Rule thing these days for this? @dsmiley ??? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed we do. Firstly, all Solr tests ought to extend SolrTestCase, at least indirectly. This test doesn't; it should be modified. Secondly, STCJ4 includes:
That obsoletes the setup & tearDown here. So for now, I suggest removing the setup & teardown here and subclass STCJ4. It's a TODO for me in my work on making SolrTestCase a better base class to transition that line from STCJ4 to STC. |
||
jettyTestMode = System.getProperty("jetty.testMode"); | ||
} | ||
|
||
@After | ||
public void tearDown() { | ||
if (jettyTestMode != null) { | ||
System.setProperty("jetty.testMode", jettyTestMode); | ||
} | ||
} | ||
|
||
@Test | ||
public void determineTestPollIntervalString() { | ||
SolrConfig.UpdateHandlerInfo updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, -1, false, "0:0:56"); | ||
String pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("00:00:01", pollInterval); | ||
} | ||
|
||
@Test | ||
public void determinePollIntervalString() { | ||
// disable jetty test mode | ||
System.clearProperty("jetty.testMode"); | ||
|
||
SolrConfig.UpdateHandlerInfo updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, true, -1, 60000, false); | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, true, -1, 60000, false, null); | ||
String pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:7", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, 15000, false); | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, 15000, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:30", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, false, -1, 60000, false); | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, false, -1, 60000, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:30", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, false, -1, 15000, false); | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, false, -1, 15000, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:30", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, -1, -1, false, -1, 60000, false); | ||
"solr.DirectUpdateHandler2", -1, -1, -1, false, -1, 60000, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:30", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, false, -1, -1, false); | ||
"solr.DirectUpdateHandler2", -1, 15000, -1, false, -1, -1, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:7", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, -1, false); | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, -1, false, null); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:30", pollInterval); | ||
|
||
updateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", -1, 60000, -1, true, -1, -1, false, "0:0:56"); | ||
pollInterval = ReplicateFromLeader.determinePollInterval(updateHandlerInfo); | ||
assertEquals("0:0:56", pollInterval); | ||
|
||
final SolrConfig.UpdateHandlerInfo illegalUpdateHandlerInfo = | ||
new SolrConfig.UpdateHandlerInfo( | ||
"solr.DirectUpdateHandler2", | ||
-1, | ||
60000, | ||
-1, | ||
true, | ||
-1, | ||
-1, | ||
false, | ||
"garbage-unfortunately"); | ||
assertThrows( | ||
SolrException.class, | ||
() -> ReplicateFromLeader.determinePollInterval(illegalUpdateHandlerInfo)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,8 @@ It is recommended that this be set for as long as is reasonable given the applic | |
A hard commit means that, if a server crashes, Solr will know exactly where your data was stored; a soft commit means that the data is stored, but the location information isn't yet stored. | ||
The tradeoff is that a soft commit gives you faster visibility because it's not waiting for background merges to finish. | ||
|
||
In a TLOG/PULL replica setup, the commit configuration also influences the interval at which the replica is polling the shard leader. You may optionally configure a custom `commitPollInterval`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please start new sentences on new lines. Not sure if this style choice is stated somewhere. Goal is reducing diffs and reducing need for line wrap. |
||
|
||
=== Explicit Commits | ||
|
||
When a client includes a `commit=true` parameter with an update request, this ensures that all index segments affected by the adds and deletes on an update are written to disk as soon as index updates are completed. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is nicer.