Merge branch 'master' into S2GRAPH-203 * master: [S2GRAPH-219] Added query that includes all vertices and associated edges for GraphVisualize. [S2GRAPH-218] add operations not supported on sql [S2GRAPH-216] Provide a transform directive in the GraphQL query result Extract Where and EdgeTransformer to TraversalHelper. make middleware for GraphFormatWriter add extension for SigmaJs add continuous trigger option add partition options for source df add dataframe cache option support multiple partitions add operations not supported on sql add simple test implement @trasform directive
Project: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/commit/4b50b29c Tree: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/tree/4b50b29c Diff: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/diff/4b50b29c Branch: refs/heads/master Commit: 4b50b29cc89b7bbeb018763891c2e09177d58dd7 Parents: 23a2277 35a369f Author: daewon <dae...@apache.org> Authored: Mon Jun 18 15:32:42 2018 +0900 Committer: daewon <dae...@apache.org> Committed: Mon Jun 18 15:32:42 2018 +0900 ---------------------------------------------------------------------- CHANGES | 4 + build.sbt | 4 +- s2core/build.sbt | 2 +- .../apache/s2graph/core/TraversalHelper.scala | 42 ++++++- .../core/fetcher/annoy/AnnoyModelFetcher.scala | 59 +--------- .../core/fetcher/fasttext/FastTextFetcher.scala | 8 +- .../fetcher/tensorflow/InceptionFetcher.scala | 8 +- .../apache/s2graph/core/storage/StorageIO.scala | 48 +++----- s2graphql/build.sbt | 4 +- .../apache/s2graph/graphql/GraphQLServer.scala | 9 +- .../org/apache/s2graph/graphql/HttpServer.scala | 4 +- .../graphql/middleware/GraphFormatWriter.scala | 101 +++++++++++++++++ .../s2graph/graphql/middleware/Transform.scala | 51 +++++++++ .../graphql/repository/GraphRepository.scala | 5 +- .../s2graph/graphql/types/FieldResolver.scala | 2 +- .../graphql/types/PlayJsonScalarType.scala | 112 +++++++++++++++++++ .../s2graph/graphql/types/S2Directive.scala | 68 +++++++++++ .../s2graph/graphql/types/SchemaDef.scala | 12 +- .../apache/s2graph/graphql/DirectiveTest.scala | 53 +++++++++ .../scala/org/apache/s2graph/s2jobs/Job.scala | 11 +- .../apache/s2graph/s2jobs/task/Process.scala | 64 ++++++++++- .../org/apache/s2graph/s2jobs/task/Sink.scala | 6 +- .../org/apache/s2graph/s2jobs/task/Source.scala | 17 ++- .../org/apache/s2graph/s2jobs/task/Task.scala | 3 +- 24 files changed, 577 insertions(+), 120 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/4b50b29c/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala ---------------------------------------------------------------------- diff --cc s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala index f71e16f,b7c0381..5f1c225 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/GraphQLServer.scala @@@ -26,8 -26,9 +26,9 @@@ import akka.http.scaladsl.model.StatusC import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server._ import com.typesafe.config.ConfigFactory ++import org.apache.s2graph.graphql.middleware.{GraphFormatted, Transform} import org.apache.s2graph.core.S2Graph import org.apache.s2graph.core.utils.SafeUpdateCache -import org.apache.s2graph.graphql.middleware.{GraphFormatted} import org.apache.s2graph.graphql.repository.GraphRepository import org.apache.s2graph.graphql.types.SchemaDef import org.slf4j.LoggerFactory @@@ -89,47 -116,38 +90,53 @@@ object GraphQLServer newSchema } - val TransformMiddleWare = List(org.apache.s2graph.graphql.middleware.Transform()) + def formatError(error: Throwable): JsValue = error match { + case syntaxError: SyntaxError â + JsObject("errors" â JsArray( + JsObject( + "message" â JsString(syntaxError.getMessage), + "locations" â JsArray(JsObject( + "line" â JsNumber(syntaxError.originalError.position.line), + "column" â JsNumber(syntaxError.originalError.position.column)))))) + + case NonFatal(e) â formatError(e.toString) + case e â throw e + } - private def executeGraphQLQuery(query: Document, op: Option[String], vars: JsObject)(implicit e: ExecutionContext) = { - val cacheKey = className + "s2Schema" - val s2schema = schemaCache.withCache(cacheKey, broadcast = false)(createNewSchema()) + def formatError(message: String): JsObject = + JsObject("errors" â JsArray(JsObject("message" â JsString(message)))) + def onEvictSchema(o: AnyRef): Unit = { + logger.info("Schema Evicted") + } + ++ val TransformMiddleWare = List(org.apache.s2graph.graphql.middleware.Transform()) ++ + def executeGraphQLQuery(query: Document, op: Option[String], vars: JsObject)(implicit e: ExecutionContext) = { import GraphRepository._ + + val cacheKey = className + "s2Schema" + val s2schema = schemaCache.withCache(cacheKey, broadcast = false, onEvict = onEvictSchema)(createNewSchema()) val resolver: DeferredResolver[GraphRepository] = DeferredResolver.fetchers(vertexFetcher, edgeFetcher) + val includeGrpaph = vars.fields.get("includeGraph").contains(spray.json.JsBoolean(true)) - val middleWares = if (includeGrpaph) { - GraphFormatted :: TransformMiddleWare - } else { - TransformMiddleWare - } ++ val middleWares = if (includeGrpaph) GraphFormatted :: TransformMiddleWare else TransformMiddleWare + Executor.execute( s2schema, query, s2Repository, variables = vars, operationName = op, - deferredResolver = resolver + deferredResolver = resolver, + middleware = middleWares - ) - .map((res: spray.json.JsValue) => OK -> res) + ).map((res: spray.json.JsValue) => OK -> res) .recover { case error: QueryAnalysisError => - logger.warn(error.getMessage, error) + logger.error("Error on execute", error) BadRequest -> error.resolveError case error: ErrorWithResolver => - logger.error(error.getMessage, error) + logger.error("Error on execute", error) InternalServerError -> error.resolveError } } http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/4b50b29c/s2graphql/src/main/scala/org/apache/s2graph/graphql/HttpServer.scala ---------------------------------------------------------------------- diff --cc s2graphql/src/main/scala/org/apache/s2graph/graphql/HttpServer.scala index 1620f30,6f57cc4..755d185 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/HttpServer.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/HttpServer.scala @@@ -50,52 -39,16 +50,52 @@@ object Server extends App implicit val materializer = ActorMaterializer() import system.dispatcher - import scala.concurrent.duration._ - val route: Flow[HttpRequest, HttpResponse, Any] = (post & path("graphql")) { - entity(as[spray.json.JsValue])(GraphQLServer.endpoint) - } ~ (post & path("updateEdgeFetcher")) { - entity(as[spray.json.JsValue])(GraphQLServer.updateEdgeFetcher) - } ~ { - getFromResource("assets/graphiql.html") - } + import spray.json.DefaultJsonProtocol._ + + val route: Route = + get { + getFromResource("assets/graphiql.html") + } ~ (post & path("updateEdgeFetcher")) { + entity(as[JsValue]) { body => + GraphQLServer.updateEdgeFetcher(body) match { + case Success(_) => complete(StatusCodes.OK -> JsString("Update fetcher finished")) + case Failure(e) => + logger.error("Error on execute", e) + complete(StatusCodes.InternalServerError -> spray.json.JsObject("message" -> JsString(e.toString))) + } + } + } ~ (post & path("graphql")) { + parameters('operationName.?, 'variables.?) { (operationNameParam, variablesParam) => + entity(as[Document]) { document â + variablesParam.map(parseJson) match { + case None â complete(GraphQLServer.executeGraphQLQuery(document, operationNameParam, JsObject())) + case Some(Right(js)) â complete(GraphQLServer.executeGraphQLQuery(document, operationNameParam, js.asJsObject)) + case Some(Left(e)) â + logger.error("Error on execute", e) + complete(StatusCodes.BadRequest -> GraphQLServer.formatError(e)) + } + } ~ entity(as[JsValue]) { body â + val fields = body.asJsObject.fields + + val query = fields.get("query").map(js => js.convertTo[String]) - val operationName = fields.get("operationName").filter(_ == null).map(_.convertTo[String]) - val variables = fields.get("variables").filter(_ == null) ++ val operationName = fields.get("operationName").filterNot(_ == null).map(_.convertTo[String]) ++ val variables = fields.get("variables").filterNot(_ == null) + + query.map(QueryParser.parse(_)) match { + case None â complete(StatusCodes.BadRequest -> GraphQLServer.formatError("No query to execute")) + case Some(Failure(error)) â + logger.error("Error on execute", error) + complete(StatusCodes.BadRequest -> GraphQLServer.formatError(error)) + case Some(Success(document)) => variables match { + case Some(js) â complete(GraphQLServer.executeGraphQLQuery(document, operationName, js.asJsObject)) + case None â complete(GraphQLServer.executeGraphQLQuery(document, operationName, JsObject())) + } + } + } + } + } val port = sys.props.get("http.port").fold(8000)(_.toInt)