Skip to content
This repository has been archived by the owner on Dec 10, 2018. It is now read-only.

Commit

Permalink
iss #8: json full view logic, some common serializers
Browse files Browse the repository at this point in the history
  • Loading branch information
maizy committed Apr 2, 2016
1 parent 77be5de commit aff07e4
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package ru.maizy.cheesecake.server
* See LICENSE.txt for details.
*/

import java.net.InetAddress
import scala.concurrent.duration._
import scala.concurrent.{ ExecutionContext, Future }
import scala.io.StdIn
Expand All @@ -22,7 +23,7 @@ import ru.maizy.cheesecake.server.resultsstorage.{ LastResultAggregate, SimpleAg
import ru.maizy.cheesecake.server.checker.{ CheckStatus, HttpCheckerActor }
import ru.maizy.cheesecake.server.jsonapi.JsonApi
import ru.maizy.cheesecake.server.service.{ AddEndpoints, Endpoint, HttpEndpoint, Service, ServiceActor }
import ru.maizy.cheesecake.server.service.SymbolicAddress
import ru.maizy.cheesecake.server.service.{ IpAddress, SymbolicAddress }
import ru.maizy.cheesecake.server.utils.ActorUtils.escapeActorName


Expand All @@ -37,8 +38,9 @@ object ServerApp extends App {
.parseString(
s"""
|akka.http.client.user-agent-header = cheesecake/${Version.literal}
|akka.http.server.server-header = cheesecake/${Version.literal} (akka-http/$${akka.version})
""".stripMargin
) withFallback loadedConfig
).resolveWith(loadedConfig) withFallback loadedConfig

implicit val system: ActorSystem = ActorSystem("cheesecake-server", config)
implicit val materializer = ActorMaterializer()
Expand Down Expand Up @@ -73,7 +75,8 @@ object ServerApp extends App {

val endpoint1 = HttpEndpoint(SymbolicAddress("localhost"), 80, "/status")
val endpoint2 = HttpEndpoint(SymbolicAddress("localhost"), 80, "/")
val endpoint3 = HttpEndpoint(SymbolicAddress("localhost"), 80, "/not_found")
val endpoint3 = HttpEndpoint(
IpAddress(InetAddress.getByAddress(Array(127, 0, 0, 1).map(_.toByte))), 80, "/not_found")
val endpoint4 = HttpEndpoint(SymbolicAddress("non.exists"), 80, "/")

val service1 = Service("nginx")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,77 @@ package ru.maizy.cheesecake.server.jsonapi
* See LICENSE.txt for details.
*/

import akka.actor.ActorSystem
import scala.concurrent.{ ExecutionContext, Future }
import scala.concurrent.duration.DurationInt
import akka.actor.{ ActorRef, ActorSystem }
import akka.pattern.ask
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ru.maizy.cheesecake.server.jsonapi.models.AppConfigs
import akka.util.Timeout
import ru.maizy.cheesecake.server.checker.CheckStatus
import ru.maizy.cheesecake.server.jsonapi.models.{ AppConfigs, FullView }
import ru.maizy.cheesecake.server.resultsstorage.{ AggregateType, AggregatedResults, AllEndpoints }
import ru.maizy.cheesecake.server.resultsstorage.{ GetAggregatedResults, GetAllEndpoints, LastResultAggregate }
import ru.maizy.cheesecake.server.resultsstorage.SimpleAggregate


class JsonApi(system: ActorSystem, host: String, port: Int) extends JsonMarshalers {
class JsonApi(system: ActorSystem, host: String, port: Int) extends JsonApiMarshallers {
implicit val ec: ExecutionContext = system.dispatcher
implicit val timeout: Timeout = 20.seconds

private var _storageRef: Option[ActorRef] = None

private val services: Route =
(path("state" / "full_view") & get) {
complete {
"full view"
path("state" / "full_view") {
get {
complete {
fullView()
}
}
}

private val configs: Route = (path("configs") & get) {
complete {
// TODO: build from app config
AppConfigs(wsStateUrl = "/ws/state")
private val configs: Route =
path("configs") {
get {
complete {
// TODO: build from app config
AppConfigs(wsStateUrl = "/ws/state")
}
}
}
}
val routes: Route = logRequestResult("cheesecake-json-api") { // TODO: how it works
configs ~ pathPrefix("services")(services)

val routes: Route = logRequestResult("cheesecake-json-api") {
// TODO: how it works
configs ~
pathPrefix("services") {
services
}
}

def storageRef: Future[ActorRef] =
if (_storageRef.isEmpty) {
val future = system.actorSelection("/user/storage").resolveOne
future.onSuccess {
case ref: ActorRef => _storageRef = Some(ref)
}
future
} else {
Future.successful(_storageRef.get)
}

def fullView(): Future[FullView] = storageRef.flatMap { storage =>
for(
endpoints <- (storage ? GetAllEndpoints).mapTo[AllEndpoints];
aggregates <- (storage ? GetAggregatedResults(
endpoints.endpointsFqns,
Seq(
SimpleAggregate(AggregateType.UptimeDuration),
SimpleAggregate(AggregateType.UptimeChecks),
LastResultAggregate(CheckStatus.Ok),
LastResultAggregate(CheckStatus.Unavailable),
LastResultAggregate(CheckStatus.UnableToCheck)
)
)).mapTo[AggregatedResults]
) yield FullView(endpoints.endpointsFqns, aggregates.toString) // FIXME: tmp
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.maizy.cheesecake.server.jsonapi

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/

import ru.maizy.cheesecake.server.jsonapi.models.{ AppConfigs, FullView }
import ru.maizy.cheesecake.server.marshalers.CommonJsonMarshallers

trait JsonApiMarshallers extends CommonJsonMarshallers {
implicit val configFormat = jsonFormat1(AppConfigs)
implicit val fullViewFormat = jsonFormat2(FullView)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ru.maizy.cheesecake.server.jsonapi.models

import ru.maizy.cheesecake.server.service.EndpointFQN

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/

// FIXME: tmp format
case class FullView(endpoints: Seq[EndpointFQN], tmpToStringRes: String = "world")
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ru.maizy.cheesecake.server.marshalers

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json.{ DefaultJsonProtocol, JsObject, JsString, JsValue, RootJsonFormat }
import spray.json.{ JsNumber, pimpAny }
import ru.maizy.cheesecake.server.service.{ Endpoint, EndpointFQN, HttpAddress, HttpEndpoint, IpAddress, Service}
import ru.maizy.cheesecake.server.service.SymbolicAddress

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/

// TODO: how to use only writer for case classes
trait CommonJsonMarshallers extends SprayJsonSupport with DefaultJsonProtocol {
implicit val serviceFormat = jsonFormat1(Service)

implicit object IpAddressFormat extends RootJsonFormat[IpAddress] {
def write(ip: IpAddress): JsValue = JsObject(
"type" -> JsString("ip"),
"ip" -> JsString(ip.hostName),
"hostname" -> JsString(ip.hostName)
)
override def read(json: JsValue): IpAddress = ???
}

implicit object SymbolicAddressFormat extends RootJsonFormat[SymbolicAddress] {
def write(ip: SymbolicAddress): JsValue = JsObject(
"type" -> JsString("symbolic"),
"hostname" -> JsString(ip.hostName)
)
override def read(json: JsValue): SymbolicAddress = ???
}

implicit object HttpAddressFormat extends RootJsonFormat[HttpAddress] {
def write(address: HttpAddress): JsValue = address match {
case ip: IpAddress => ip.toJson
case symb: SymbolicAddress => symb.toJson
case _ => JsObject("hostname" -> JsString(address.hostName))
}
override def read(json: JsValue): HttpAddress = ???
}

implicit object HttpEndpointFormat extends RootJsonFormat[HttpEndpoint] {
def write(endpoint: HttpEndpoint): JsValue = JsObject(
"type" -> JsString("http"),
"address" -> endpoint.address.toJson,
"port" -> JsNumber(endpoint.port),
"path" -> JsString(endpoint.path),
"headers" -> endpoint.headers.toJson
)
override def read(json: JsValue): HttpEndpoint = ???
}

implicit object EndpointFormat extends RootJsonFormat[Endpoint] {
def write(address: Endpoint): JsValue = address match {
case ep: HttpEndpoint => ep.toJson
case _ => JsObject(
"type" -> JsString("unknown")
)
}

override def read(json: JsValue): Endpoint = ???
}

implicit val httpEndpointFormat = jsonFormat4(HttpEndpoint)

implicit val endpointFQN = jsonFormat2(EndpointFQN)
}

0 comments on commit aff07e4

Please sign in to comment.