aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-09-03 23:40:35 -0700
committerJakob Odersky <jakob@driver.xyz>2018-09-12 14:17:39 -0700
commit9c36ff4f9e43857e2f73ebadad9942d85017e5c0 (patch)
tree2dffe5ec8ce2c17a63db528827db671447ce8feb
parentadb943605e6e41d10d7b6984b515a13b7ad84de7 (diff)
downloaddriver-core-9c36ff4f9e43857e2f73ebadad9942d85017e5c0.tar.gz
driver-core-9c36ff4f9e43857e2f73ebadad9942d85017e5c0.tar.bz2
driver-core-9c36ff4f9e43857e2f73ebadad9942d85017e5c0.zip
Move platform back into init and use a configurable DNS discovery
-rw-r--r--src/main/resources/reference.conf5
-rw-r--r--src/main/scala/xyz/driver/core/discovery/CanDiscoverService.scala11
-rw-r--r--src/main/scala/xyz/driver/core/init/CloudServices.scala47
-rw-r--r--src/main/scala/xyz/driver/core/init/Platform.scala (renamed from src/main/scala/xyz/driver/core/Platform.scala)14
-rw-r--r--src/main/scala/xyz/driver/core/messaging/ReportingBus.scala34
-rw-r--r--src/main/scala/xyz/driver/core/rest/DnsDiscovery.scala11
-rw-r--r--src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala4
-rw-r--r--src/main/scala/xyz/driver/core/rest/ServiceDescriptor.scala16
8 files changed, 98 insertions, 44 deletions
diff --git a/src/main/resources/reference.conf b/src/main/resources/reference.conf
index 608262a..01dba3c 100644
--- a/src/main/resources/reference.conf
+++ b/src/main/resources/reference.conf
@@ -19,6 +19,11 @@ application {
]
}
+services.dev-overrides = [
+ // {"service1": "http://localhost:8080"},
+ // {"service2": "https://stable.sand.driver.network"}
+]
+
# Settings about the auto-generated REST API documentation.
swagger {
diff --git a/src/main/scala/xyz/driver/core/discovery/CanDiscoverService.scala b/src/main/scala/xyz/driver/core/discovery/CanDiscoverService.scala
deleted file mode 100644
index 8711332..0000000
--- a/src/main/scala/xyz/driver/core/discovery/CanDiscoverService.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package xyz.driver.core
-package discovery
-
-import scala.annotation.implicitNotFound
-
-@implicitNotFound(
- "Don't know how to communicate with service ${Service}. Make sure an implicit CanDiscoverService is" +
- "available. A good place to put one is in the service's companion object.")
-trait CanDiscoverService[Service] {
- def discover(platform: Platform): Service
-}
diff --git a/src/main/scala/xyz/driver/core/init/CloudServices.scala b/src/main/scala/xyz/driver/core/init/CloudServices.scala
index 9f4ab5c..c492add 100644
--- a/src/main/scala/xyz/driver/core/init/CloudServices.scala
+++ b/src/main/scala/xyz/driver/core/init/CloudServices.scala
@@ -3,12 +3,14 @@ package init
import java.nio.file.Paths
-import xyz.driver.core.discovery.CanDiscoverService
+import com.typesafe.config.ConfigValueType
import xyz.driver.core.messaging.{GoogleBus, QueueBus, StreamBus}
import xyz.driver.core.reporting._
import xyz.driver.core.reporting.ScalaLoggerLike.defaultScalaLogger
+import xyz.driver.core.rest.{DnsDiscovery, ServiceDescriptor}
import xyz.driver.core.storage.{BlobStorage, FileSystemBlobStorage, GcsBlobStorage}
+import scala.collection.JavaConverters._
import scala.concurrent.ExecutionContext
/** Mixin trait that provides essential cloud utilities. */
@@ -21,28 +23,29 @@ trait CloudServices extends AkkaBootable { self =>
/** Service discovery for the current platform.
*
- * Define a service trait and companion object:
- * {{{
- * trait MyService {
- * def call(): Int
- * }
- * object MyService {
- * implicit val isDiscoverable = new xyz.driver.core.discovery.CanDiscoverService[MyService] {
- * def discover(p: xyz.driver.core.Platform): MyService = new MyService {
- * def call() = 42
- * }
- * }
- * }
- * }}}
- *
- * Then discover and use it:
- * {{{
- * discover[MyService].call()
- * }}}
- *
- * @group utilities
*/
- def discover[A](implicit cds: CanDiscoverService[A]): A = cds.discover(platform)
+ private lazy val discovery = {
+ def getOverrides(): Map[String, String] =
+ (for {
+ obj <- config.getObjectList("services.dev-overrides").asScala
+ entry <- obj.entrySet().asScala
+ } yield {
+ val tpe = entry.getValue.valueType()
+ require(
+ tpe == ConfigValueType.STRING,
+ s"URL override for '${entry.getKey}' must be a " +
+ s"string. Found '${entry.getValue.unwrapped}', which is of type $tpe.")
+ entry.getKey -> entry.getValue.unwrapped.toString
+ }).toMap
+
+ val overrides = platform match {
+ case Platform.Dev => getOverrides()
+ case _ => Map.empty[String, String] // TODO we may want to provide a way to override deployed services as well
+ }
+ new DnsDiscovery(clientTransport, overrides)
+ }
+
+ def discover[A: ServiceDescriptor]: A = discovery.discover[A]
/* TODO: this reporter uses the platform to determine if JSON logging should be enabled.
* Since the default logger uses slf4j, its settings must be specified before a logger
diff --git a/src/main/scala/xyz/driver/core/Platform.scala b/src/main/scala/xyz/driver/core/init/Platform.scala
index aa7e711..2daa2c8 100644
--- a/src/main/scala/xyz/driver/core/Platform.scala
+++ b/src/main/scala/xyz/driver/core/init/Platform.scala
@@ -1,24 +1,20 @@
package xyz.driver.core
+package init
+
import java.nio.file.{Files, Path, Paths}
import com.google.auth.oauth2.ServiceAccountCredentials
-sealed trait Platform {
- def isKubernetes: Boolean
-}
-
+sealed trait Platform
object Platform {
case class GoogleCloud(keyfile: Path, namespace: String) extends Platform {
def credentials: ServiceAccountCredentials = ServiceAccountCredentials.fromStream(
Files.newInputStream(keyfile)
)
- def project: String = credentials.getProjectId
- override def isKubernetes = true
+ def project: String = credentials.getProjectId
}
// case object AliCloud extends Platform
- case object Dev extends Platform {
- override def isKubernetes: Boolean = false
- }
+ case object Dev extends Platform
lazy val fromEnv: Platform = {
def isGoogle = sys.env.get("GOOGLE_APPLICATION_CREDENTIALS").map { value =>
diff --git a/src/main/scala/xyz/driver/core/messaging/ReportingBus.scala b/src/main/scala/xyz/driver/core/messaging/ReportingBus.scala
new file mode 100644
index 0000000..74038e4
--- /dev/null
+++ b/src/main/scala/xyz/driver/core/messaging/ReportingBus.scala
@@ -0,0 +1,34 @@
+package xyz.driver.core.messaging
+
+import xyz.driver.core.reporting.{Reporter, SpanContext}
+
+import scala.concurrent.Future
+import scala.language.higherKinds
+
+trait ReportingBus extends Bus {
+
+ def reporter: Reporter
+
+ trait TracedMessage[A] extends BasicMessage[A] { self: Message[A] =>
+ def spanContext: SpanContext
+ }
+
+ type Message[A] <: TracedMessage[A]
+
+ abstract override def publishMessages[A](topic: Topic[A], messages: Seq[A]): Future[Unit] = {
+ super.publishMessages(topic, messages)
+ }
+
+ abstract override def fetchMessages[A](
+ topic: Topic[A],
+ config: SubscriptionConfig,
+ maxMessages: Int): Future[Seq[Message[A]]] = {
+ super.fetchMessages(topic, config, maxMessages)
+ }
+
+}
+
+trait Topic2
+trait Bus2 {
+ def publishMessage[A](topic: Topic2, message: A)
+}
diff --git a/src/main/scala/xyz/driver/core/rest/DnsDiscovery.scala b/src/main/scala/xyz/driver/core/rest/DnsDiscovery.scala
new file mode 100644
index 0000000..38880d4
--- /dev/null
+++ b/src/main/scala/xyz/driver/core/rest/DnsDiscovery.scala
@@ -0,0 +1,11 @@
+package xyz.driver.core
+package rest
+
+class DnsDiscovery(transport: HttpRestServiceTransport, overrides: Map[String, String]) {
+
+ def discover[A](implicit descriptor: ServiceDescriptor[A]): A = {
+ val url = overrides.getOrElse(descriptor.name, s"https://{descriptor.name}")
+ descriptor.connect(transport, url)
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala b/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
index e60998f..e31635b 100644
--- a/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
+++ b/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
@@ -17,8 +17,8 @@ import scala.util.{Failure, Success}
class HttpRestServiceTransport(
applicationName: Name[App],
applicationVersion: String,
- actorSystem: ActorSystem,
- executionContext: ExecutionContext,
+ val actorSystem: ActorSystem,
+ val executionContext: ExecutionContext,
reporter: Reporter)
extends ServiceTransport {
diff --git a/src/main/scala/xyz/driver/core/rest/ServiceDescriptor.scala b/src/main/scala/xyz/driver/core/rest/ServiceDescriptor.scala
new file mode 100644
index 0000000..646fae8
--- /dev/null
+++ b/src/main/scala/xyz/driver/core/rest/ServiceDescriptor.scala
@@ -0,0 +1,16 @@
+package xyz.driver.core
+package rest
+import scala.annotation.implicitNotFound
+
+@implicitNotFound(
+ "Don't know how to communicate with service ${S}. Make sure an implicit ServiceDescriptor is" +
+ "available. A good place to put one is in the service's companion object.")
+trait ServiceDescriptor[S] {
+
+ /** The service's name. Must be unique among all services. */
+ def name: String
+
+ /** Get an instance of the service. */
+ def connect(transport: HttpRestServiceTransport, url: String): S
+
+}