diff options
author | Jakob Odersky <jakob@driver.xyz> | 2018-08-22 12:51:36 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@driver.xyz> | 2018-09-12 14:17:39 -0700 |
commit | 5ec270aa98b806f32338fa25357abdf45dd0625b (patch) | |
tree | f1423f8add00cc2f899d2f8259b9ab33ba3c914b /src/main/scala/xyz/driver/core/init/CloudServices.scala | |
parent | 3eb6a9e96bd8bf111490f390ea94a1c6d7677eff (diff) | |
download | driver-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.scala | 88 |
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 + } + } + +} |