diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/DbExport.java b/plugins/riot/src/main/java/com/redis/riot/cli/DbExport.java index 6f5cffb25..c6ebe33e8 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/DbExport.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/DbExport.java @@ -16,8 +16,8 @@ import com.redis.riot.cli.common.AbstractExportCommand; import com.redis.riot.cli.common.CommandContext; import com.redis.riot.cli.common.DatabaseHelper; +import com.redis.riot.cli.common.DbExportOptions; import com.redis.riot.cli.common.StepProgressMonitor; -import com.redis.riot.cli.db.DbExportOptions; import com.redis.riot.core.processor.DataStructureToMapProcessor; import com.redis.spring.batch.RedisItemReader; import com.redis.spring.batch.common.DataStructure; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/DbImport.java b/plugins/riot/src/main/java/com/redis/riot/cli/DbImport.java index 624c61285..2a3847c7d 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/DbImport.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/DbImport.java @@ -16,8 +16,8 @@ import com.redis.riot.cli.common.AbstractImportCommand; import com.redis.riot.cli.common.CommandContext; import com.redis.riot.cli.common.DatabaseHelper; +import com.redis.riot.cli.common.DbImportOptions; import com.redis.riot.cli.common.StepProgressMonitor; -import com.redis.riot.cli.db.DbImportOptions; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/Main.java b/plugins/riot/src/main/java/com/redis/riot/cli/Main.java index f1e8fa21f..a6f80b827 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/Main.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/Main.java @@ -25,7 +25,8 @@ @Command(name = "riot", usageHelpAutoWidth = true, versionProvider = ManifestVersionProvider.class, subcommands = { DbImport.class, DbExport.class, DumpImport.class, FileImport.class, FileExport.class, FakerImport.class, - Generate.class, Replicate.class, Ping.class, GenerateCompletion.class }) + Generate.class, Replicate.class, Ping.class, + GenerateCompletion.class }, resourceBundle = "com.redis.riot.Messages") public class Main { @Mixin @@ -56,17 +57,17 @@ public int execute(String... args) { return commandLine().execute(args); } - public CommandLine commandLine() { - CommandLine commandLine = new CommandLine(this); - commandLine.setExecutionStrategy(new RiotExecutionStrategy(LoggingOptions::executionStrategy)); - commandLine.setExecutionExceptionHandler(this::handleExecutionException); - registerConverters(commandLine); - commandLine.setCaseInsensitiveEnumValuesAllowed(true); - commandLine.setUnmatchedOptionsAllowedAsOptionParameters(false); - return commandLine; + public static CommandLine commandLine() { + CommandLine cmd = new CommandLine(new Main()); + cmd.setExecutionStrategy(new RiotExecutionStrategy(LoggingOptions::executionStrategy)); + cmd.setExecutionExceptionHandler(Main::handleExecutionException); + ((Main) cmd.getCommand()).registerConverters(cmd); + cmd.setCaseInsensitiveEnumValuesAllowed(true); + cmd.setUnmatchedOptionsAllowedAsOptionParameters(false); + return cmd; } - private int handleExecutionException(Exception ex, CommandLine cmd, ParseResult parseResult) { + private static int handleExecutionException(Exception ex, CommandLine cmd, ParseResult parseResult) { // bold red error message cmd.getErr().println(cmd.getColorScheme().errorText(ex.getMessage())); return cmd.getExitCodeExceptionMapper() == null ? cmd.getCommandSpec().exitCodeOnExecutionException() diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/Ping.java b/plugins/riot/src/main/java/com/redis/riot/cli/Ping.java index 34d40fae9..d35ce957f 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/Ping.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/Ping.java @@ -55,8 +55,8 @@ public PingTask(CommandContext context, PingOptions options) { @Override public RepeatStatus call() throws Exception { - if (iteration.get() > 0 && getTransferOptions().getSleep() > 0) { - Thread.sleep(Duration.ofSeconds(getTransferOptions().getSleep()).toMillis()); + if (iteration.get() > 0 && getJobOptions().getSleep() > 0) { + Thread.sleep(Duration.ofSeconds(getJobOptions().getSleep()).toMillis()); } try (StatefulRedisModulesConnection connection = RedisModulesUtils .connection(context.getRedisClient())) { diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/Replicate.java b/plugins/riot/src/main/java/com/redis/riot/cli/Replicate.java index 10d0c9dbf..78c66b61a 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/Replicate.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/Replicate.java @@ -33,7 +33,7 @@ import com.redis.riot.cli.common.RedisOptions; import com.redis.riot.cli.common.RedisWriterOptions; import com.redis.riot.cli.common.ReplicateCommandContext; -import com.redis.riot.cli.common.ReplicationOptions; +import com.redis.riot.cli.common.ReplicateOptions; import com.redis.riot.cli.common.ReplicationStrategy; import com.redis.riot.cli.common.StepProgressMonitor; import com.redis.riot.core.KeyComparisonLogger; @@ -58,7 +58,6 @@ import io.lettuce.core.codec.ByteArrayCodec; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; -import picocli.CommandLine.Mixin; @SuppressWarnings({ "rawtypes", "unchecked" }) @Command(name = "replicate", description = "Replicate a Redis database into another Redis database.") @@ -67,7 +66,7 @@ public class Replicate extends AbstractExportCommand { private static final Logger log = Logger.getLogger(Replicate.class.getName()); private static final String COMPARE_MESSAGE = " %,d missing, %,d type, %,d value, %,d ttl"; - private static final String QUEUE_MESSAGE = " %,d queued notifications"; + private static final String QUEUE_MESSAGE = " %,d notifications in queue"; private static final String JOB_NAME = "replicate-job"; private static final String COMPARE_STEP = "compare-step"; private static final String SCAN_STEP = "scan-step"; @@ -82,8 +81,8 @@ public class Replicate extends AbstractExportCommand { @ArgGroup(exclusive = false, heading = "Writer options%n") private RedisWriterOptions writerOptions = new RedisWriterOptions(); - @Mixin - private ReplicationOptions replicationOptions = new ReplicationOptions(); + @ArgGroup(exclusive = false, heading = "Replication options%n") + private ReplicateOptions replicationOptions = new ReplicateOptions(); public RedisOptions getTargetRedisOptions() { return targetRedisOptions; @@ -100,11 +99,11 @@ protected CommandContext context(RedisURI redisURI, AbstractRedisClient redisCli return new ReplicateCommandContext(redisURI, redisClient, targetRedisURI, targetRedisClient); } - public ReplicationOptions getReplicateOptions() { + public ReplicateOptions getReplicateOptions() { return replicationOptions; } - public void setReplicationOptions(ReplicationOptions replicationOptions) { + public void setReplicationOptions(ReplicateOptions replicationOptions) { this.replicationOptions = replicationOptions; } diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/common/AbstractCommand.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/AbstractCommand.java index 15fa60ec8..a2fe2fc02 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/common/AbstractCommand.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/AbstractCommand.java @@ -47,6 +47,7 @@ import io.lettuce.core.event.DefaultEventPublisherOptions; import io.lettuce.core.metrics.CommandLatencyCollector; import io.lettuce.core.metrics.DefaultCommandLatencyCollectorOptions; +import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; import picocli.CommandLine.Model.CommandSpec; @@ -68,8 +69,8 @@ public abstract class AbstractCommand implements Callable { @Mixin private HelpOptions helpOptions; - @Mixin - private TransferOptions transferOptions = new TransferOptions(); + @ArgGroup(exclusive = false, heading = "Job options%n") + private JobOptions jobOptions = new JobOptions(); private JobRepository jobRepository; private JobLauncher jobLauncher; @@ -218,21 +219,21 @@ protected JobBuilder job(String name) { return jobBuilderFactory().get(name); } - public TransferOptions getTransferOptions() { - return transferOptions; + public JobOptions getJobOptions() { + return jobOptions; } - public void setTransferOptions(TransferOptions options) { - this.transferOptions = options; + public void setJobOptions(JobOptions options) { + this.jobOptions = options; } private SimpleStepBuilder step(String name) { - SimpleStepBuilder step = stepBuilder(name).chunk(transferOptions.getChunkSize()); - Utils.multiThread(step, transferOptions.getThreads()); - if (transferOptions.getSkipPolicy() == StepSkipPolicy.NEVER) { + SimpleStepBuilder step = stepBuilder(name).chunk(jobOptions.getChunkSize()); + Utils.multiThread(step, jobOptions.getThreads()); + if (jobOptions.getSkipPolicy() == StepSkipPolicy.NEVER) { return step; } - return step.faultTolerant().skipPolicy(skipPolicy(transferOptions)); + return step.faultTolerant().skipPolicy(skipPolicy(jobOptions)); } protected StepBuilder stepBuilder(String name) { @@ -252,20 +253,20 @@ protected SimpleStepBuilder step(String name, ItemReader reader, protected StepProgressMonitor monitor(String task) { StepProgressMonitor monitor = new StepProgressMonitor(); monitor.withTask(task); - monitor.withStyle(transferOptions.getProgressBarStyle()); - monitor.withUpdateInterval(Duration.ofMillis(transferOptions.getProgressUpdateInterval())); + monitor.withStyle(jobOptions.getProgressBarStyle()); + monitor.withUpdateInterval(Duration.ofMillis(jobOptions.getProgressUpdateInterval())); return monitor; } private ItemWriter throttle(ItemWriter writer) { - Duration sleep = Duration.ofMillis(transferOptions.getSleep()); + Duration sleep = Duration.ofMillis(jobOptions.getSleep()); if (sleep.isNegative() || sleep.isZero()) { return writer; } return new ThrottledItemWriter<>(writer, sleep); } - private SkipPolicy skipPolicy(TransferOptions options) { + private SkipPolicy skipPolicy(JobOptions options) { switch (options.getSkipPolicy()) { case ALWAYS: return new AlwaysSkipItemSkipPolicy(); diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/db/DataSourceOptions.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/DataSourceOptions.java similarity index 97% rename from plugins/riot/src/main/java/com/redis/riot/cli/db/DataSourceOptions.java rename to plugins/riot/src/main/java/com/redis/riot/cli/common/DataSourceOptions.java index b763fef37..d14f2f7e2 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/db/DataSourceOptions.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/DataSourceOptions.java @@ -1,4 +1,4 @@ -package com.redis.riot.cli.db; +package com.redis.riot.cli.common; import picocli.CommandLine.Option; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/common/DatabaseHelper.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/DatabaseHelper.java index b5e9f7d9e..f6cc1b04f 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/common/DatabaseHelper.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/DatabaseHelper.java @@ -4,8 +4,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import com.redis.riot.cli.db.DataSourceOptions; - public interface DatabaseHelper { static DataSource dataSource(DataSourceOptions options) { diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/db/DbExportOptions.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/DbExportOptions.java similarity index 97% rename from plugins/riot/src/main/java/com/redis/riot/cli/db/DbExportOptions.java rename to plugins/riot/src/main/java/com/redis/riot/cli/common/DbExportOptions.java index fa3b3b019..a1b7566b0 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/db/DbExportOptions.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/DbExportOptions.java @@ -1,4 +1,4 @@ -package com.redis.riot.cli.db; +package com.redis.riot.cli.common; import picocli.CommandLine.Mixin; import picocli.CommandLine.Option; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/db/DbImportOptions.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/DbImportOptions.java similarity index 98% rename from plugins/riot/src/main/java/com/redis/riot/cli/db/DbImportOptions.java rename to plugins/riot/src/main/java/com/redis/riot/cli/common/DbImportOptions.java index 42ee1c3dc..93f4cb169 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/db/DbImportOptions.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/DbImportOptions.java @@ -1,4 +1,4 @@ -package com.redis.riot.cli.db; +package com.redis.riot.cli.common; import org.springframework.batch.item.database.AbstractCursorItemReader; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/common/TransferOptions.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/JobOptions.java similarity index 99% rename from plugins/riot/src/main/java/com/redis/riot/cli/common/TransferOptions.java rename to plugins/riot/src/main/java/com/redis/riot/cli/common/JobOptions.java index 189ce70a8..cfa2f30cf 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/common/TransferOptions.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/JobOptions.java @@ -7,7 +7,7 @@ import me.tongfei.progressbar.ProgressBarStyle; import picocli.CommandLine.Option; -public class TransferOptions { +public class JobOptions { public static final StepSkipPolicy DEFAULT_SKIP_POLICY = StepSkipPolicy.LIMIT; public static final int DEFAULT_CHUNK_SIZE = ReaderOptions.DEFAULT_CHUNK_SIZE; diff --git a/plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicationOptions.java b/plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicateOptions.java similarity index 99% rename from plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicationOptions.java rename to plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicateOptions.java index c7c2d4ec0..ae6bb1b22 100644 --- a/plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicationOptions.java +++ b/plugins/riot/src/main/java/com/redis/riot/cli/common/ReplicateOptions.java @@ -13,7 +13,7 @@ import io.lettuce.core.ReadFrom; import picocli.CommandLine.Option; -public class ReplicationOptions { +public class ReplicateOptions { @Option(names = "--mode", description = "Replication mode: ${COMPLETION-CANDIDATES} (default: ${DEFAULT-VALUE}).", paramLabel = "") private ReplicationMode mode = ReplicationMode.SNAPSHOT; diff --git a/plugins/riot/src/main/resources/com/redis/riot/Messages.properties b/plugins/riot/src/main/resources/com/redis/riot/Messages.properties new file mode 100644 index 000000000..3f198668d --- /dev/null +++ b/plugins/riot/src/main/resources/com/redis/riot/Messages.properties @@ -0,0 +1,5 @@ +# Header +usage.headerHeading = RIOT is a data import/export tool for Redis.%n%n + +# Footer +usage.footerHeading = %nDocumentation found at https://developer.redis.com/riot%n \ No newline at end of file