aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/init/CloudServices.scala
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-08-22 12:51:36 -0700
committerJakob Odersky <jakob@driver.xyz>2018-09-12 14:17:39 -0700
commit5ec270aa98b806f32338fa25357abdf45dd0625b (patch)
treef1423f8add00cc2f899d2f8259b9ab33ba3c914b /src/main/scala/xyz/driver/core/init/CloudServices.scala
parent3eb6a9e96bd8bf111490f390ea94a1c6d7677eff (diff)
downloaddriver-core-5ec270aa98b806f32338fa25357abdf45dd0625b.tar.gz
driver-core-5ec270aa98b806f32338fa25357abdf45dd0625b.tar.bz2
driver-core-5ec270aa98b806f32338fa25357abdf45dd0625b.zip
Trait-based initialization and other utilities
Adds the concept of a 'platform', a centralized place in which environment-specific information will be managed, and provides common initialization logic for most "standard" apps. As part of the common initialization, other parts of core have also been reworked: - HTTP-related unmarshallers and path matchers have been factored out from core.json to a new core.rest.directives package (core.json extends those unmarshallers and matchers for backwards compatibility) - CORS handling has also been moved to a dedicated utility trait - Some custom headers have been moved from raw headers to typed ones in core.rest.headers - The concept of a "reporter" has been introduced. A reporter is a context-aware combination of tracing and logging. It is intended to issue diagnostic messages that can be traced across service boundaries. Closes #192 Closes #195
Diffstat (limited to 'src/main/scala/xyz/driver/core/init/CloudServices.scala')
-rw-r--r--src/main/scala/xyz/driver/core/init/CloudServices.scala88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/core/init/CloudServices.scala b/src/main/scala/xyz/driver/core/init/CloudServices.scala
new file mode 100644
index 0000000..9f4ab5c
--- /dev/null
+++ b/src/main/scala/xyz/driver/core/init/CloudServices.scala
@@ -0,0 +1,88 @@
+package xyz.driver.core
+package init
+
+import java.nio.file.Paths
+
+import xyz.driver.core.discovery.CanDiscoverService
+import xyz.driver.core.messaging.{GoogleBus, QueueBus, StreamBus}
+import xyz.driver.core.reporting._
+import xyz.driver.core.reporting.ScalaLoggerLike.defaultScalaLogger
+import xyz.driver.core.storage.{BlobStorage, FileSystemBlobStorage, GcsBlobStorage}
+
+import scala.concurrent.ExecutionContext
+
+/** Mixin trait that provides essential cloud utilities. */
+trait CloudServices extends AkkaBootable { self =>
+
+ /** The platform that this application is running on.
+ * @group config
+ */
+ def platform: Platform = Platform.current
+
+ /** 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)
+
+ /* 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
+ * is first accessed. This in turn leads to somewhat convoluted code,
+ * since we can't log when the platform being is determined.
+ * A potential fix would be to make the log format independent of the platform, and always log
+ * as JSON for example.
+ */
+ override lazy val reporter: Reporter with ScalaLoggerLike = {
+ Console.println("determining platform") // scalastyle:ignore
+ val r = platform match {
+ case p @ Platform.GoogleCloud(_, _) =>
+ new GoogleReporter(p.credentials, p.namespace, defaultScalaLogger(true))
+ case Platform.Dev =>
+ new NoTraceReporter(defaultScalaLogger(false))
+ }
+ r.info(s"application started on platform '${platform}'")(SpanContext.fresh())
+ r
+ }
+
+ /** Object storage.
+ * @group utilities
+ */
+ def storage(bucketId: String): BlobStorage =
+ platform match {
+ case Platform.GoogleCloud(keyfile, _) =>
+ GcsBlobStorage.fromKeyfile(keyfile, bucketId)
+ case Platform.Dev =>
+ new FileSystemBlobStorage(Paths.get(s".data-$bucketId"))
+ }
+
+ /** Message bus.
+ * @group utilities
+ */
+ def messageBus: StreamBus = platform match {
+ case Platform.GoogleCloud(keyfile, namespace) => GoogleBus.fromKeyfile(keyfile, namespace)
+ case Platform.Dev =>
+ new QueueBus()(self.system) with StreamBus {
+ override def executionContext: ExecutionContext = self.executionContext
+ }
+ }
+
+}