Search in sources :

Example 11 with KsqlRestException

use of io.confluent.ksql.rest.server.resources.KsqlRestException in project ksql by confluentinc.

the class DistributingExecutor method execute.

/**
 * The transactional protocol for sending a command to the command topic is to
 * initTransaction(), beginTransaction(), wait for commandRunner to finish processing all previous
 * commands that were present at the start of the transaction, validate the current command,
 * enqueue the command in the command topic, and commit the transaction.
 * Only successfully committed commands can be read by the command topic consumer.
 * If any exceptions are thrown during this protocol, the transaction is aborted.
 * If a new transactional producer is initialized while the current transaction is incomplete,
 * the old producer will be fenced off and unable to continue with its transaction.
 */
// CHECKSTYLE_RULES.OFF: NPathComplexity
public StatementExecutorResponse execute(final ConfiguredStatement<? extends Statement> statement, final KsqlExecutionContext executionContext, final KsqlSecurityContext securityContext) {
    final String commandRunnerWarningString = commandRunnerWarning.get();
    if (!commandRunnerWarningString.equals("")) {
        throw new KsqlServerException("Failed to handle Ksql Statement." + System.lineSeparator() + commandRunnerWarningString);
    }
    final ConfiguredStatement<?> injected = injectorFactory.apply(executionContext, securityContext.getServiceContext()).inject(statement);
    if (injected.getStatement() instanceof InsertInto) {
        validateInsertIntoQueries(executionContext.getMetaStore(), (InsertInto) injected.getStatement());
    }
    final Optional<StatementExecutorResponse> response = checkIfNotExistsResponse(executionContext, statement);
    if (response.isPresent()) {
        return response.get();
    }
    checkAuthorization(injected, securityContext, executionContext);
    final Producer<CommandId, Command> transactionalProducer = commandQueue.createTransactionalProducer();
    try {
        transactionalProducer.initTransactions();
    } catch (final TimeoutException e) {
        throw new KsqlServerException(errorHandler.transactionInitTimeoutErrorMessage(e), e);
    } catch (final Exception e) {
        throw new KsqlServerException(String.format("Could not write the statement '%s' into the command topic: " + e.getMessage(), statement.getStatementText()), e);
    }
    if (!rateLimiter.tryAcquire(1, TimeUnit.SECONDS)) {
        throw new KsqlRestException(Errors.tooManyRequests("DDL/DML rate is crossing the configured rate limit of statements/second"));
    }
    CommandId commandId = null;
    try {
        transactionalProducer.beginTransaction();
        commandQueue.waitForCommandConsumer();
        commandId = commandIdAssigner.getCommandId(statement.getStatement());
        final Command command = validatedCommandFactory.create(injected, executionContext.createSandbox(executionContext.getServiceContext()));
        final QueuedCommandStatus queuedCommandStatus = commandQueue.enqueueCommand(commandId, command, transactionalProducer);
        transactionalProducer.commitTransaction();
        final CommandStatus commandStatus = queuedCommandStatus.tryWaitForFinalStatus(distributedCmdResponseTimeout);
        return StatementExecutorResponse.handled(Optional.of(new CommandStatusEntity(injected.getStatementText(), queuedCommandStatus.getCommandId(), commandStatus, queuedCommandStatus.getCommandSequenceNumber(), getDeprecatedWarnings(executionContext.getMetaStore(), injected))));
    } catch (final ProducerFencedException | OutOfOrderSequenceException | AuthorizationException e) {
        // This catch doesn't abortTransaction() since doing that would throw another exception.
        if (commandId != null) {
            commandQueue.abortCommand(commandId);
        }
        throw new KsqlServerException(String.format("Could not write the statement '%s' into the command topic.", statement.getStatementText()), e);
    } catch (final Exception e) {
        transactionalProducer.abortTransaction();
        if (commandId != null) {
            commandQueue.abortCommand(commandId);
        }
        throw new KsqlServerException(String.format("Could not write the statement '%s' into the command topic.", statement.getStatementText()), e);
    } finally {
        transactionalProducer.close();
    }
}
Also used : AuthorizationException(org.apache.kafka.common.errors.AuthorizationException) KsqlServerException(io.confluent.ksql.util.KsqlServerException) StatementExecutorResponse(io.confluent.ksql.rest.server.execution.StatementExecutorResponse) TimeoutException(org.apache.kafka.common.errors.TimeoutException) AuthorizationException(org.apache.kafka.common.errors.AuthorizationException) OutOfOrderSequenceException(org.apache.kafka.common.errors.OutOfOrderSequenceException) KsqlServerException(io.confluent.ksql.util.KsqlServerException) ProducerFencedException(org.apache.kafka.common.errors.ProducerFencedException) KsqlRestException(io.confluent.ksql.rest.server.resources.KsqlRestException) KsqlException(io.confluent.ksql.util.KsqlException) CommandStatusEntity(io.confluent.ksql.rest.entity.CommandStatusEntity) ProducerFencedException(org.apache.kafka.common.errors.ProducerFencedException) OutOfOrderSequenceException(org.apache.kafka.common.errors.OutOfOrderSequenceException) KsqlRestException(io.confluent.ksql.rest.server.resources.KsqlRestException) InsertInto(io.confluent.ksql.parser.tree.InsertInto) CommandStatus(io.confluent.ksql.rest.entity.CommandStatus) CommandId(io.confluent.ksql.rest.entity.CommandId) TimeoutException(org.apache.kafka.common.errors.TimeoutException)

Aggregations

KsqlRestException (io.confluent.ksql.rest.server.resources.KsqlRestException)11 Test (org.junit.Test)8 MetricsCallbackHolder (io.confluent.ksql.api.server.MetricsCallbackHolder)4 KsqlRequest (io.confluent.ksql.rest.entity.KsqlRequest)4 CompletableFuture (java.util.concurrent.CompletableFuture)4 PrintTopic (io.confluent.ksql.parser.tree.PrintTopic)3 TimeoutException (java.util.concurrent.TimeoutException)3 CommandStatusEntity (io.confluent.ksql.rest.entity.CommandStatusEntity)2 InsertInto (io.confluent.ksql.parser.tree.InsertInto)1 Query (io.confluent.ksql.parser.tree.Query)1 CommandId (io.confluent.ksql.rest.entity.CommandId)1 CommandStatus (io.confluent.ksql.rest.entity.CommandStatus)1 KsqlEntity (io.confluent.ksql.rest.entity.KsqlEntity)1 KsqlErrorMessage (io.confluent.ksql.rest.entity.KsqlErrorMessage)1 StatementExecutorResponse (io.confluent.ksql.rest.server.execution.StatementExecutorResponse)1 KsqlConfig (io.confluent.ksql.util.KsqlConfig)1 KsqlException (io.confluent.ksql.util.KsqlException)1 KsqlServerException (io.confluent.ksql.util.KsqlServerException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1