From b9d2c22066c63da5f730654a83d81ffc6a1aad3d Mon Sep 17 00:00:00 2001
From: Leonardo Menezes <mail@lmenezes.com>
Date: Sat, 7 Oct 2017 17:50:33 +0200
Subject: [PATCH] optimised cluster changes api

---
 .../ClusterChangesController.scala            | 31 ++++------------
 app/services/changes/DataService.scala        | 36 +++++++++++++++++++
 .../ClusterChangesControllerSpec.scala        | 20 +++++------
 3 files changed, 53 insertions(+), 34 deletions(-)
 create mode 100644 app/services/changes/DataService.scala

diff --git a/app/controllers/ClusterChangesController.scala b/app/controllers/ClusterChangesController.scala
index 8fc9e64..41cb4b6 100644
--- a/app/controllers/ClusterChangesController.scala
+++ b/app/controllers/ClusterChangesController.scala
@@ -3,36 +3,19 @@ package controllers
 import javax.inject.Inject
 
 import controllers.auth.AuthenticationModule
-import elastic.{ElasticClient, Error}
-import models.commons.{Indices, Nodes}
+import elastic.ElasticClient
 import models.{CerebroResponse, Hosts}
-import play.api.libs.json.Json
+import services.changes.DataService
 
 import scala.concurrent.ExecutionContext.Implicits.global
-import scala.concurrent.Future
 
 class ClusterChangesController @Inject()(val authentication: AuthenticationModule,
                                          val hosts: Hosts,
-                                         client: ElasticClient) extends BaseController {
+                                         client: ElasticClient,
+                                         data: DataService) extends BaseController {
 
-  def get = process { request =>
-    Future.sequence(Seq(
-      client.getIndices(request.target),
-      client.getNodes(request.target),
-      client.main(request.target)
-    )).map { responses =>
-      val failed = responses.find(_.isInstanceOf[Error])
-      failed match {
-        case None =>
-          val body = Json.obj(
-            "indices" -> Indices(responses(0).body),
-            "nodes" -> Nodes(responses(1).body),
-            "cluster_name" -> (responses(2).body \ "cluster_name").as[String]
-          )
-          CerebroResponse(200, body)
-        case Some(f) =>
-          CerebroResponse(f.status, f.body)
-      }
-    }
+  def get = process {
+    request => data.getData(request.target).map(CerebroResponse(200, _))
   }
+
 }
diff --git a/app/services/changes/DataService.scala b/app/services/changes/DataService.scala
new file mode 100644
index 0000000..97f22df
--- /dev/null
+++ b/app/services/changes/DataService.scala
@@ -0,0 +1,36 @@
+package services.changes
+
+import com.google.inject.Inject
+import elastic.{ElasticClient, Error}
+import models.ElasticServer
+import models.commons.{Indices, Nodes}
+import play.api.libs.json.{JsValue, Json}
+import services.exception.RequestFailedException
+
+import scala.concurrent.ExecutionContext.Implicits.global
+import scala.concurrent.Future
+
+class DataService @Inject()(client: ElasticClient) {
+
+  val apis = Seq(
+    "_cat/nodes?format=json&h=name", // Node names
+    "_cat/indices?format=json&h=index", // Index names
+    "_cat/health?h=cluster&format=json" // Cluster name
+  )
+
+  def getData(target: ElasticServer): Future[JsValue] =
+    Future.sequence(apis.map(client.executeRequest("GET", _, None, target))).map { responses =>
+      responses.zipWithIndex.find(_._1.isInstanceOf[Error]) match {
+        case Some((response, idx)) =>
+          throw RequestFailedException(apis(idx), response.status, response.body.toString())
+
+        case None =>
+          Json.obj(
+          "nodes" -> Nodes(responses(0).body),
+          "indices" -> Indices(responses(1).body),
+          "cluster_name" -> (responses(2).body \\ "cluster").head
+        )
+      }
+    }
+
+}
diff --git a/test/controllers/ClusterChangesControllerSpec.scala b/test/controllers/ClusterChangesControllerSpec.scala
index d7a9c7f..ae9d95a 100644
--- a/test/controllers/ClusterChangesControllerSpec.scala
+++ b/test/controllers/ClusterChangesControllerSpec.scala
@@ -1,7 +1,6 @@
 package controllers
 
-import controllers.AnalysisControllerSpec.application
-import elastic.{ElasticResponse, Success}
+import elastic.Success
 import models.ElasticServer
 import play.api.libs.json.Json
 import play.api.test.FakeRequest
@@ -28,26 +27,27 @@ object ClusterChangesControllerSpec extends MockedServices {
         |}
       """.stripMargin
     )
-    val mainResponse = Json.parse("""{"cluster_name": "elasticsearch"}""")
+    val healthResponse = Json.parse("""[{"cluster": "elasticsearch"}]""")
     val indicesResponse = Json.parse(
       """
         |[
-        |  {"health":"green","status":"open","index":"index1","pri":"10","rep":"0","docs.count":"4330","docs.deleted":"10","store.size":"4.1mb","pri.store.size":"4.1mb"},
-        |  {"health":"green","status":"closed","index":"index2","pri":"10","rep":"0","docs.count":"1497203","docs.deleted":"5048","store.size":"860.9mb","pri.store.size":"860.9mb"}
+        |  {"index":"index1"},
+        |  {"index":"index2"}
         |]
       """.stripMargin
     )
     val nodesResponse = Json.parse(
       """
       |[
-      |  {"host":"127.0.0.1","ip":"127.0.0.1","name":"Shriek"},
-      |  {"host":"127.0.0.1","ip":"127.0.0.1","name":"Jimaine Szardos"}
+      |  {"name":"Shriek"},
+      |  {"name":"Jimaine Szardos"}
       |]
       """.stripMargin
     )
-    client.main(ElasticServer("somehost", None)) returns Future.successful(Success(200, mainResponse))
-    client.getNodes(ElasticServer("somehost", None)) returns Future.successful(Success(200, nodesResponse))
-    client.getIndices(ElasticServer("somehost", None)) returns Future.successful(Success(200, indicesResponse))
+
+    client.executeRequest("GET", "_cat/health?h=cluster&format=json", None, ElasticServer("somehost", None)) returns Future.successful(Success(200, healthResponse))
+    client.executeRequest("GET", "_cat/nodes?format=json&h=name", None, ElasticServer("somehost", None)) returns Future.successful(Success(200, nodesResponse))
+    client.executeRequest("GET", "_cat/indices?format=json&h=index", None, ElasticServer("somehost", None)) returns Future.successful(Success(200, indicesResponse))
     val response = route(application, FakeRequest(POST, "/cluster_changes").withBody(Json.obj("host" -> "somehost"))).get
     ensure(response, 200, expectedResponse)
   }
-- 
GitLab