Skip to content

Commit 9e274d6

Browse files
committed
add serviceName field to ConsulDiscoverable typeclass
1 parent 19255ba commit 9e274d6

File tree

5 files changed

+78
-30
lines changed

5 files changed

+78
-30
lines changed

smithy4s-tests/src/test/scala-2/com/dwolla/consul/smithy4s/ConsulDiscoverableSpecPerScalaVersion.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package some_other_package
22

3+
import com.dwolla.consul.ServiceName
34
import com.dwolla.consul.smithy4s._
45
import com.dwolla.test.HelloService
56
import munit.FunSuite
@@ -10,11 +11,13 @@ trait ConsulDiscoverableSpecPerScalaVersion { self: FunSuite =>
1011
val serviceUri: Uri = UriFromService(HelloService)
1112
private val serviceHost: Host = HostFromService(HelloService)
1213
private val serviceUriAuthority: Uri.Authority = UriAuthorityFromService(HelloService)
14+
private val serviceName: ServiceName = ServiceNameFromService(HelloService)
1315

1416
test("ConsulDiscoverable typeclass macro constructs a working instance of the typeclass") {
1517
assertEquals(ConsulDiscoverable[HelloService].host, serviceHost)
1618
assertEquals(ConsulDiscoverable[HelloService].uriAuthority, serviceUriAuthority)
1719
assertEquals(ConsulDiscoverable[HelloService].uri, serviceUri)
20+
assertEquals(ConsulDiscoverable[HelloService].serviceName, serviceName)
1821
}
1922

2023
test("ConsulDiscoverable typeclass macro returns no instance when the type parameter isn't a Smithy Service") {

smithy4s-tests/src/test/scala-2/com/dwolla/consul/smithy4s/UriFromServiceSpec.scala

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
package com.dwolla.consul.smithy4s
22

3-
import com.comcast.ip4s._
3+
import cats.syntax.all._
4+
import com.dwolla.consul.ServiceName
5+
import com.dwolla.consul.smithy.Discoverable
6+
import com.dwolla.test.HelloService
47
import munit.FunSuite
58
import org.http4s.Uri
9+
import org.http4s.syntax.all._
610

711
class UriFromServiceSpec extends FunSuite {
812
test("Service URI is derived from Smithy hint at compile time") {
9-
import org.http4s.syntax.all._
10-
1113
val uri = UriFromService(com.dwolla.test.HelloService)
12-
assertEquals(uri, uri"consul://hello-world")
14+
assertEquals(uri.some, HelloService.hints.get[Discoverable].map(d => Uri(scheme = scheme"consul".some, authority = Uri.Authority(host = Uri.RegName(d.serviceName.value)).some)))
1315
}
1416

1517
test("Service Host is derived from Smithy hint at compile time") {
1618
val uri = HostFromService(com.dwolla.test.HelloService)
17-
assertEquals(uri, Uri.Host.fromIp4sHost(host"hello-world"))
19+
assertEquals(uri.some, HelloService.hints.get[Discoverable].map(d => Uri.RegName(d.serviceName.value)))
1820
}
1921

2022
test("Service URI.Authority is derived from Smithy hint at compile time") {
2123
val uri = UriAuthorityFromService(com.dwolla.test.HelloService)
22-
assertEquals(uri, Uri.Authority(host = Uri.Host.fromIp4sHost(host"hello-world")))
24+
assertEquals(uri.some, HelloService.hints.get[Discoverable].map(d => Uri.Authority(host = Uri.RegName(d.serviceName.value))))
25+
}
26+
27+
test("ServiceName is derived from Smithy hint at compile time") {
28+
val serviceName = ServiceNameFromService(com.dwolla.test.HelloService)
29+
assertEquals(serviceName.some, HelloService.hints.get[Discoverable].map(d => ServiceName(d.serviceName.value)))
2330
}
2431

2532
test("unannotated Smithy services are rejected at compile time") {

smithy4s/src/main/scala-2/com/dwolla/consul/smithy4s/ConsulDiscoverablePlatform.scala

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.dwolla.consul.smithy4s
22

33
import cats.syntax.all._
4-
import com.dwolla.consul.smithy._
5-
import org.http4s.Uri.{Host, Scheme}
4+
import com.dwolla.consul.ServiceName
5+
import com.dwolla.consul.smithy
6+
import com.dwolla.consul.smithy.{ServiceName => _, _}
7+
import org.http4s.Uri
68
import org.typelevel.scalaccompat.annotation.nowarn212
79
import smithy4s.Hints
810

@@ -15,18 +17,16 @@ trait ConsulDiscoverablePlatform {
1517
}
1618

1719
object ConsulDiscoverableMacros {
18-
@nowarn212("msg=local val (liftableScheme|liftableHost) in method makeInstance is never used")
20+
@nowarn212("msg=local val (liftableServiceName|liftableHost) in method makeInstance is never used")
1921
def makeInstance[Alg[_[_]]](c: whitebox.Context): c.Expr[ConsulDiscoverable[Alg]] = {
2022
import c.universe.{Try => _, _}
2123

22-
implicit val liftableScheme: Liftable[Scheme] = Liftable { scheme: Scheme =>
23-
q"""_root_.org.http4s.Uri.Scheme.unsafeFromString(${scheme.value})"""
24-
}
25-
implicit val liftableHost: Liftable[Host] = Liftable { host: Host =>
24+
implicit val liftableHost: Liftable[Uri.Host] = Liftable { host: Uri.Host =>
2625
q"""_root_.org.http4s.Uri.Host.unsafeFromString(${host.value})"""
2726
}
28-
29-
val consulScheme = DiscoveryMacros.consulScheme.some
27+
implicit val liftableServiceName: Liftable[ServiceName] = Liftable { serviceName: ServiceName =>
28+
q"""_root_.com.dwolla.consul.ServiceName(${serviceName.value})"""
29+
}
3030

3131
def findHintsInTree(tpe: Tree): Either[String, Hints] =
3232
Try {
@@ -45,28 +45,25 @@ object ConsulDiscoverableMacros {
4545
_.get(Discoverable.tagInstance)
4646
.toRight(s"could not find Discoverable hint for $tpe")
4747

48-
val getHostFromDiscoverable: PartialFunction[Discoverable, Either[String, Host]] = {
49-
case Discoverable(ServiceName(serviceName)) =>
50-
Host.fromString(serviceName)
48+
val getHostFromDiscoverable: PartialFunction[Discoverable, Either[String, (ServiceName, Uri.Host)]] = {
49+
case Discoverable(smithy.ServiceName(serviceName)) =>
50+
Uri.Host.fromString(serviceName)
5151
.leftMap(_.message)
52+
.tupleLeft(ServiceName(serviceName))
5253
}
5354

54-
def hostToConsulDiscoverableExpr(tpe: Tree): Host => c.Expr[ConsulDiscoverable[Alg]] = host =>
55+
def hostToConsulDiscoverableExpr(tpe: Tree): (ServiceName, Uri.Host) => c.Expr[ConsulDiscoverable[Alg]] = (serviceName, host) =>
5556
c.Expr[ConsulDiscoverable[Alg]](
5657
q"""
57-
new _root_.com.dwolla.consul.smithy4s.ConsulDiscoverable[$tpe] {
58-
override def host: _root_.org.http4s.Uri.Host = $host
59-
override def uriAuthority: _root_.org.http4s.Uri.Authority = _root_.org.http4s.Uri.Authority(host = host)
60-
override def uri: _root_.org.http4s.Uri = _root_.org.http4s.Uri(scheme = $consulScheme, authority = _root_.scala.Option(uriAuthority))
61-
}
58+
_root_.com.dwolla.consul.smithy4s.ConsulDiscoverable.make[$tpe]($serviceName, $host)
6259
""")
6360

6461
c.macroApplication match {
6562
case TypeApply(_, List(tpe)) if tpe.symbol.companion != NoSymbol =>
6663
val maybeExpr = findHintsInTree(tpe)
6764
.flatMap(getDiscoverableFromHints(tpe))
6865
.flatMap(getHostFromDiscoverable)
69-
.map(hostToConsulDiscoverableExpr(tpe))
66+
.map(hostToConsulDiscoverableExpr(tpe).tupled)
7067

7168
maybeExpr.fold(c.abort(c.enclosingPosition, _), identity)
7269
case TypeApply(_, List(tpe)) if tpe.symbol.companion == NoSymbol =>

smithy4s/src/main/scala-2/com/dwolla/consul/smithy4s/UriFromService.scala

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.dwolla.consul.smithy4s
22

3-
import com.dwolla.consul.smithy.{Discoverable, ServiceName}
3+
import com.dwolla.consul.smithy.Discoverable
4+
import com.dwolla.consul.smithy
45
import org.http4s.Uri
56
import smithy4s.{Hints, Service}
67
import cats.syntax.all._
8+
import com.dwolla.consul.ServiceName
79
import org.http4s.Uri.{Host, Scheme}
810
import org.http4s.syntax.all._
11+
import org.typelevel.scalaccompat.annotation.nowarn212
912

1013
import scala.reflect.macros.blackbox
1114

@@ -36,7 +39,7 @@ object DiscoveryMacros {
3639
.get(Discoverable.tagInstance)
3740
.toRight(s"could not find Discoverable hint for ${cleanService.symbol.fullName}")
3841
.flatMap {
39-
case Discoverable(ServiceName(serviceName)) =>
42+
case Discoverable(smithy.ServiceName(serviceName)) =>
4043
Host.fromString(serviceName)
4144
.leftMap(_.message)
4245
}
@@ -45,6 +48,29 @@ object DiscoveryMacros {
4548
}
4649
.fold(c.abort(c.enclosingPosition, _), identity)
4750
}
51+
52+
@nowarn212("msg=local val liftableServiceName in method makeServiceName is never used")
53+
def makeServiceName[Alg[_[_, _, _, _, _]]](c: blackbox.Context)
54+
(service: c.Expr[smithy4s.Service[Alg]]): c.Expr[ServiceName] = {
55+
import c.universe.{Try => _, _}
56+
57+
implicit val liftableServiceName: Liftable[ServiceName] = Liftable { serviceName: ServiceName =>
58+
q"""_root_.com.dwolla.consul.ServiceName(${serviceName.value})"""
59+
}
60+
61+
val cleanService = c.untypecheck(service.tree.duplicate)
62+
63+
c.eval(c.Expr[Hints](q"$cleanService.hints"))
64+
.get(Discoverable.tagInstance)
65+
.toRight(s"could not find Discoverable hint for ${cleanService.symbol.fullName}")
66+
.map {
67+
case Discoverable(serviceName) => ServiceName(serviceName.value)
68+
}
69+
.map { serviceName =>
70+
c.Expr[ServiceName](q"$serviceName")
71+
}
72+
.fold(c.abort(c.enclosingPosition, _), identity)
73+
}
4874
}
4975

5076
object UriAuthorityFromService {
@@ -61,3 +87,8 @@ object UriFromService {
6187
def apply[Alg[_[_, _, _, _, _]]](service: Service[Alg]): Uri =
6288
macro DiscoveryMacros.makeUri[Alg]
6389
}
90+
91+
object ServiceNameFromService {
92+
def apply[Alg[_[_, _, _, _, _]]](service: Service[Alg]): ServiceName =
93+
macro DiscoveryMacros.makeServiceName[Alg]
94+
}
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
package com.dwolla.consul.smithy4s
22

3+
import cats.syntax.all._
4+
import com.dwolla.consul.ServiceName
35
import org.http4s.Uri
4-
import org.http4s.Uri.Host
6+
import org.http4s.syntax.all._
57

68
import scala.annotation.implicitNotFound
79

810
@implicitNotFound("Instances are only available for Smithy4s Services annotated with @discoverable")
9-
trait ConsulDiscoverable[Alg[_[_]]] {
10-
def host: Host
11+
sealed trait ConsulDiscoverable[Alg[_[_]]] {
12+
def host: Uri.Host
1113
def uriAuthority: Uri.Authority
1214
def uri: Uri
15+
def serviceName: ServiceName = ServiceName(host.value) // default implementation for MiMa compatibility, but it's never used in practice
1316
}
1417

1518
object ConsulDiscoverable extends ConsulDiscoverablePlatform {
1619
def apply[Alg[_[_]] : ConsulDiscoverable]: ConsulDiscoverable[Alg] = implicitly
20+
21+
def make[Alg[_[_]]](name: ServiceName, dest: Uri.Host): ConsulDiscoverable[Alg] = new ConsulDiscoverable[Alg] {
22+
override def host: Uri.Host = dest
23+
override def uriAuthority: Uri.Authority = Uri.Authority(host = host)
24+
override def uri: Uri = Uri(scheme = scheme"consul".some, authority = uriAuthority.some)
25+
override def serviceName: ServiceName = name
26+
}
1727
}

0 commit comments

Comments
 (0)