All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.imrafaelmerino.kafkacli.ConsumerStartCommand Maven / Gradle / Ivy

package com.github.imrafaelmerino.kafkacli;

import jio.IO;
import jio.RetryPolicies;
import jio.cli.Command;
import jio.cli.ConsolePrograms;
import jio.cli.ConsolePrograms.AskForInputParams;
import jio.cli.State;
import jsonvalues.JsObj;
import jsonvalues.JsPath;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import static com.github.imrafaelmerino.kafkacli.ConfigurationFields.*;

class ConsumerStartCommand extends Command {

    static final String CREATE_CONSUMER_COMMAND = "consumer-start";
    private static final String USAGE = """
            Usage: consumer-start [consumer-name] [-verbose]

            Description:
            The `consumer-start` command starts a Kafka consumer using the provided configuration.

            Parameters:
            - consumer-name (optional): The name of the consumer to start. If not provided, the user will be prompted to select from a list of available consumers.
            - -verbose (optional): If provided, the consumer will output a verbose log of the received messages.

            Steps:
            1. Without a consumer name:
               - The command will list all available consumers.
               - The user will be prompted to type the name of one of the listed consumers.
               - The user will be asked if they want a verbose output of the received messages (yes | no).
               - If the input is invalid, the user will have three attempts to provide a correct name and response.

            2. With a consumer name:
               - The command will directly attempt to start the specified consumer.
               - If `-verbose` is provided, the consumer will output a verbose log of the received messages.

            Output:
            - Success: "Consumer `` started!"
            - Failure: Appropriate error message if the configuration is not found or if the consumer is already started.

            Example:
            1. Interactive mode (prompt user for consumer name):
               $ consumer-start
               consumer1
               consumer2
               consumer3
               Type the consumer name (choose one of the above):
               Do you want a verbose output of the received messages? (yes | no):

            2. Direct mode (provide consumer name and verbose flag):
               $ consumer-start consumer1 -verbose

            Note:
            Ensure that the consumer configurations are correctly set in the configuration file before starting a consumer.
            """;
    private final KafkaConsumers consumers;


    ConsumerStartCommand(final KafkaConsumers consumers) {
        super(CREATE_CONSUMER_COMMAND,
              USAGE,
              tokens -> tokens[0].equals(CREATE_CONSUMER_COMMAND));
        this.consumers = consumers;
    }

    @Override
    public Function> apply(final JsObj conf,
                                                final State state
                                               ) {
        return args -> {
            if (args.length == 1) {
                var allConsumers = ConfigurationQueries.getConsumers(conf);
                return ConsolePrograms.ASK_FOR_PAIR(Prompts.ASK_FOR_CONSUMER_PARAMS.apply(allConsumers),
                                                    new AskForInputParams(
                                                            "\nDo you want a verbose output of the received messages? "
                                                            + "(yes | no)",
                                                            resp -> resp.equalsIgnoreCase("yes")
                                                                    || resp.equalsIgnoreCase("no"),
                                                            "\nInvalid response.",
                                                            RetryPolicies.limitRetries(3)
                                                    )
                                                   )
                                      .then(pair -> start(conf,
                                                          pair.first(),
                                                          "yes".equalsIgnoreCase(pair.second()))
                                           );
            }
            var consumerName = args[1];
            boolean verbose = Arrays.stream(args)
                                    .toList()
                                    .contains("-verbose");
            return start(conf,
                         consumerName,
                         verbose);
        };
    }

    private IO start(final JsObj conf,
                             final String consumerName,
                             final boolean verbose
                            ) {
        return IO.lazy(() -> {
            JsPath pathConf = JsPath.fromKey(KAFKA)
                                    .key(CONSUMERS)
                                    .key(consumerName);
            JsObj consumerConf = conf.getObj(pathConf);
            if (consumerConf == null) {
                return "The configuration associated to the the consumer `%s` wasn't found at %s".formatted(consumerName,
                                                                                                            pathConf);
            }
            var consumerProps = consumerConf.getObj(CONSUMER_PROPS);
            if (consumerProps == null) {
                return "The kafka configuration associated to the the consumer `%s` wasn't found at %s".formatted(consumerName,
                                                                                                                  pathConf.key(CONSUMER_PROPS));
            }
            if (consumers.isStarted(consumerName)) {
                return "Consumer `%s` already started!".formatted(consumerName);
            }
            var common = conf.getObj(JsPath.fromKey(KAFKA)
                                           .key(COMMON_PROPS));

            Duration pollTimeout = Duration.ofSeconds(consumerConf.getInt(ConfigurationFields.POLL_TIMEOUT_SEC));
            List topics = consumerConf.getArray(TOPICS)
                                              .streamOfValues()
                                              .map(it -> it.toJsStr().value)
                                              .toList();
            consumers.startConsumer(common,
                                    consumerName,
                                    consumerProps,
                                    topics,
                                    pollTimeout,
                                    verbose);
            return "Consumer `%s` started!".formatted(consumerName);
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy