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

com.datastax.oss.simulacron.http.server.QueryManager Maven / Gradle / Ivy

There is a newer version: 0.12.0
Show newest version
/*
 * Copyright (C) 2017-2017 DataStax Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.datastax.oss.simulacron.http.server;

import com.datastax.oss.protocol.internal.response.result.RawType;
import com.datastax.oss.simulacron.common.cluster.ObjectMapperHolder;
import com.datastax.oss.simulacron.common.cluster.RequestPrime;
import com.datastax.oss.simulacron.common.codec.CodecUtils;
import com.datastax.oss.simulacron.common.result.SuccessResult;
import com.datastax.oss.simulacron.common.stubbing.Prime;
import com.datastax.oss.simulacron.server.Server;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.datastax.oss.simulacron.http.server.HttpUtils.handleMessage;

public class QueryManager implements HttpListener {
  private static Logger logger = LoggerFactory.getLogger(QueryManager.class);

  private final Server server;

  public QueryManager(Server server) {
    this.server = server;
  }

  /**
   * This is an async callback that will be invoked whenever a request to /prime is posted. It will
   * parse the provided json and construct a query which when called from the server will return the
   * rows defined.
   *
   * 

Example Supported HTTP Requests * *

POST http://iphere:porthere/prime with json body of {@code { "when": { "query": "SELECT * * FROM table" }, "then": { "rows": [ { "row1": "sample1", "row2": "1" } ], "result": "success", * "column_types": { "row1": "ascii", "row2": "bigint" } } }} * *

This will return a row containing two columns when a SELECT * FROM table. The row will * contain two fields row1, and row2, that are of type ascii and bigint respectively * * @param context RoutingContext provided by vertx */ private void primeQuery(RoutingContext context) { context .request() .bodyHandler( totalBuffer -> { String jsonBody = ""; try { logger.info("Full body received, length = " + totalBuffer.length()); Scope scope = HttpUtils.getScope(context, server); if (scope == null) { return; } jsonBody = totalBuffer.toString(); ObjectMapper om = ObjectMapperHolder.getMapper(); RequestPrime query = om.readValue(jsonBody, RequestPrime.class); if (query.then instanceof SuccessResult) { SuccessResult success = (SuccessResult) query.then; for (String key : success.columnTypes.keySet()) { String typeName = success.columnTypes.get(key); RawType type = CodecUtils.getTypeFromName(typeName); if (type == null) { handleBadType(key, typeName, context); } } } Prime prime = new Prime(query); HttpUtils.find(server, scope).prime(prime); } catch (Exception e) { handleQueryError(e, "prime query", context); } if (!context.response().ended()) { context .request() .response() .putHeader("content-type", "application/json") .setStatusCode(201) .end(jsonBody); } }); } /** * This is an async callback that will be invoked whenever a request to /clear_primed is posted. * It will remove all primed queries that have been set so far * *

Example Supported HTTP Requests * *

POST http://iphere:porthere/clear_primed no payload. * * @param context RoutingContext provided by vertx */ private void clearPrimedQueries(RoutingContext context) { context .request() .bodyHandler( totalBuffer -> { Scope scope = HttpUtils.getScope(context, server); if (scope == null) { return; } int cleared = 0; try { cleared = HttpUtils.find(server, scope).clearPrimes(true); } catch (Exception e) { handleQueryError(e, "clear primed queries", context); } if (!context.response().ended()) { handleMessage(new Message("Cleared " + cleared + " primed queries", 202), context); } }); } /** * Convenience method to set failure on response and print a relative error messaged * * @param e Exception thrown * @param operation for logging. * @param context RoutingContext to set failure upon */ private void handleQueryError(Throwable e, String operation, RoutingContext context) { String errorString = "Error encountered while attempting to " + operation + ". See logs for details"; HttpUtils.handleError(new ErrorMessage(errorString, 400, e), context); } /** * Convenience method to set failure on response when an invalid type is detected * * @param context RoutingContext to set failure upon */ private void handleBadType(String key, String typeName, RoutingContext context) { String errorMsg = "Invalid type defined for column " + key + ", " + typeName + " is not a recognized type."; HttpUtils.handleError(new ErrorMessage(errorMsg, 400), context); } public void registerWithRouter(Router router) { // Priming queries router.route(HttpMethod.POST, "/prime/:clusterIdOrName").handler(this::primeQuery); router .route(HttpMethod.POST, "/prime/:clusterIdOrName/:datacenterIdOrName") .handler(this::primeQuery); router .route(HttpMethod.POST, "/prime/:clusterIdOrName/:datacenterIdOrName/:nodeIdOrName") .handler(this::primeQuery); //Deleting primed queries router.route(HttpMethod.DELETE, "/prime/:clusterIdOrName").handler(this::clearPrimedQueries); router .route(HttpMethod.DELETE, "/prime/:clusterIdOrName/:datacenterIdOrName") .handler(this::clearPrimedQueries); router .route(HttpMethod.DELETE, "/prime/:clusterIdOrName/:datacenterIdOrName/:nodeIdOrName") .handler(this::primeQuery); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy