-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce round-robining for scan and ft.search commands (#3334)
- Loading branch information
Showing
8 changed files
with
306 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package redis.clients.jedis; | ||
|
||
import java.util.function.Function; | ||
import redis.clients.jedis.params.ScanParams; | ||
import redis.clients.jedis.Protocol.Keyword; | ||
import redis.clients.jedis.providers.ConnectionProvider; | ||
import redis.clients.jedis.resps.ScanResult; | ||
import redis.clients.jedis.util.JedisRoundRobinBase; | ||
|
||
public class ScanRoundRobin extends JedisRoundRobinBase<ScanResult<String>> { | ||
|
||
private final int count; | ||
private final Function<String, CommandArguments> args; | ||
|
||
public ScanRoundRobin(ConnectionProvider connectionProvider, int batchCount, String match) { | ||
super(connectionProvider, BuilderFactory.SCAN_RESPONSE); | ||
this.count = batchCount; | ||
this.args = (cursor) -> new CommandArguments(Protocol.Command.SCAN).add(cursor) | ||
.add(Keyword.MATCH).add(match).add(Keyword.COUNT).add(count); | ||
} | ||
|
||
public ScanRoundRobin(ConnectionProvider connectionProvider, int batchCount, String match, String type) { | ||
super(connectionProvider, BuilderFactory.SCAN_RESPONSE); | ||
this.count = batchCount; | ||
this.args = (cursor) -> new CommandArguments(Protocol.Command.SCAN).add(cursor) | ||
.add(Keyword.MATCH).add(match).add(Keyword.COUNT).add(count).add(Keyword.TYPE).add(type); | ||
} | ||
|
||
@Override | ||
protected boolean isIterationCompleted(ScanResult<String> reply) { | ||
return reply.isCompleteIteration(); | ||
} | ||
|
||
@Override | ||
protected CommandArguments initCommandArguments() { | ||
return args.apply(ScanParams.SCAN_POINTER_START); | ||
} | ||
|
||
@Override | ||
protected CommandArguments nextCommandArguments(ScanResult<String> lastReply) { | ||
return args.apply(lastReply.getCursor()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
src/main/java/redis/clients/jedis/search/FtSearchRoundRobin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package redis.clients.jedis.search; | ||
|
||
import java.util.function.IntFunction; | ||
|
||
import redis.clients.jedis.CommandArguments; | ||
import redis.clients.jedis.providers.ConnectionProvider; | ||
import redis.clients.jedis.search.SearchResult.SearchResultBuilder; | ||
import redis.clients.jedis.util.JedisRoundRobinBase; | ||
|
||
public class FtSearchRoundRobin extends JedisRoundRobinBase<SearchResult> { | ||
|
||
private int batchStart; | ||
private final int batchSize; | ||
private final IntFunction<CommandArguments> args; | ||
|
||
public FtSearchRoundRobin(ConnectionProvider connectionProvider, int batchSize, String indexName, String query, FTSearchParams params) { | ||
super(connectionProvider, new SearchResultBuilder(!params.getNoContent(), params.getWithScores(), false, true)); | ||
this.batchSize = batchSize; | ||
this.args = (limitFirst) -> new CommandArguments(SearchProtocol.SearchCommand.SEARCH) | ||
.add(indexName).add(query).addParams(params.limit(limitFirst, this.batchSize)); | ||
} | ||
|
||
public FtSearchRoundRobin(ConnectionProvider connectionProvider, int batchSize, String indexName, Query query) { | ||
super(connectionProvider, new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), query.getWithPayloads(), true)); | ||
this.batchSize = batchSize; | ||
this.args = (limitFirst) -> new CommandArguments(SearchProtocol.SearchCommand.SEARCH) | ||
.add(indexName).addParams(query.limit(limitFirst, this.batchSize)); | ||
} | ||
|
||
@Override | ||
protected boolean isIterationCompleted(SearchResult reply) { | ||
return batchStart >= reply.getTotalResults() - batchSize; | ||
} | ||
|
||
@Override | ||
protected CommandArguments initCommandArguments() { | ||
batchStart = 0; | ||
return args.apply(batchStart); | ||
} | ||
|
||
@Override | ||
protected CommandArguments nextCommandArguments(SearchResult lastReply) { | ||
batchStart += batchSize; | ||
return args.apply(batchStart); | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
src/main/java/redis/clients/jedis/util/JedisRoundRobinBase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package redis.clients.jedis.util; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.LinkedList; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
import java.util.Queue; | ||
|
||
import redis.clients.jedis.Builder; | ||
import redis.clients.jedis.CommandArguments; | ||
import redis.clients.jedis.Connection; | ||
import redis.clients.jedis.providers.ConnectionProvider; | ||
|
||
public abstract class JedisRoundRobinBase<R> { | ||
|
||
private final Builder<R> builder; | ||
|
||
private final Queue<Map.Entry> connections; | ||
|
||
private Map.Entry connection; | ||
|
||
private R lastReply; | ||
|
||
private boolean roundRobinCompleted; | ||
private boolean iterationCompleted; | ||
|
||
protected JedisRoundRobinBase(ConnectionProvider connectionProvider, Builder<R> responseBuilder) { | ||
Map connectionMap = connectionProvider.getConnectionMap(); | ||
ArrayList<Map.Entry> connectionList = new ArrayList<>(connectionMap.entrySet()); | ||
Collections.shuffle(connectionList); | ||
this.connections = new LinkedList<>(connectionList); | ||
this.builder = responseBuilder; | ||
this.iterationCompleted = true; | ||
this.roundRobinCompleted = this.connections.isEmpty(); | ||
} | ||
|
||
public final boolean isRoundRobinCompleted() { | ||
return roundRobinCompleted; | ||
} | ||
|
||
protected abstract boolean isIterationCompleted(R reply); | ||
|
||
protected abstract CommandArguments initCommandArguments(); | ||
|
||
protected abstract CommandArguments nextCommandArguments(R lastReply); | ||
|
||
public final R get() { | ||
if (roundRobinCompleted) { | ||
throw new NoSuchElementException(); | ||
} | ||
|
||
CommandArguments args; | ||
if (iterationCompleted) { | ||
connection = connections.poll(); | ||
args = initCommandArguments(); | ||
} else { | ||
args = nextCommandArguments(lastReply); | ||
} | ||
|
||
Object rawReply; | ||
if (connection.getValue() instanceof Connection) { | ||
rawReply = ((Connection) connection.getValue()).executeCommand(args); | ||
} else if (connection.getValue() instanceof Pool) { | ||
try (Connection c = ((Pool<Connection>) connection.getValue()).getResource()) { | ||
rawReply = c.executeCommand(args); | ||
} | ||
} else { | ||
throw new IllegalArgumentException(connection.getValue().getClass() + "is not supported."); | ||
} | ||
|
||
lastReply = builder.build(rawReply); | ||
iterationCompleted = isIterationCompleted(lastReply); | ||
if (iterationCompleted) { | ||
if (connections.isEmpty()) { | ||
roundRobinCompleted = true; | ||
} | ||
} | ||
return lastReply; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.