From 582971b85c1eb533ef337b7808e5bff3e1178128 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 27 May 2022 13:48:20 -0700 Subject: [PATCH 1/2] airframe-grpc: Fix syntax for Scala 3 --- .../scala/wvlet/airframe/http/grpc/GrpcServer.scala | 8 +++++--- .../wvlet/airframe/http/grpc/GrpcClientTest.scala | 5 ++--- .../wvlet/airframe/http/grpc/GrpcContextTest.scala | 2 +- .../wvlet/airframe/http/grpc/GrpcErrorLogTest.scala | 4 ++-- .../wvlet/airframe/http/grpc/GrpcJsonTest.scala | 2 +- .../airframe/http/grpc/GrpcRequestLoggerTest.scala | 4 ++-- .../airframe/http/grpc/GrpcServerFactoryTest.scala | 2 +- .../wvlet/airframe/http/grpc/GrpcStreamingTest.scala | 12 ++++++------ .../scala/wvlet/airframe/http/grpc/GrpcTest.scala | 2 +- .../wvlet/airframe/http/grpc/example/DemoApi.scala | 2 +- 10 files changed, 22 insertions(+), 21 deletions(-) diff --git a/airframe-http-grpc/src/main/scala/wvlet/airframe/http/grpc/GrpcServer.scala b/airframe-http-grpc/src/main/scala/wvlet/airframe/http/grpc/GrpcServer.scala index ae5f856535..4d5c0197a3 100644 --- a/airframe-http-grpc/src/main/scala/wvlet/airframe/http/grpc/GrpcServer.scala +++ b/airframe-http-grpc/src/main/scala/wvlet/airframe/http/grpc/GrpcServer.scala @@ -38,7 +38,7 @@ case class GrpcServerConfig( executorProvider: GrpcServerConfig => ExecutorService = GrpcServer.newAsyncExecutorFactory, maxThreads: Int = (Runtime.getRuntime.availableProcessors() * 2).max(2), codecFactory: MessageCodecFactory = MessageCodecFactory.defaultFactoryForMapOutput, - requestLoggerProvider: GrpcServerConfig => GrpcRequestLogger = { config: GrpcServerConfig => + requestLoggerProvider: GrpcServerConfig => GrpcRequestLogger = { (config: GrpcServerConfig) => GrpcRequestLogger .newLogger(config.name) } @@ -85,7 +85,9 @@ case class GrpcServerConfig( def withRequestLoggerProvider(provider: GrpcServerConfig => GrpcRequestLogger) = this .copy(requestLoggerProvider = provider) // Disable RPC logging - def noRequestLogging = this.copy(requestLoggerProvider = { config: GrpcServerConfig => GrpcRequestLogger.nullLogger }) + def noRequestLogging = this.copy(requestLoggerProvider = { (config: GrpcServerConfig) => + GrpcRequestLogger.nullLogger + }) /** * Create and start a new server based on this config. @@ -123,7 +125,7 @@ case class GrpcServerConfig( */ def designWithChannel: Design = { design - .bind[Channel].toProvider { server: GrpcServer => + .bind[Channel].toProvider { (server: GrpcServer) => ManagedChannelBuilder.forTarget(server.localAddress).usePlaintext().build() } .onShutdown { diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcClientTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcClientTest.scala index 166ef23098..7f0c838d34 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcClientTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcClientTest.scala @@ -23,12 +23,11 @@ import wvlet.airframe.rx.Rx import wvlet.airspec.AirSpec import wvlet.log.{LogSupport, Logger} -import scala.concurrent.Promise +import scala.concurrent.{ExecutionContext, Promise} class GrpcClientTest extends AirSpec { - // TODO Use AirSpec's defaultExecutionContext - private implicit val sc = scala.concurrent.ExecutionContext.global + private implicit val sc: ExecutionContext = defaultExecutionContext override def design: Design = DemoApiV2.design diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcContextTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcContextTest.scala index 9fc975d173..2f93af6673 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcContextTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcContextTest.scala @@ -22,7 +22,7 @@ object GrpcContextTest extends AirSpec { override protected def design: Design = DemoApi.design - test("get context") { client: DemoApiClient => + test("get context") { (client: DemoApiClient) => val ret = client.getContext info(ret) client.getContext diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcErrorLogTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcErrorLogTest.scala index cab89304f0..b43f7da8de 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcErrorLogTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcErrorLogTest.scala @@ -47,7 +47,7 @@ object GrpcErrorLogTest extends AirSpec { gRPC.server .withName("demo-api-debug") .withRouter(Router.add[DemoApiDebug]) - .withRequestLoggerProvider { config: GrpcServerConfig => + .withRequestLoggerProvider { (config: GrpcServerConfig) => GrpcRequestLogger .newLogger(config.name, inMemoryLogWriter) } @@ -64,7 +64,7 @@ object GrpcErrorLogTest extends AirSpec { inMemoryLogWriter.getLogs } - test("request logger test") { client: DemoApiClient => + test("request logger test") { (client: DemoApiClient) => test("unary method error log") { val logs = captureAll { client.hello("gRPC") diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcJsonTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcJsonTest.scala index 2c500a7fbf..7689babb94 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcJsonTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcJsonTest.scala @@ -27,7 +27,7 @@ class GrpcJsonTest extends AirSpec { protected override def design = gRPC.server.withRouter(router).designWithChannel - test("json encoding") { c: DemoApiClient => + test("json encoding") { (c: DemoApiClient) => val client = c.withEncoding(RPCEncoding.JSON) test("unary") { diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcRequestLoggerTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcRequestLoggerTest.scala index d1ca5c757b..fdc4e9634e 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcRequestLoggerTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcRequestLoggerTest.scala @@ -33,7 +33,7 @@ class GrpcRequestLoggerTest extends AirSpec { gRPC.server .withName("demo-api") .withRouter(DemoApi.router) - .withRequestLoggerProvider { config: GrpcServerConfig => + .withRequestLoggerProvider { (config: GrpcServerConfig) => GrpcRequestLogger.newLogger(config.name, inMemoryLogWriter) } .designWithChannel @@ -45,7 +45,7 @@ class GrpcRequestLoggerTest extends AirSpec { inMemoryLogWriter.getLogs } - test("request logger test") { client: DemoApiClient => + test("request logger test") { (client: DemoApiClient) => test("unary method log") { val logs = captureAll { client.hello("gRPC") diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcServerFactoryTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcServerFactoryTest.scala index e32f3544a5..8e692b74f7 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcServerFactoryTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcServerFactoryTest.scala @@ -21,7 +21,7 @@ object GrpcServerFactoryTest extends AirSpec { private val r = Router.add[Greeter] - test("Build multiple gRPC servers") { f: GrpcServerFactory => + test("Build multiple gRPC servers") { (f: GrpcServerFactory) => val s1 = f.newServer(gRPC.server.withName("grpc1").withRouter(r)) val s2 = f.newServer(gRPC.server.withName("grpc2").withRouter(r)) } diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcStreamingTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcStreamingTest.scala index c79cbd2c71..84949f3492 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcStreamingTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcStreamingTest.scala @@ -23,14 +23,14 @@ import wvlet.airspec.AirSpec */ object GrpcStreamingTest extends AirSpec { - private def router = Router.add[DemoApi] - debug(router) - - protected override def design = gRPC.server.withRouter(router).designWithChannel + private lazy val router: Router = Router.add[DemoApi] + protected override def design = { + gRPC.server.withRouter(router).designWithChannel + } // launching a gRPC server first - test("Launch a standalone gRPC server") { server: GrpcServer => - test("Test gRPC client methods") { stub: DemoApiClient => + test("Launch a standalone gRPC server") { (server: GrpcServer) => + test("Test gRPC client methods") { (stub: DemoApiClient) => val N = 10 test("unary") { diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcTest.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcTest.scala index 21d7173e44..be0f21ead2 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcTest.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/GrpcTest.scala @@ -89,7 +89,7 @@ object GrpcTest extends AirSpec { info(s"Shutting down gRPC server localhost:${port}") server.shutdownNow() } - .bind[ManagedChannel].toProvider { server: Server => + .bind[ManagedChannel].toProvider { (server: Server) => ManagedChannelBuilder.forTarget(s"localhost:${server.getPort}").usePlaintext().build() } .onShutdown { channel => diff --git a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/example/DemoApi.scala b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/example/DemoApi.scala index 3f6703549a..f6b5bef1c7 100644 --- a/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/example/DemoApi.scala +++ b/airframe-http-grpc/src/test/scala/wvlet/airframe/http/grpc/example/DemoApi.scala @@ -94,7 +94,7 @@ object DemoApi { .withRouter(router) .withName("DemoApi") .designWithChannel - .bind[DemoApiClient].toProvider { channel: Channel => new DemoApiClient(channel) } + .bind[DemoApiClient].toProvider { (channel: Channel) => new DemoApiClient(channel) } val router = Router.add[DemoApi] From 51a8d690385895f14633a3bb3535a040223d94f7 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 27 May 2022 14:15:33 -0700 Subject: [PATCH 2/2] Mark remaining tasks as TODO --- .../src/main/scala-3/wvlet/airframe/package.scala | 1 + .../wvlet/airframe/http/router/RouterBase.scala | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/airframe-di/src/main/scala-3/wvlet/airframe/package.scala b/airframe-di/src/main/scala-3/wvlet/airframe/package.scala index aa5a50c768..db00b81eca 100644 --- a/airframe-di/src/main/scala-3/wvlet/airframe/package.scala +++ b/airframe-di/src/main/scala-3/wvlet/airframe/package.scala @@ -37,6 +37,7 @@ package object airframe { def newSilentDesign: Design = newDesign.noLifeCycleLogging import scala.jdk.CollectionConverters._ + // This will not be used in Scala 3, but left for the compatibility with Scala 2 val traitFactoryCache = new ConcurrentHashMap[Surface, Session => Any].asScala def getOrElseUpdateTraitFactoryCache(s: Surface, factory: Session => Any): Session => Any = { diff --git a/airframe-http-router/src/main/scala-3/wvlet/airframe/http/router/RouterBase.scala b/airframe-http-router/src/main/scala-3/wvlet/airframe/http/router/RouterBase.scala index d3fa84de99..f98011ceeb 100644 --- a/airframe-http-router/src/main/scala-3/wvlet/airframe/http/router/RouterBase.scala +++ b/airframe-http-router/src/main/scala-3/wvlet/airframe/http/router/RouterBase.scala @@ -16,9 +16,11 @@ package wvlet.airframe.http.router import wvlet.airframe.http.Router import wvlet.airframe.http.HttpFilterType import wvlet.airframe.surface.Surface +import wvlet.airframe.Session trait RouterBase { self: Router => inline def add[Controller]: Router = { + // TODO registerTraitFactory self.addInternal(Surface.of[Controller], Surface.methodsOf[Controller]) } @@ -41,9 +43,22 @@ private[router] object RouterObjectMacros { import quotes.reflect._ if (TypeRepr.of[Controller] <:< TypeRepr.of[HttpFilterType]) { + // TODO registerTraitFactory '{ Router(filterSurface = Some(Surface.of[Controller])) } } else { + // TODO registerTraitFactory '{ Router.empty.add[Controller] } } } + +// def registerTraitFactory[T: Type](using quotes: Quotes): Expr[Unit] = { +// // TODO implement simlar thing method like AirframeMacros.shouldGenerateTrait +// // TODO instantiate an arbitrary trait https://github.com/lampepfl/dotty/issues/11685 +// val t = Type.of[T].info +// '{ wvlet.airframe.getOrElseUpdateTraitFactoryCache( +// Surface.of[T], +// { (ss: Session) => (new ${t} {}).asInstanceOf[Any] } +// ) +// } +// } }