diff --git a/.circleci/config.yml b/.circleci/config.yml index ef16449..8c084d0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,9 +3,9 @@ jobs: build: working_directory: ~/arkadius/reliable-http-client docker: - - image: openjdk:8 + - image: openjdk:11 environment: - SBT_VERSION: 1.5.1 + SBT_VERSION: 1.10.7 DOCKER_VERSION: 18.06.3-ce TESTCONTAINERS_RYUK_DISABLED: "true" steps: diff --git a/README.md b/README.md index 70ea486..fb71364 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ libraryDependencies += "org.rhttpc" %% "rhttpc-json4s" % "0.9.0" Then: ```scala -import akka.actor._ +import org.apache.pekko.actor._ import rhttpc.transport.amqp._ import rhttpc.transport.json4s._ import rhttpc.transport.json4s.CommonFormats._ @@ -61,7 +61,7 @@ libraryDependencies += "org.rhttpc" %% "rhttpc-client" % "0.9.0" ### In-only scenario ```scala -import akka.actor._ +import org.apache.pekko.actor._ import rhttpc.transport.amqp._ import rhttpc.transport.json4s._ import rhttpc.transport.json4s.CommonFormats._ @@ -78,7 +78,7 @@ AmqpConnectionFactory.connect(actorSystem).map { implicit connection => ### In-out with stateless consumer ```scala -import akka.actor._ +import org.apache.pekko.actor._ import rhttpc.transport.amqp._ import rhttpc.transport.json4s._ import rhttpc.transport.json4s.CommonFormats._ diff --git a/build.sbt b/build.sbt index 6ccde30..5a88cca 100644 --- a/build.sbt +++ b/build.sbt @@ -2,8 +2,8 @@ import com.typesafe.sbt.packager.docker.DockerPlugin.autoImport._ import sbt.Keys._ import ReleaseTransformations._ -val defaultScalaVersion = "2.13.6" -val scalaVersions = Seq("2.12.13", defaultScalaVersion) +val defaultScalaVersion = "3.3.5" +val scalaVersions = Seq("2.13.16", defaultScalaVersion) val commonSettings = Seq( @@ -37,15 +37,11 @@ val commonSettings = headerEmptyLine := false, homepage := Some(url("https://github.com/arkadius/reliable-http-client")), dockerRepository := Some("arkadius"), - dockerBaseImage := "openjdk:8", + dockerBaseImage := "openjdk:11", resolvers ++= Seq( "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository", Resolver.jcenterRepo ), - ThisBuild / libraryDependencies ++= Seq( - compilerPlugin("com.github.ghik" % "silencer-plugin" % "1.7.5" cross CrossVersion.full), - "com.github.ghik" % "silencer-lib" % "1.7.5" % Provided cross CrossVersion.full - ) ) val publishSettings = Seq( @@ -74,25 +70,22 @@ val publishSettings = Seq( } ) -val akkaV = "2.6.18" -val akkaHttpV = "10.2.6" +val pekkoV = "1.1.3" +val pekkoHttpV = "1.1.0" val amqpcV = "3.6.6" -val argonaut62MinorV = ".3" -val betterFilesV = "3.9.1" -val commonsIoV = "2.5" -val dispatchV = "1.2.0" -val ficusV = "1.4.7" +val betterFilesV = "3.9.2" +val commonsIoV = "2.18.0" +val dispatchV = "2.0.0" +val ficusV = "1.5.2" val flywayV = "6.2.4" -val hsqldbV = "2.3.6" -val json4sV = "3.6.11" +val hsqldbV = "2.7.4" val jaxbV = "2.3.1" -val logbackV = "1.1.11" -val scalaCompatV = "2.4.4" -val scalaTestV = "3.2.9" -val slf4jV = "1.7.26" -val slickV = "3.3.2" +val logbackV = "1.5.16" +val scalaTestV = "3.2.19" +val slf4jV = "1.7.36" +val slickV = "3.5.2" val scalaStmV = "0.11.1" -val testContainersV = "0.39.5" +val testContainersV = "0.41.8" lazy val transport = (project in file("rhttpc-transport")). settings(commonSettings). @@ -101,7 +94,7 @@ lazy val transport = (project in file("rhttpc-transport")). name := "rhttpc-transport", libraryDependencies ++= { Seq( - "com.typesafe.akka" %% "akka-actor" % akkaV, + "org.apache.pekko" %% "pekko-actor" % pekkoV, "org.slf4j" % "slf4j-api" % slf4jV, "org.scala-stm" %% "scala-stm" % scalaStmV, "org.scalatest" %% "scalatest" % scalaTestV % "test" @@ -116,9 +109,9 @@ lazy val inMemTransport = (project in file("rhttpc-inmem")). name := "rhttpc-inmem", libraryDependencies ++= { Seq( - "com.typesafe.akka" %% "akka-testkit" % akkaV % "test", + "org.apache.pekko" %% "pekko-testkit" % pekkoV % "test", "org.scalatest" %% "scalatest" % scalaTestV % "test", - "com.typesafe.akka" %% "akka-slf4j" % akkaV % "test", + "org.apache.pekko" %% "pekko-slf4j" % pekkoV % "test", "ch.qos.logback" % "logback-classic" % logbackV % "test" ) } @@ -132,18 +125,16 @@ lazy val amqpTransport = (project in file("rhttpc-amqp")). name := "rhttpc-amqp", libraryDependencies ++= { Seq( - "com.typesafe.akka" %% "akka-stream" % akkaV, + "org.apache.pekko" %% "pekko-stream" % pekkoV, "com.rabbitmq" % "amqp-client" % amqpcV, "com.iheart" %% "ficus" % ficusV, - "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, - "org.scala-lang" % "scala-reflect" % scalaVersion.value, - "com.typesafe.akka" %% "akka-testkit" % akkaV % "test", + "org.apache.pekko" %% "pekko-testkit" % pekkoV % "test", "org.scalatest" %% "scalatest" % scalaTestV % "test", "org.dispatchhttp" %% "dispatch-core" % dispatchV % "test", - "com.typesafe.akka" %% "akka-slf4j" % akkaV % "test", + "org.apache.pekko" %% "pekko-slf4j" % pekkoV % "test", "ch.qos.logback" % "logback-classic" % logbackV % "test", - "com.typesafe.akka" %% "akka-http" % akkaHttpV % "test" + "org.apache.pekko" %% "pekko-http" % pekkoHttpV % "test" ) } ). @@ -167,34 +158,6 @@ lazy val amqpJdbcTransport = (project in file("rhttpc-amqp-jdbc")). ). dependsOn(amqpTransport) -lazy val json4sSerialization = (project in file("rhttpc-json4s")). - settings(commonSettings). - settings(publishSettings). - settings( - name := "rhttpc-json4s", - libraryDependencies ++= { - Seq( - "org.json4s" %% "json4s-native" % json4sV, - "org.scala-lang" % "scala-reflect" % scalaVersion.value, - "org.scalatest" %% "scalatest" % scalaTestV % "test" - ) - } - ). - dependsOn(transport) - -lazy val argonaut62Serialization = (project in file("rhttpc-argonaut_6.2")). - settings(commonSettings). - settings(publishSettings). - settings( - name := "rhttpc-argonaut_6.2", - libraryDependencies ++= { - Seq( - "io.argonaut" %% "argonaut" % s"6.2$argonaut62MinorV" - ) - } - ). - dependsOn(transport) - lazy val client = (project in file("rhttpc-client")). settings(commonSettings). settings(publishSettings). @@ -203,9 +166,9 @@ lazy val client = (project in file("rhttpc-client")). libraryDependencies ++= { Seq( "com.iheart" %% "ficus" % ficusV, - "com.typesafe.akka" %% "akka-testkit" % akkaV % "test", + "org.apache.pekko" %% "pekko-testkit" % pekkoV % "test", "org.scalatest" %% "scalatest" % scalaTestV % "test", - "com.typesafe.akka" %% "akka-slf4j" % akkaV % "test", + "org.apache.pekko" %% "pekko-slf4j" % pekkoV % "test", "ch.qos.logback" % "logback-classic" % logbackV % "test" ) } @@ -213,38 +176,6 @@ lazy val client = (project in file("rhttpc-client")). dependsOn(transport). dependsOn(inMemTransport % "test") -lazy val akkaHttpClient = (project in file("rhttpc-akka-http")). - settings(commonSettings). - settings(publishSettings). - settings( - name := "rhttpc-akka-http", - libraryDependencies ++= { - Seq( - "com.typesafe.akka" %% "akka-http" % akkaHttpV, - "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, - "org.scalatest" %% "scalatest" % scalaTestV % "test" - ) - } - ). - dependsOn(client). - dependsOn(amqpTransport). - dependsOn(json4sSerialization). - dependsOn(inMemTransport) - -lazy val akkaPersistence = (project in file("rhttpc-akka-persistence")). - settings(commonSettings). - settings(publishSettings). - settings( - name := "rhttpc-akka-persistence", - libraryDependencies ++= { - Seq( - "com.typesafe.akka" %% "akka-persistence" % akkaV - ) - } - ). - dependsOn(client % "compile->compile;test->test"). - dependsOn(json4sSerialization) - lazy val sampleEcho = (project in file("sample/sample-echo")). settings(commonSettings). enablePlugins(DockerPlugin). @@ -252,9 +183,9 @@ lazy val sampleEcho = (project in file("sample/sample-echo")). settings( libraryDependencies ++= { Seq( - "com.typesafe.akka" %% "akka-http" % akkaHttpV, - "com.typesafe.akka" %% "akka-slf4j" % akkaV, - "com.typesafe.akka" %% "akka-stream" % akkaV, + "org.apache.pekko" %% "pekko-http" % pekkoHttpV, + "org.apache.pekko" %% "pekko-slf4j" % pekkoV, + "org.apache.pekko" %% "pekko-stream" % pekkoV, "ch.qos.logback" % "logback-classic" % logbackV, "org.scalatest" %% "scalatest" % scalaTestV % "test" ) @@ -264,31 +195,6 @@ lazy val sampleEcho = (project in file("sample/sample-echo")). ) .dependsOn(transport) -lazy val sampleApp = (project in file("sample/sample-app")). - settings(commonSettings). - settings(Seq( - bashScriptExtraDefines += s"""addJava "-Dlogback.configurationFile=/etc/${name.value}/logback.xml"""" - )). - enablePlugins(DockerPlugin). - enablePlugins(JavaAppPackaging). - settings( - libraryDependencies ++= { - Seq( - "com.typesafe.akka" %% "akka-http" % akkaHttpV, - "org.iq80.leveldb" % "leveldb" % "0.12", - "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.8", - "com.typesafe.akka" %% "akka-slf4j" % akkaV, - "ch.qos.logback" % "logback-classic" % logbackV, - "com.typesafe.akka" %% "akka-testkit" % akkaV % "test", - "org.scalatest" %% "scalatest" % scalaTestV % "test" - ) - }, - dockerExposedPorts := Seq(8081), - publish / skip := true - ). - dependsOn(akkaHttpClient). - dependsOn(akkaPersistence) - lazy val testProj = (project in file("sample/test")). settings(commonSettings). settings( @@ -306,7 +212,6 @@ lazy val testProj = (project in file("sample/test")). }, Test / Keys.test := (Test / Keys.test).dependsOn( sampleEcho / Docker / publishLocal, - sampleApp / Docker / publishLocal ).value, publish / skip := true ) @@ -314,10 +219,8 @@ lazy val testProj = (project in file("sample/test")). lazy val root = (project in file(".")) .aggregate( transport, inMemTransport, amqpTransport, amqpJdbcTransport, - json4sSerialization, argonaut62Serialization, - client, akkaHttpClient, - akkaPersistence, - sampleEcho, sampleApp, testProj) + client, + sampleEcho, testProj) .settings(commonSettings) .settings(publishSettings) .settings( diff --git a/project/build.properties b/project/build.properties index f0be67b..73df629 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.1 +sbt.version=1.10.7 diff --git a/rhttpc-akka-http/src/main/resources/reference.conf b/rhttpc-akka-http/src/main/resources/reference.conf deleted file mode 100644 index 25b2534..0000000 --- a/rhttpc-akka-http/src/main/resources/reference.conf +++ /dev/null @@ -1,17 +0,0 @@ -akka { - stream { - materializer { - subscription-timeout { - timeout=2m - } - } - } - - http { - host-connection-pool { - max-connections = ${rhttpc.batchSize} - max-retries = 0 - idle-timeout = infinite - } - } -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/ReliableHttpClientFactory.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/ReliableHttpClientFactory.scala deleted file mode 100644 index 6f13425..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/ReliableHttpClientFactory.scala +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp - -import akka.actor.ActorSystem -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} -import akka.stream.Materializer -import com.rabbitmq.client.Connection -import rhttpc.akkahttp.proxy.{AcceptSuccessHttpStatus, ReliableHttpProxyFactory, SuccessHttpResponseRecognizer} -import rhttpc.client._ -import rhttpc.client.config.ConfigParser -import rhttpc.client.protocol.Exchange -import rhttpc.client.proxy.FailureResponseHandleStrategyChooser -import rhttpc.transport._ -import rhttpc.transport.amqp.{AmqpConnectionFactory, AmqpTransport} -import rhttpc.transport.inmem.InMemTransport - -import scala.concurrent._ - -case class ReliableHttpClientFactory()(implicit actorSystem: ActorSystem, materialize: Materializer) { - import actorSystem.dispatcher - import rhttpc.transport.fallback._ - import rhttpc.transport.json4s._ - - private val inMemTransport = InMemTransport() - - private implicit def transport(implicit connection: Connection): PubSubTransport = - AmqpTransport(connection).withFallbackTo(inMemTransport) - - private lazy val config = ConfigParser.parse(actorSystem) - - def inOutWithSubscriptions(connection: Connection, - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): InOutReliableHttpClient = { - implicit val implicitConnection = connection - ReliableClientFactory().inOutWithSubscriptions( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy - ) - } - - def inOut(connection: Connection, - handleResponse: Exchange[HttpRequest, HttpResponse] => Future[Unit], - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): InOnlyReliableHttpClient = { - implicit val implicitConnection = connection - ReliableClientFactory().inOut( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - handleResponse = handleResponse, - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy - ) - } - - def inOutWithRequestQueueOnly(connection: Connection, - handleResponse: Exchange[HttpRequest, HttpResponse] => Future[Unit], - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): InOnlyReliableHttpClient = { - implicit val implicitConnection = connection - ReliableClientFactory().inOutWithRequestQueueOnly( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - handleResponse = handleResponse, - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy - ) - } - - def inOnly(connection: Connection, - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): InOnlyReliableHttpClient = { - implicit val implicitConnection = connection - ReliableClientFactory().inOnly[HttpRequest]( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers)(_).map(_ => ()), - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy - ) - } - - def withOwnAmqpConnection = new { - - private final val AMQP_CLOSE_TIMEOUT_MILLIS = 5 * 1000 - - def inOutWithSubscriptions(successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): Future[InOutReliableHttpClient] = { - val connectionF = AmqpConnectionFactory.connect(actorSystem) - connectionF.map { implicit connection => - ReliableClientFactory().inOutWithSubscriptions( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy, - additionalStopAction = { - Future { - blocking { - connection.close(AMQP_CLOSE_TIMEOUT_MILLIS) - } - } - } - ) - } - } - - def inOut(handleResponse: Exchange[HttpRequest, HttpResponse] => Future[Unit], - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): Future[InOnlyReliableHttpClient] = { - val connectionF = AmqpConnectionFactory.connect(actorSystem) - connectionF.map { implicit connection => - ReliableClientFactory().inOut( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - handleResponse = handleResponse, - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy, - additionalStopAction = { - Future { - blocking { - connection.close(AMQP_CLOSE_TIMEOUT_MILLIS) - } - } - } - ) - } - } - - def inOutWithRequestQueueOnly(handleResponse: Exchange[HttpRequest, HttpResponse] => Future[Unit], - successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): Future[InOnlyReliableHttpClient] = { - val connectionF = AmqpConnectionFactory.connect(actorSystem) - connectionF.map { implicit connection => - ReliableClientFactory().inOutWithRequestQueueOnly( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers), - handleResponse = handleResponse, - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy, - additionalStopAction = { - Future { - blocking { - connection.close(AMQP_CLOSE_TIMEOUT_MILLIS) - } - } - } - ) - } - } - - def inOnly(successRecognizer: SuccessHttpResponseRecognizer = AcceptSuccessHttpStatus, - batchSize: Int = config.batchSize, - parallelConsumers: Int = config.parallelConsumers, - queuesPrefix: String = config.queuesPrefix, - retryStrategy: FailureResponseHandleStrategyChooser = config.retryStrategy): Future[InOnlyReliableHttpClient] = { - val connectionF = AmqpConnectionFactory.connect(actorSystem) - connectionF.map { implicit connection => - ReliableClientFactory().inOnly[HttpRequest]( - send = ReliableHttpProxyFactory.send(successRecognizer, batchSize, parallelConsumers)(_).map(_ => ()), - batchSize = batchSize, - parallelConsumers = parallelConsumers, - queuesPrefix = queuesPrefix, - retryStrategy = retryStrategy, - additionalStopAction = { - Future { - blocking { - connection.close(AMQP_CLOSE_TIMEOUT_MILLIS) - } - } - } - ) - } - } - - } - -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ByteStringSerializer.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ByteStringSerializer.scala deleted file mode 100644 index d50e9ea..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ByteStringSerializer.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.json4s - -import akka.util.ByteString -import org.json4s.JsonAST.JString -import rhttpc.transport.json4s.CustomSerializerWithTypeHints - -object ByteStringSerializer extends CustomSerializerWithTypeHints[ByteString, JString](formats => ( - { - case js => ByteString(js.values) - }, - { - case bs => JString(bs.utf8String) - } -)) \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ContentTypeSerializer.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ContentTypeSerializer.scala deleted file mode 100644 index 3f3f4d3..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/ContentTypeSerializer.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.json4s - -import java.text.ParseException - -import akka.http.scaladsl.model.ContentType -import org.json4s.JsonAST.JString -import rhttpc.transport.json4s.CustomSerializerWithTypeHints - -object ContentTypeSerializer extends CustomSerializerWithTypeHints[ContentType, JString](formats => ( - { - case js => ContentType.parse(js.values).getOrElse(throw new ParseException("Illegal content-type: " + js.values, -1)) - }, - { - case ct => JString(ct.toString()) - } -)) \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormats.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormats.scala deleted file mode 100644 index 90be2ab..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormats.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.json4s - -import org.json4s.Formats -import rhttpc.transport.json4s._ - -object Json4sHttpRequestResponseFormats { - - implicit val formats: Formats = - CommonFormats.formats + - ContentTypeSerializer + - ByteStringSerializer + - UriSerializer - -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/UriSerializer.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/UriSerializer.scala deleted file mode 100644 index 5e7d8dc..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/json4s/UriSerializer.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.json4s - -import akka.http.scaladsl.model.Uri -import org.json4s.JsonAST.JString -import rhttpc.transport.json4s.CustomSubTypesSerializer - -object UriSerializer extends CustomSubTypesSerializer[Uri, JString](formats => ( - { - case js => Uri(js.values) - }, - { - case uri => JString(uri.toString()) - } -)) \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/package.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/package.scala deleted file mode 100644 index d1ac7cb..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/package.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc - -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} -import org.json4s.Formats -import rhttpc.akkahttp.json4s._ -import rhttpc.client.proxy.ReliableProxy -import rhttpc.client.{InOnlyReliableClient, InOutReliableClient} -import rhttpc.transport.json4s.CommonFormats - -package object akkahttp { - type InOutReliableHttpClient = InOutReliableClient[HttpRequest] - type InOnlyReliableHttpClient = InOnlyReliableClient[HttpRequest] - type ReliableHttpProxy = ReliableProxy[HttpRequest, HttpResponse] - - implicit val formats: Formats = - CommonFormats.formats + - ContentTypeSerializer + - ByteStringSerializer + - UriSerializer - -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/ReliableHttpProxyFactory.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/ReliableHttpProxyFactory.scala deleted file mode 100644 index df3d02f..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/ReliableHttpProxyFactory.scala +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.proxy - -import akka.NotUsed -import akka.actor._ -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} -import akka.stream.Materializer -import akka.stream.scaladsl.{Flow, Sink, Source} -import org.slf4j.LoggerFactory -import rhttpc.client.protocol.{Correlated, Request} -import rhttpc.client.proxy._ - -import scala.concurrent.duration._ -import scala.concurrent.{ExecutionContext, Future} -import scala.util.control.NonFatal -import scala.util.{Failure, Success} - -object ReliableHttpProxyFactory { - - private lazy val logger = LoggerFactory.getLogger(getClass) - - def send(successRecognizer: SuccessHttpResponseRecognizer, batchSize: Int, parallelConsumers: Int) - (request: Request[HttpRequest]) - (implicit actorSystem: ActorSystem, materialize: Materializer): Future[HttpResponse] = { - import actorSystem.dispatcher - send(prepareHttpFlow(batchSize * parallelConsumers), successRecognizer)(request.correlated) - } - - private def prepareHttpFlow(parallelism: Int) - (implicit actorSystem: ActorSystem, materialize: Materializer): - Flow[(HttpRequest, String), HttpResponse, NotUsed] = { - - import actorSystem.dispatcher - Http().superPool[String]().mapAsync(parallelism) { - case (tryResponse, id) => - tryResponse match { - case Success(response) => - response.toStrict(1 minute) - case Failure(ex) => - Future.failed(ex) - } - } - } - - private def send(httpFlow: Flow[(HttpRequest, String), HttpResponse, Any], successRecognizer: SuccessHttpResponseRecognizer) - (corr: Correlated[HttpRequest]) - (implicit ec: ExecutionContext, materialize: Materializer): Future[HttpResponse] = { - import scala.collection.compat._ - import scala.jdk.CollectionConverters._ - logger.debug( - s"""Sending request for ${corr.correlationId} to ${corr.msg.getUri()}. Headers: - |${corr.msg.getHeaders().asScala.toSeq.map(h => " " + h.name() + ": " + h.value()).mkString("\n")} - |Body: - |${corr.msg.entity.asInstanceOf[HttpEntity.Strict].data.utf8String}""".stripMargin - ) - val logResp = logResponse(corr) _ - val responseFuture = Source.single((corr.msg, corr.correlationId)).via(httpFlow).runWith(Sink.head) - responseFuture.onComplete { - case Failure(ex) => - logger.error(s"Got failure for ${corr.correlationId} to ${corr.msg.getUri()}", ex) - case Success(_) => - } - for { - response <- responseFuture - transformedToFailureIfNeed <- { - if (successRecognizer.isSuccess(response)) { - logResp(response, "success response") - Future.successful(response) - } else { - logResp(response, "response recognized as non-success") - Future.failed(NonSuccessResponse) - } - } - } yield transformedToFailureIfNeed - } - - private def logResponse(corr: Correlated[HttpRequest]) - (response: HttpResponse, additionalInfo: String): Unit = { - import scala.collection.compat._ -import scala.jdk.CollectionConverters._ - logger.debug( - s"""Got $additionalInfo for ${corr.correlationId} to ${corr.msg.getUri()}. Status: ${response.status.value}. Headers: - |${response.getHeaders().asScala.toSeq.map(h => " " + h.name() + ": " + h.value()).mkString("\n")} - |Body: - |${response.entity.asInstanceOf[HttpEntity.Strict].data.utf8String}""".stripMargin - ) - } - -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/SuccessHttpResponseRecognizer.scala b/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/SuccessHttpResponseRecognizer.scala deleted file mode 100644 index 43dac2d..0000000 --- a/rhttpc-akka-http/src/main/scala/rhttpc/akkahttp/proxy/SuccessHttpResponseRecognizer.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.proxy - -import akka.http.scaladsl.model.HttpResponse - -trait SuccessHttpResponseRecognizer { - def isSuccess(response: HttpResponse): Boolean -} - -object AcceptSuccessHttpStatus extends SuccessHttpResponseRecognizer { - override def isSuccess(response: HttpResponse) = response.status.isSuccess() -} \ No newline at end of file diff --git a/rhttpc-akka-http/src/test/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormatsSpec.scala b/rhttpc-akka-http/src/test/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormatsSpec.scala deleted file mode 100644 index a8833e8..0000000 --- a/rhttpc-akka-http/src/test/scala/rhttpc/akkahttp/json4s/Json4sHttpRequestResponseFormatsSpec.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkahttp.json4s - -import java.util.UUID - -import akka.http.scaladsl.model._ -import org.json4s.native.Serialization -import org.scalatest.matchers.should.Matchers -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.prop.TableDrivenPropertyChecks -import rhttpc.client.protocol.{Correlated, Exchange, FailureExchange, SuccessExchange} -import rhttpc.client.proxy.{ExhaustedRetry, NonSuccessResponse} - -class Json4sHttpRequestResponseFormatsSpec extends AnyFlatSpec with TableDrivenPropertyChecks with Matchers { - implicit val formats = Json4sHttpRequestResponseFormats.formats - - val requestsData = Table[Correlated[HttpRequest]]( - "request", - Correlated(HttpRequest().withMethod(HttpMethods.POST).withEntity("foo"), UUID.randomUUID().toString) - ) - - // FIXME: unignore tests when json4s problem with classloaders will be fixed (test fail only from cmd, from IDE work) - ignore should "work round-trip for requests" in { - forAll(requestsData) { request => - val serialized = Serialization.writePretty(request) - println("Serialized: " + serialized) - withClue("Serialized: " + serialized) { - val deserialized = Serialization.read[Correlated[HttpRequest]](serialized) - println("Deserialized: " + deserialized) - deserialized shouldEqual request - } - } - } - - val responsesData = Table[Correlated[Exchange[HttpRequest, HttpResponse]]]( - "responses", - Correlated(SuccessExchange(HttpRequest(), HttpResponse().withEntity("bar")), UUID.randomUUID().toString), - Correlated(FailureExchange(HttpRequest(), ExhaustedRetry(NonSuccessResponse)), UUID.randomUUID().toString) - ) - - ignore should "work round-trip for responses" in { - forAll(responsesData) { response => - val serialized = Serialization.writePretty(response) - println("Serialized: " + serialized) - withClue("Serialized: " + serialized) { - val deserialized = Serialization.read[Correlated[Exchange[HttpRequest, HttpResponse]]](serialized) - println("Deserialized: " + deserialized) - deserialized shouldEqual response - } - } - } -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/resources/reference.conf b/rhttpc-akka-persistence/src/main/resources/reference.conf deleted file mode 100644 index 2c70e55..0000000 --- a/rhttpc-akka-persistence/src/main/resources/reference.conf +++ /dev/null @@ -1,11 +0,0 @@ -akka { - actor { - serializers = { - json4s = "rhttpc.akkapersistence.json4s.Json4sSerializer" - } - - serialization-bindings = { - "akka.persistence.serialization.Snapshot" = json4s - } - } -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/akka/persistence/AkkaPersistentSnapshotter.scala b/rhttpc-akka-persistence/src/main/scala/akka/persistence/AkkaPersistentSnapshotter.scala deleted file mode 100644 index a65c8ae..0000000 --- a/rhttpc-akka-persistence/src/main/scala/akka/persistence/AkkaPersistentSnapshotter.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package akka.persistence - -import akka.persistence.SnapshotProtocol.SaveSnapshot -import rhttpc.akkapersistence.impl.AbstractSnapshotter - -// this trait must be in akka.persistence package because of snapshotStore package protected access -trait AkkaPersistentSnapshotter extends AbstractSnapshotter with PersistentActor { - - override def receiveCommand: Receive = { - case _ => throw new IllegalArgumentException("Should be used receive method instead") - } - - override def saveSnapshotWithSeqNr(snapshot: Any, seqNr: Long): Unit = { - snapshotStore ! SaveSnapshot(SnapshotMetadata(snapshotterId, seqNr), snapshot) - } - -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/RecoverableActorsManager.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/RecoverableActorsManager.scala deleted file mode 100644 index 1b8675c..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/RecoverableActorsManager.scala +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence - -import akka.actor._ -import akka.pattern._ -import akka.util.Timeout -import rhttpc.akkapersistence.impl._ - -import scala.concurrent.Future -import scala.concurrent.duration._ - -private class RecoverableActorsManager(persistenceCategory: String, childPropsCreate: String => Props) extends Actor with ActorLogging { - - import context.dispatcher - - override def receive: Receive = { - case RecoverAllActors => - val registry = context.actorOf(SnapshotsRegistry.props(persistenceCategory), s"$persistenceCategory-registry") - registry ! GetIdsWithStoredSnapshots - context.become(waitForIdsWithStoredSnapshots(registry, sender())) - } - - private def waitForIdsWithStoredSnapshots(registry: ActorRef, originalSender: ActorRef): Receive = { - case IdsWithStoredSnapshots(ids) => - val recoveryFinishedFuture = - if (ids.nonEmpty) { - log.info(ids.mkString("Recovering actors from registry: ", ", ", "")) - implicit val timeout = Timeout(1 minute) - val futures = ids.map { id => - context.actorOf(childPropsCreate(id), id) ? NotifyAboutRecoveryCompleted - } - Future.sequence(futures).map { _ => - log.info("Recovering of all actors completed") - } - } else { - log.info("Empty registry - nothing to recover") - Future.unit - } - recoveryFinishedFuture.foreach { _ => - self ! BecomeRecovered - originalSender ! ActorsRecovered - registry ! PoisonPill - } - case BecomeRecovered => - context.become(recovered) - } - - val recovered: Receive = { - case SendMsgToChild(id, msg) => - context.child(id) match { - case Some(child) => child forward msg - case None => - val child = context.actorOf(childPropsCreate(id), id) - child forward msg - } - } - - case object BecomeRecovered -} - -object RecoverableActorsManager { - def props(persistenceCategory: String, childPropsCreate: String => Props): Props = - Props(new RecoverableActorsManager(persistenceCategory, childPropsCreate)) -} - -case object RecoverAllActors -case object ActorsRecovered - -case class SendMsgToChild(id: String, msg: Any) \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/ReliableFSM.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/ReliableFSM.scala deleted file mode 100644 index 7645570..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/ReliableFSM.scala +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence - -import akka.actor.FSM._ -import akka.actor._ -import akka.persistence.{AkkaPersistentSnapshotter, SnapshotOffer} -import rhttpc.akkapersistence.impl._ -import rhttpc.client.subscription.SubscriptionOnResponse - -trait ReliableFSM[S, D] extends AkkaPersistentSnapshotter with AbstractReliableFSM[S, D] - -trait AbstractReliableFSM[S, D] - extends PersistentFSM[S, D] - with SubscriptionsHolder[S, D] { self: AbstractSnapshotter => - - override def receive: Receive = - handleNotifyAboutRecoveryCompleted orElse - handleSubscriptionMessages orElse - handleSnapshotEvents orElse - super.receive -} - -trait PersistentFSM[S, D] - extends PersistentActorWithNotifications - with FSM[S, D] - with FSMAfterAllListenerHolder[S, D] - with FSMStateTransitionRegistrar[S, D] - with NotifierAboutRecoveryCompleted { self: AbstractSnapshotter with StateTransitionHandler[S, D] => - - private var ownLastSequenceNr = 0L - - override protected def incOwnLastSequenceNr(): Long = { - ownLastSequenceNr += 1 - ownLastSequenceNr - } - - override def receiveRecover: Receive = - handleSnapshotOffer orElse - handleRecoveryCompleted - - private val handleSnapshotOffer: Receive = { - case SnapshotOffer(metadata, snapshot) => - log.info(s"Recovering: $metadata from snapshot: $snapshot") - ownLastSequenceNr = metadata.sequenceNr - val casted = snapshot.asInstanceOf[FSMState[S, D]] - onSubscriptionsOffered(casted.subscriptions) - startWith(casted.state, casted.data) - } - - override protected def onFinishedJobAfterTransition(afterAllData: FinishedJobAfterTransitionData[S, D]): Unit = { - saveSnapshotNotifying(FSMState(afterAllData), afterAllData.sequenceNumber, afterAllData.afterAllListener) - } - - onTermination { - case StopEvent(Normal, _, _) => - deleteSnapshotsLogging() - case StopEvent(Failure(_), _, _) => - deleteSnapshotsLogging() - } - -} - -case class FSMState[S, D](state: S, data: D, subscriptions: Set[SubscriptionOnResponse]) - -object FSMState { - def apply[S, D](data: FinishedJobAfterTransitionData[S, D]): FSMState[S, D] = FSMState(data.state, data.data, data.subscriptions) -} - -case object StateSaved \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/AbstractSnapshotter.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/AbstractSnapshotter.scala deleted file mode 100644 index 75c3c14..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/AbstractSnapshotter.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import akka.actor.Actor -import akka.persistence.SnapshotSelectionCriteria - -trait AbstractSnapshotter extends Actor { - - def persistenceId: String - - def saveSnapshotWithSeqNr(snapshot: Any, seqNr: Long): Unit - - def deleteSnapshots(criteria: SnapshotSelectionCriteria): Unit - - def receiveRecover: Receive - -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/FSMAfterAllListenerHolder.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/FSMAfterAllListenerHolder.scala deleted file mode 100644 index f9a384b..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/FSMAfterAllListenerHolder.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import akka.actor.FSM -import rhttpc.akkapersistence.StateSaved - -private[akkapersistence] trait FSMAfterAllListenerHolder[S, D] { this: FSM[S, D] => - private var currentAfterAllListener: Option[RecipientWithMsg] = None - - implicit class StateExt(state: this.State) { - def acknowledgingAfterSave() = { - replyingAfterSave() - } - - def replyingAfterSave(msg: Any = StateSaved) = { - currentAfterAllListener = Some(new RecipientWithMsg(sender(), msg)) - state - } - } - - protected def useCurrentAfterAllListener(): Option[RecipientWithMsg] = { - val tmp = currentAfterAllListener - currentAfterAllListener = None - tmp - } -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/NotifierAboutRecoveryCompleted.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/NotifierAboutRecoveryCompleted.scala deleted file mode 100644 index 39270c9..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/NotifierAboutRecoveryCompleted.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import akka.actor._ -import akka.persistence.RecoveryCompleted - -private[akkapersistence] trait NotifierAboutRecoveryCompleted { this: AbstractSnapshotter with ActorLogging => - - private var recoveryCompleted: Boolean = false - private var waitingForRecoveryCompleted: List[ActorRef] = List.empty - - protected val handleRecoveryCompleted: Receive = { - case RecoveryCompleted => - log.info("Recovery completed for: " + persistenceId) - recoveryCompleted = true - waitingForRecoveryCompleted.foreach(_ ! RecoveryCompleted) - waitingForRecoveryCompleted = List.empty - } - - protected val handleNotifyAboutRecoveryCompleted: Receive = { - case NotifyAboutRecoveryCompleted => - if (recoveryCompleted) - sender() ! RecoveryCompleted - else - waitingForRecoveryCompleted = sender() :: waitingForRecoveryCompleted - } - -} - -case object NotifyAboutRecoveryCompleted \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/PersistentActorWithNotifications.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/PersistentActorWithNotifications.scala deleted file mode 100644 index 8f72d2c..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/PersistentActorWithNotifications.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import java.io.{PrintWriter, StringWriter} - -import akka.actor.{ActorLogging, ActorRef} -import akka.persistence._ - -private[akkapersistence] trait PersistentActorWithNotifications { this: AbstractSnapshotter with ActorLogging => - override def persistenceId: String = SnapshotsRegistry.persistenceId(persistenceCategory, id) - - protected def persistenceCategory: String - - protected def id: String - - private var listenersForSnapshotSave: Map[Long, RecipientWithMsg] = Map.empty - - protected def deleteSnapshotsLogging(): Unit = { - deleteSnapshotsLogging(None) - } - - private def deleteSnapshotsLogging(maxSequenceNr: Option[Long]): Unit = { - log.debug(s"Deleting all snapshots for $persistenceId until (inclusive): $maxSequenceNr...") - deleteSnapshots(SnapshotSelectionCriteria(maxSequenceNr = maxSequenceNr.getOrElse(Int.MaxValue))) - } - - protected def saveSnapshotNotifying(snapshot: Any, sequenceNr: Long, listener: Option[RecipientWithMsg]): Unit = { - log.debug(s"Saving snapshot for $persistenceId with sequenceNr: $sequenceNr: $snapshot ...") - listener.foreach { listener => - listenersForSnapshotSave += sequenceNr -> listener - } - saveSnapshotWithSeqNr(snapshot, sequenceNr) - } - - protected val handleSnapshotEvents: Receive = { - case SaveSnapshotSuccess(metadata) => - log.debug(s"State saved for: $metadata") - deleteSnapshotsLogging(Some(metadata.sequenceNr-1)) - replyToListenerForSaveIfWaiting(metadata) - case DeleteSnapshotsSuccess(criteria) => - log.debug(s"Snapshots with criteria: $criteria deleted") - case SaveSnapshotFailure(metadata, cause) => - log.error(cause, s"State save failure for: $metadata") - case DeleteSnapshotsFailure(criteria, cause) => - log.warning(s"Delete snapshots with criteria failure: $criteria.\nError: ${printStackTrace(cause)}") - } - - private def printStackTrace(cause: Throwable): String = { - val stringWriter = new StringWriter() - val printWriter = new PrintWriter(stringWriter) - cause.printStackTrace(printWriter) - stringWriter.toString - } - - private def replyToListenerForSaveIfWaiting(metadata: SnapshotMetadata): Unit = { - listenersForSnapshotSave.get(metadata.sequenceNr).foreach { listener => - listener.reply() - listenersForSnapshotSave -= metadata.sequenceNr - } - } -} - -class RecipientWithMsg(recipient: ActorRef, msg: Any) { - def reply() = recipient ! msg -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SnapshotsRegistry.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SnapshotsRegistry.scala deleted file mode 100644 index 84ccf21..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SnapshotsRegistry.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import java.io.File - -import akka.actor.{Actor, Props} - -private[akkapersistence] class SnapshotsRegistry(persistenceCategory: String) extends Actor { - private val FilenamePattern = s"""^snapshot-$persistenceCategory-(.+)-(\\d+)-(\\d+)""".r - - private val config = context.system.settings.config.getConfig("akka.persistence.snapshot-store.local") - private val snapshotDir = new File(config.getString("dir")) - - override def receive: Receive = { - case GetIdsWithStoredSnapshots => - val ids = Option(snapshotDir.list()).toSeq.flatten.collect { - case FilenamePattern(id, _, _) => id - }.toSet - sender() ! IdsWithStoredSnapshots(ids) - } - -} - -private[rhttpc] object SnapshotsRegistry { - def persistenceId(category: String, id: String) = s"$category-$id" - - def props(persistenceCategory: String): Props = Props(new SnapshotsRegistry(persistenceCategory)) -} - -private[rhttpc] case object GetIdsWithStoredSnapshots - -private[rhttpc] case class IdsWithStoredSnapshots(ids: Set[String]) \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/StateTransitionHandler.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/StateTransitionHandler.scala deleted file mode 100644 index 6c379ba..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/StateTransitionHandler.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import akka.actor.FSM -import rhttpc.client.subscription.SubscriptionOnResponse - -private[akkapersistence] trait StateTransitionHandler[S, D] { - protected def onSubscriptionsOffered(subscriptions: Set[SubscriptionOnResponse]): Unit - - protected def onStateTransition(transitionData: TransitionData[S, D]): Unit - - protected def onFinishedJobAfterTransition(afterAllData: FinishedJobAfterTransitionData[S, D]): Unit -} - -private[rhttpc] trait FSMStateTransitionRegistrar[S, D] { self: FSM[S, D] with StateTransitionHandler[S, D] with FSMAfterAllListenerHolder[S, D] => - - protected def incOwnLastSequenceNr(): Long - - onTransition { - case (_, to) => - onStateTransition(TransitionData[S, D](to, nextStateData, incOwnLastSequenceNr(), useCurrentAfterAllListener())) - } - -} - -private[rhttpc] case class TransitionData[S, D](state: S, data: D, sequenceNumber: Long, afterAllListener: Option[RecipientWithMsg]) { - def toFinishedJobData(subscriptions: Set[SubscriptionOnResponse]): FinishedJobAfterTransitionData[S, D] = { - FinishedJobAfterTransitionData(state, data, subscriptions, sequenceNumber, afterAllListener) - } -} - -private[rhttpc] case class FinishedJobAfterTransitionData[S, D](state: S, data: D, subscriptions: Set[SubscriptionOnResponse], sequenceNumber: Long, afterAllListener: Option[RecipientWithMsg]) \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsHolder.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsHolder.scala deleted file mode 100644 index 015e836..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsHolder.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import rhttpc.client.subscription._ -import rhttpc.client.subscription.{PublicationListener, SubscriptionOnResponse, SubscriptionManager} - -private[akkapersistence] trait SubscriptionsHolder[S, D] extends PublicationListener with StateTransitionHandler[S, D] { - - protected def subscriptionManager: SubscriptionManager - - private var subscriptionStates: SubscriptionsStateStack = SubscriptionsStateStack() - - override protected def onSubscriptionsOffered(subscriptionsOffered: Set[SubscriptionOnResponse]): Unit = { - val withRegistered = subscriptionsOffered.foldLeft(SubscriptionsStateStack())(_.withRegisteredPromise(_)) - subscriptionsOffered.foreach(subscriptionManager.confirmOrRegister(_, self)) - // _ => Unit is because for all promises, request will be published immediately and it shouldn't trigger saving of (restored) state - subscriptionStates = subscriptionsOffered.foldLeft(withRegistered.withNextState(_ => ()))(_.withPublishedRequestFor(_)) - } - - override def subscriptionPromiseRegistered(sub: SubscriptionOnResponse): Unit = { - subscriptionStates = subscriptionStates.withRegisteredPromise(sub) - } - - override protected def onStateTransition(transitionData: TransitionData[S, D]): Unit = { - subscriptionStates = subscriptionStates.withNextState { publishedRequests => - onFinishedJobAfterTransition(transitionData.toFinishedJobData(publishedRequests)) - } - } - - protected val handleSubscriptionMessages: Receive = { - case RequestPublished(subscription) => - // TODO: timeouts for missing MessageFromSubscription - subscriptionManager.confirmOrRegister(subscription, self) - subscriptionStates = subscriptionStates.withPublishedRequestFor(subscription) - case RequestAborted(subscription, cause) => - subscriptionStates = subscriptionStates.withAbortedRequestFor(subscription) - case MessageFromSubscription(msg, subscription) => - subscriptionStates = subscriptionStates.withConsumedSubscription(subscription) - self forward msg - } - -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStack.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStack.scala deleted file mode 100644 index d5658ef..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStack.scala +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import rhttpc.client.subscription.SubscriptionOnResponse - -case class SubscriptionsStateStack private (stack: List[SubscriptionsState]) { - import SubscriptionsStateStack._ - - def withNextState(onAllRequestsPublishedForPrevState: Set[SubscriptionOnResponse] => Unit) = { - val head :: tail = stack - val newTail = head.withOnAllRequestsPublished(onAllRequestsPublishedForPrevState) match { - case AllSubscriptionsConsumed => - tail - case SomeSubscriptionsLeft(updated) => - updated :: tail - } - copy(stack = SubscriptionsState() :: newTail) - } - - def withRegisteredPromise(sub: SubscriptionOnResponse): SubscriptionsStateStack = { - val head :: tail = stack - copy(stack = head.withRegisteredPromise(sub) :: tail) - } - - def withPublishedRequestFor(sub: SubscriptionOnResponse): SubscriptionsStateStack = - withCompletedSubscription(sub)(_.withPublishedRequestFor(sub)) - - def withAbortedRequestFor(sub: SubscriptionOnResponse): SubscriptionsStateStack = - withCompletedSubscription(sub)(_.withAbortedRequestFor(sub)) - - def withConsumedSubscription(sub: SubscriptionOnResponse): SubscriptionsStateStack = - copy(stack = consumeSubscriptionOnStack(stack)(sub, _.withConsumedSubscription(sub))) - - private def withCompletedSubscription(sub: SubscriptionOnResponse) - (complete: SubscriptionsState => SubscriptionsState): SubscriptionsStateStack = { - copy(stack = completeSubscriptionOnStack(stack)(sub, complete)) - } - -} - -object SubscriptionsStateStack { - def apply(): SubscriptionsStateStack = SubscriptionsStateStack(List(SubscriptionsState())) - - private def completeSubscriptionOnStack(s: List[SubscriptionsState]) - (sub: SubscriptionOnResponse, - complete: SubscriptionsState => SubscriptionsState): List[SubscriptionsState] = s match { - case head :: tail if head.containsSubscription(sub) => complete(head) :: tail - case head :: tail => head :: completeSubscriptionOnStack(tail)(sub, complete) - case Nil => Nil - } - - private def consumeSubscriptionOnStack(s: List[SubscriptionsState]) - (sub: SubscriptionOnResponse, - consume: SubscriptionsState => SubscriptionConsumptionResult): List[SubscriptionsState] = s match { - case head :: tail if head.containsSubscription(sub) => - consume(head) match { - case AllSubscriptionsConsumed => - tail - case SomeSubscriptionsLeft(updated) => - updated :: tail - } - case head :: tail => head :: consumeSubscriptionOnStack(tail)(sub, consume) - case Nil => Nil - } -} - -case class SubscriptionsState private (private val subscriptions: Map[SubscriptionOnResponse, SubscriptionState], onAllRequestsPublished: Set[SubscriptionOnResponse] => Unit) { - def containsSubscription(sub: SubscriptionOnResponse) = subscriptions.contains(sub) - - def withRegisteredPromise(sub: SubscriptionOnResponse): SubscriptionsState = copy(subscriptions = subscriptions + (sub -> SubscriptionPromisedState)) - - def withOnAllRequestsPublished(newOnAllRequestsPublished: Set[SubscriptionOnResponse] => Unit): SubscriptionConsumptionResult = { - if (subscriptions.isEmpty) { - newOnAllRequestsPublished(Set.empty) - AllSubscriptionsConsumed - } else { - copy(onAllRequestsPublished = newOnAllRequestsPublished).consumptionResult - } - } - - def withPublishedRequestFor(sub: SubscriptionOnResponse): SubscriptionsState = - copy(subscriptions = subscriptions.updated(sub, RequestPublishedState)).completionResult - - def withAbortedRequestFor(sub: SubscriptionOnResponse): SubscriptionsState = - copy(subscriptions = subscriptions - sub).completionResult - - private def completionResult: SubscriptionsState = { - val published = subscriptions.filter { - case (k, v) => v.isPublished - } - if (published.size == subscriptions.size) { - onAllRequestsPublished(published.keys.toSet) - } - this - } - - def withConsumedSubscription(sub: SubscriptionOnResponse): SubscriptionConsumptionResult = - copy(subscriptions = subscriptions.updated(sub, SubscriptionConsumedState)).consumptionResult - - private def consumptionResult: SubscriptionConsumptionResult = { - if (subscriptions.values.forall(_ == SubscriptionConsumedState)) { - AllSubscriptionsConsumed - } else { - SomeSubscriptionsLeft(this) - } - } -} - -sealed trait SubscriptionState { - def isPublished: Boolean -} - -case object SubscriptionPromisedState extends SubscriptionState { - override def isPublished: Boolean = false -} -case object RequestPublishedState extends SubscriptionState { - override def isPublished: Boolean = true -} -case object SubscriptionConsumedState extends SubscriptionState { - override def isPublished: Boolean = true -} - -sealed trait SubscriptionConsumptionResult - -case object AllSubscriptionsConsumed extends SubscriptionConsumptionResult - -case class SomeSubscriptionsLeft(updated: SubscriptionsState) extends SubscriptionConsumptionResult - -object SubscriptionsState { - def apply(): SubscriptionsState = - new SubscriptionsState(Map.empty, _ => throw new IllegalStateException("Callback should be executed after withNextState")) - - def apply(onAllRequestsPublished: Set[SubscriptionOnResponse] => Unit): SubscriptionsState = - new SubscriptionsState(Map.empty, onAllRequestsPublished) -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/json4s/Json4sSerializer.scala b/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/json4s/Json4sSerializer.scala deleted file mode 100644 index b28b09f..0000000 --- a/rhttpc-akka-persistence/src/main/scala/rhttpc/akkapersistence/json4s/Json4sSerializer.scala +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.json4s - -import java.nio.ByteBuffer -import java.nio.charset.Charset - -import akka.actor.ExtendedActorSystem -import akka.serialization.Serializer -import org.json4s.native.Serialization._ -import org.json4s.{DefaultFormats, Formats, TypeHints} -import rhttpc.transport.json4s.{AllTypeHints, ObjectSerializer} - -class Json4sSerializer(system: ExtendedActorSystem) extends Serializer { - import Json4sSerializer._ - import rhttpc.transport.json4s.CommonFormats._ - - override def identifier: Int = ID - - override def includeManifest: Boolean = true - - override def fromBinary(bytes: Array[Byte], manifestOpt: Option[Class[_]]): AnyRef = { - implicit val manifest = manifestOpt match { - case Some(x) => Manifest.classType(x) - case None => Manifest.AnyRef - } - read(new String(bytes, UTF8)) - } - - override def toBinary(o: AnyRef): Array[Byte] = { - writePretty(o).getBytes(UTF8) - } -} - -object Json4sSerializer { - private val UTF8: Charset = Charset.forName("UTF-8") - private val ID: Int = ByteBuffer.wrap("json4s".getBytes(UTF8)).getInt -} \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/FooBarActor.scala b/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/FooBarActor.scala deleted file mode 100644 index f4e18bf..0000000 --- a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/FooBarActor.scala +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence - -import akka.actor._ -import rhttpc.client.InOutReliableClient -import rhttpc.client.subscription.SubscriptionManager - -import scala.concurrent.duration._ - -class FooBarActor(protected val id: String, client: InOutReliableClient[String]) extends MockReliableFSM[FooBarState, FooBarData] { - import context.dispatcher - - override protected def persistenceCategory: String = FooBarActor.persistenceCategory - - override protected def subscriptionManager: SubscriptionManager = client.subscriptionManager - - startWith(InitState, EmptyData) - - when(InitState) { - case Event(SendMsg(msg), _) => - client.send(msg) pipeTo this - goto(WaitingForResponseState) replyingAfterSave() - } - - when(WaitingForResponseState) { - case Event("foo", _) => goto(FooState).acknowledgingAfterSave() - case Event("bar", _) => goto(BarState).acknowledgingAfterSave() - } - - when(FooState, stateTimeout = 5 minutes) { - case Event(StateTimeout, _) => stop() - } - - when(BarState, stateTimeout = 5 minutes) { - case Event(StateTimeout, _) => stop() - } - - whenUnhandled { - case Event(CurrentState, _) => - sender() ! stateName - stay() - case Event(StopYourself, _) => - stop() - case Event(event, _) if handleRecover.isDefinedAt(event) => // whenUnhandled doesn't append handlers so it must be duplicated - handleRecover(event) - stay() - } -} - -object FooBarActor { - val persistenceCategory = "foobar" - - def props(id: String, client: InOutReliableClient[String]): Props = Props(new FooBarActor(id, client)) -} - -sealed trait FooBarState - -case object InitState extends FooBarState -case object WaitingForResponseState extends FooBarState -case object FooState extends FooBarState -case object BarState extends FooBarState - -sealed trait FooBarData - -case object EmptyData extends FooBarData - -case class SendMsg(msg: String) -case object CurrentState -case object StopYourself \ No newline at end of file diff --git a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/ReliableFSMSpec.scala b/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/ReliableFSMSpec.scala deleted file mode 100644 index 1c42186..0000000 --- a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/ReliableFSMSpec.scala +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence - -import akka.actor.{ActorSystem, FSM, PoisonPill} -import akka.persistence._ -import akka.testkit._ -import org.scalatest.matchers.should.Matchers -import rhttpc.akkapersistence.impl._ -import rhttpc.client.ReliableClientBaseSpec - -import scala.concurrent.Await -import scala.concurrent.duration._ - -class ReliableFSMSpec - extends TestKit(ActorSystem("ReliableFSMSpec")) - with ReliableClientBaseSpec with ImplicitSender with Matchers { - - // FIXME: tests doesn't pass after some changes - expected StateSaved, found () - ignore should "save snapshot after message publication and reply with StateSaved" in { fixture => - createAndSendFoo(fixture, "12") - } - - ignore should "recover in correct state not saving snapshot one more time" in { fixture => - val id = "123" - val actor = createAndSendFoo(fixture, id) - val snapshot = actor.underlyingActor.savedSnapshots.head - - watch(actor) - actor ! PoisonPill - expectTerminated(actor) - - val recovered = TestActorRef[FooBarActor](FooBarActor.props(id, fixture.client)) - recovered ! NotifyAboutRecoveryCompleted - recovered.underlyingActor.recover(snapshot) - expectMsg(RecoveryCompleted) - - Thread.sleep(500) - recovered.underlyingActor.savedSnapshots shouldBe empty - - fixture.transport.replySubscriptionPromise.success("foo") - awaitCond(recovered.underlyingActor.savedSnapshots.size == 1) - Await.result(fixture.transport.ackOnReplySubscriptionFuture, 3 seconds) - - recovered ! CurrentState - expectMsg(FooState) - } - - def createAndSendFoo(fixture: FixtureParam, id: String): TestActorRef[FooBarActor] = { - val actor = TestActorRef[FooBarActor](FooBarActor.props(id, fixture.client)) - actor ! SendMsg("foo") - Thread.sleep(500) - actor.underlyingActor.savedSnapshots shouldBe empty - fixture.transport.publicationPromise.success(()) - awaitCond(actor.underlyingActor.savedSnapshots.size == 1) - expectMsg(StateSaved) - actor - } -} - -trait MockReliableFSM[S, D] extends AbstractReliableFSM[S, D] with MockSnapshotter[S, D] - -trait MockSnapshotter[S, D] extends AbstractSnapshotter { this: FSM[S, D] => - @volatile var savedSnapshots: List[SnapshotWithSeqNr] = List.empty - - override def saveSnapshotWithSeqNr(snapshot: Any, seqNr: Long): Unit = { - savedSnapshots = SnapshotWithSeqNr(snapshot, seqNr) :: savedSnapshots - self ! SaveSnapshotSuccess(SnapshotMetadata(persistenceId, seqNr)) - } - - def recover(snap: SnapshotWithSeqNr) = { - self ! SnapshotOffer(SnapshotMetadata(persistenceId, snap.seqNr), snap.snapshot) - } - - protected def handleRecover: Receive = { - val handleOfferAndThanSendCompleted: Receive = { - case offer: SnapshotOffer => - receiveRecover(offer) - self ! RecoveryCompleted - } - handleOfferAndThanSendCompleted orElse receiveRecover - } - - whenUnhandled { - case Event(event, _) if handleRecover.isDefinedAt(event) => - handleRecover(event) - stay() - } - - override def deleteSnapshots(criteria: SnapshotSelectionCriteria): Unit = {} -} - -case class SnapshotWithSeqNr(snapshot: Any, seqNr: Long) diff --git a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStackSpec.scala b/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStackSpec.scala deleted file mode 100644 index 6bda982..0000000 --- a/rhttpc-akka-persistence/src/test/scala/rhttpc/akkapersistence/impl/SubscriptionsStateStackSpec.scala +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.akkapersistence.impl - -import org.scalatest.matchers.should.Matchers -import org.scalatest.flatspec.AnyFlatSpec -import rhttpc.client.subscription.SubscriptionOnResponse - -class SubscriptionsStateStackSpec extends AnyFlatSpec with Matchers { - - it should "notify about sub after register -> publish" in { - var published: Set[SubscriptionOnResponse] = null - val sub = SubscriptionOnResponse("foo") - SubscriptionsStateStack() - .withRegisteredPromise(sub) - .withNextState(published = _) - .withPublishedRequestFor(sub) - published shouldEqual Set(sub) - } - - it should "notify about sub after register -> next -> publish" in { - var published: Set[SubscriptionOnResponse] = null - val sub = SubscriptionOnResponse("foo") - SubscriptionsStateStack() - .withRegisteredPromise(sub) - .withNextState(published = _) - .withPublishedRequestFor(sub) - - published shouldEqual Set(sub) - } - - it should "notify about sub after register1 -> register2 -> publish1 -> consume1 -> publish2" in { - var published: Set[SubscriptionOnResponse] = null - val sub1 = SubscriptionOnResponse("foo1") - val sub2 = SubscriptionOnResponse("foo2") - SubscriptionsStateStack() - .withRegisteredPromise(sub1) - .withRegisteredPromise(sub2) - .withNextState(published = _) - .withPublishedRequestFor(sub1) - .withConsumedSubscription(sub1) - .withPublishedRequestFor(sub2) - - published shouldEqual Set(sub1, sub2) - } - - it should "notify about sub after register1 -> register2 -> publish1 -> abort2" in { - var published: Set[SubscriptionOnResponse] = null - val sub1 = SubscriptionOnResponse("foo1") - val sub2 = SubscriptionOnResponse("foo2") - SubscriptionsStateStack() - .withRegisteredPromise(sub1) - .withRegisteredPromise(sub2) - .withNextState(published = _) - .withPublishedRequestFor(sub1) - .withAbortedRequestFor(sub2) - - published shouldEqual Set(sub1) - } - - it should "notify about sub after empty -> next" in { - var published1: Set[SubscriptionOnResponse] = null - var published2: Set[SubscriptionOnResponse] = null - val sub = SubscriptionOnResponse("foo") - SubscriptionsStateStack() - .withNextState(published1 = _) - .withRegisteredPromise(sub) - .withNextState(published2 = _) - .withPublishedRequestFor(sub) - - published1 shouldEqual Set.empty - published2 shouldEqual Set(sub) - } - -} \ No newline at end of file diff --git a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcScheduler.scala b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcScheduler.scala index dfa44f1..5bf5044 100644 --- a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcScheduler.scala +++ b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcScheduler.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport.amqpjdbc -import akka.actor.{Cancellable, Scheduler} +import org.apache.pekko.actor.{Cancellable, Scheduler} import org.slf4j.LoggerFactory import rhttpc.transport.SerializingPublisher.SerializedMessage import rhttpc.transport._ diff --git a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcTransport.scala b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcTransport.scala index c2de600..e5438b3 100644 --- a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcTransport.scala +++ b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/AmqpJdbcTransport.scala @@ -16,9 +16,8 @@ package rhttpc.transport.amqpjdbc import _root_.slick.jdbc.{JdbcBackend, JdbcProfile} -import akka.actor.{ActorRef, ActorSystem} +import org.apache.pekko.actor.{ActorRef, ActorSystem} import rhttpc.utils.Agent -import com.github.ghik.silencer.silent import com.rabbitmq.client.AMQP.Queue.DeclareOk import com.rabbitmq.client.{AMQP, Connection} import rhttpc.transport.SerializingPublisher.SerializedMessage @@ -26,6 +25,7 @@ import rhttpc.transport._ import rhttpc.transport.amqp.{AmqpDeclareInboundQueueData, AmqpDeclareOutboundQueueData, AmqpQueueStats, AmqpTransport} import rhttpc.transport.amqpjdbc.slick.SlickJdbcScheduledMessagesRepository +import scala.annotation.nowarn import scala.collection.concurrent.TrieMap import scala.concurrent.Future import scala.concurrent.duration._ @@ -45,7 +45,7 @@ private[amqpjdbc] class AmqpJdbcTransportImpl(underlying: AmqpTransport, private val schedulersCache = TrieMap[String, AmqpJdbcScheduler[_]]() - @silent private val publisherQueueNamesAgent = Agent[Set[String]](Set.empty) + @nowarn private val publisherQueueNamesAgent = Agent[Set[String]](Set.empty) override def publisher[PubMsg: Serializer](queueData: OutboundQueueData): Publisher[PubMsg] = { val underlyingPublisher = underlying.publisher[PubMsg](queueData).asInstanceOf[SerializingPublisher[PubMsg]] diff --git a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/package.scala b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/package.scala index 9c6acb9..4146f43 100644 --- a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/package.scala +++ b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/package.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem import com.rabbitmq.client.Connection import slick.jdbc.{JdbcBackend, JdbcProfile} diff --git a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/slick/AddingPropertiesToScheduledMessagesMigration.scala b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/slick/AddingPropertiesToScheduledMessagesMigration.scala index 8c3578d..217537d 100644 --- a/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/slick/AddingPropertiesToScheduledMessagesMigration.scala +++ b/rhttpc-amqp-jdbc/src/main/scala/rhttpc/transport/amqpjdbc/slick/AddingPropertiesToScheduledMessagesMigration.scala @@ -40,7 +40,6 @@ trait AddingPropertiesToScheduledMessagesMigration extends SlickJdbcMigration { protected val messageMaxSize = 8192 protected val propertiesMaxSize = 256 - import scala.collection.compat._ import scala.jdk.CollectionConverters._ protected implicit def propertiesMapper: JdbcType[Map[String, Any]] = MappedColumnType.base[Map[String, Any], String]( diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpConnectionFactory.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpConnectionFactory.scala index 7ec1327..c835dcd 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpConnectionFactory.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpConnectionFactory.scala @@ -15,33 +15,55 @@ */ package rhttpc.transport.amqp -import java.util.concurrent.TimeUnit - -import akka.actor.ActorSystem import com.rabbitmq.client.{Connection, ConnectionFactory} -import net.ceedubs.ficus.Ficus._ -import net.ceedubs.ficus.readers.ArbitraryTypeReader +import com.typesafe.config.Config +import org.apache.pekko.actor.ActorSystem -import scala.concurrent.duration.{Duration, FiniteDuration} -import scala.concurrent.{ExecutionContext, Future} +import java.util.concurrent.TimeUnit +import scala.annotation.tailrec import scala.concurrent._ +import scala.concurrent.duration.{Duration, FiniteDuration} +import scala.jdk.CollectionConverters._ import scala.util._ object AmqpConnectionFactory { private final val DEFAULT_RETRY_CONFIG = AmqpConnectionRetry( count = 10, - delay = Duration(5, TimeUnit.SECONDS) + delay = Duration(5, TimeUnit.SECONDS), ) def connect(actorSystem: ActorSystem): Future[Connection] = { - import ArbitraryTypeReader._ import actorSystem.dispatcher - val config = actorSystem.settings.config.as[AmqpConfig]("amqp") - connect(config) + val config = actorSystem.settings.config + val amqpConfig = AmqpConfig( + hosts = config.getStringList("hosts").asScala.toSeq, + port = getOptionFromConfig("port", config, _.getInt(_)), + virtualHost = getOptionFromConfig("virtualHost", config, _.getString(_)), + userName = getOptionFromConfig("userName", config, _.getString(_)), + password = getOptionFromConfig("password", config, _.getString(_)), + retry = getOptionFromConfig("retry", config, _.getConfig(_)).map { c => + AmqpConnectionRetry( + count = config.getInt("count"), + delay = FiniteDuration(config.getDuration("delay").toMillis, TimeUnit.MILLISECONDS), + ) + }, + ) + connect(amqpConfig) + } + + private def getOptionFromConfig[T](path: String, config: Config, extract: (Config, String) => T): Option[T] = { + getFirstDefinedFromConfig(List(path), config, extract) + } + + private def getFirstDefinedFromConfig[T](paths: List[String], + config: Config, + extract: (Config, String) => T): Option[T] = { + paths + .find(config.hasPath) + .map(extract(config, _)) } - def connect(config: AmqpConfig) - (implicit executionContext: ExecutionContext): Future[Connection] = + def connect(config: AmqpConfig)(implicit executionContext: ExecutionContext): Future[Connection] = Future { blocking { val factory = new ConnectionFactory() @@ -51,9 +73,7 @@ object AmqpConnectionFactory { config.password.foreach(factory.setPassword) factory.setAutomaticRecoveryEnabled(true) val retryConfig = config.retry.getOrElse(DEFAULT_RETRY_CONFIG) - retry( - n = retryConfig.count, - delay = retryConfig.delay.toMillis) { + retry(n = retryConfig.count, delay = retryConfig.delay.toMillis) { Try { // Could By IOException or TimeoutException @@ -64,6 +84,7 @@ object AmqpConnectionFactory { } } + @tailrec private def retry[T](n: Int, delay: Long)(fn: => Try[T]): T = { fn match { case Success(x) => x @@ -82,5 +103,4 @@ case class AmqpConfig(hosts: Seq[String], password: Option[String] = None, retry: Option[AmqpConnectionRetry] = None) -case class AmqpConnectionRetry(count: Int, - delay: FiniteDuration) \ No newline at end of file +case class AmqpConnectionRetry(count: Int, delay: FiniteDuration) diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpDefaults.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpDefaults.scala index 1def009..72ea6fe 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpDefaults.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpDefaults.scala @@ -27,7 +27,6 @@ trait AmqpDefaults extends AmqpQueuesNaming with AmqpExchangesNaming { - import scala.collection.compat._ import scala.jdk.CollectionConverters._ private[rhttpc] final val consumeTimeout: FiniteDuration = 5 minutes diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpPublisher.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpPublisher.scala index 2fcafea..a9b9f57 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpPublisher.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpPublisher.scala @@ -17,13 +17,13 @@ package rhttpc.transport.amqp import java.io._ import rhttpc.utils.Agent -import com.github.ghik.silencer.silent import com.rabbitmq.client._ import org.slf4j.LoggerFactory import rhttpc.transport.SerializingPublisher.SerializedMessage import rhttpc.transport.{Message, Publisher, Serializer, SerializingPublisher} import rhttpc.utils.Recovered._ +import scala.annotation.nowarn import scala.concurrent.{ExecutionContext, Future, Promise} private[amqp] class AmqpPublisher[PubMsg](channel: Channel, @@ -36,7 +36,7 @@ private[amqp] class AmqpPublisher[PubMsg](channel: Channel, private lazy val logger = LoggerFactory.getLogger(getClass) - @silent private val seqNoOnAckPromiseAgent = Agent[Map[Long, Promise[Unit]]](Map.empty) + @nowarn private val seqNoOnAckPromiseAgent = Agent[Map[Long, Promise[Unit]]](Map.empty) override private[rhttpc] def publishSerialized(msg: SerializedMessage): Future[Unit] = { val properties = prepareProperties.applyOrElse( diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpSubscriber.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpSubscriber.scala index 18d3abf..fc7c01d 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpSubscriber.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpSubscriber.scala @@ -15,16 +15,16 @@ */ package rhttpc.transport.amqp -import akka.actor._ +import org.apache.pekko.actor._ import rhttpc.utils.Agent -import akka.pattern._ -import akka.util.Timeout -import com.github.ghik.silencer.silent +import org.apache.pekko.pattern._ +import org.apache.pekko.util.Timeout import com.rabbitmq.client._ import org.slf4j.LoggerFactory import rhttpc.transport._ import rhttpc.utils.Recovered._ +import scala.annotation.nowarn import scala.concurrent.duration._ import scala.concurrent.{Future, Promise} import scala.util.{Failure, Success, Try} @@ -42,7 +42,7 @@ private[amqp] abstract class AmqpSubscriber[Sub](channel: Channel, private lazy val logger = LoggerFactory.getLogger(getClass) - @silent private val pendingConsumePromises = Agent[Set[Promise[Unit]]](Set.empty) + @nowarn private val pendingConsumePromises = Agent[Set[Promise[Unit]]](Set.empty) @volatile private var consumerTag: Option[String] = None @@ -134,7 +134,6 @@ trait SendingFullMessage[Sub] { self: AmqpSubscriber[Sub] => // that is why if you ever add a new string property here use _.toString instead of casting (we do not Cast to LongString to avoid weird dependencies // between modules, and casting to String would result in ClassCastException) override protected def prepareMessage(deserializedMessage: Sub, properties: AMQP.BasicProperties): Any = { - import scala.collection.compat._ import scala.jdk.CollectionConverters._ Message(deserializedMessage, Option(properties.getHeaders).map(_.asInstanceOf[java.util.Map[String, Any]].asScala.toMap).getOrElse(Map.empty)) } diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpTransport.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpTransport.scala index d05d807..12d9325 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpTransport.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/AmqpTransport.scala @@ -15,14 +15,14 @@ */ package rhttpc.transport.amqp -import akka.actor._ +import org.apache.pekko.actor._ import rhttpc.utils.Agent -import com.github.ghik.silencer.silent import com.rabbitmq.client.AMQP.Queue.DeclareOk import com.rabbitmq.client.{AMQP, Channel, Connection} import rhttpc.transport.SerializingPublisher.SerializedMessage import rhttpc.transport._ +import scala.annotation.nowarn import scala.concurrent.Future import scala.concurrent.duration._ import scala.util.Try @@ -45,7 +45,7 @@ private[rhttpc] class AmqpTransportImpl(connection: Connection, private lazy val statsChannel = connection.createChannel() - @silent private val queueNamesAgent = Agent[Set[String]](Set.empty) + @nowarn private val queueNamesAgent = Agent[Set[String]](Set.empty) override def publisher[PubMsg](queueData: OutboundQueueData) (implicit serializer: Serializer[PubMsg]): AmqpPublisher[PubMsg] = { diff --git a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/package.scala b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/package.scala index e6a0068..2b60782 100644 --- a/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/package.scala +++ b/rhttpc-amqp/src/main/scala/rhttpc/transport/amqp/package.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem import com.rabbitmq.client.Connection package object amqp { diff --git a/rhttpc-amqp/src/test/resources/application.conf b/rhttpc-amqp/src/test/resources/application.conf index d81fef8..8e86f6c 100644 --- a/rhttpc-amqp/src/test/resources/application.conf +++ b/rhttpc-amqp/src/test/resources/application.conf @@ -1,8 +1,8 @@ akka { loglevel = "DEBUG" - loggers = ["akka.event.slf4j.Slf4jLogger"] - event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger"] + event-handlers = ["org.apache.pekko.event.slf4j.Slf4jEventHandler"] + logging-filter = "org.apache.pekko.event.slf4j.Slf4jLoggingFilter" log-dead-letters = on } diff --git a/rhttpc-amqp/src/test/scala/rhttpc/transport/amqp/AmqpSubscriberPerfSpec.scala b/rhttpc-amqp/src/test/scala/rhttpc/transport/amqp/AmqpSubscriberPerfSpec.scala index a764d6e..1137bee 100644 --- a/rhttpc-amqp/src/test/scala/rhttpc/transport/amqp/AmqpSubscriberPerfSpec.scala +++ b/rhttpc-amqp/src/test/scala/rhttpc/transport/amqp/AmqpSubscriberPerfSpec.scala @@ -15,13 +15,14 @@ */ package rhttpc.transport.amqp -import akka.Done -import akka.actor.{Actor, ActorSystem, Props} -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} -import akka.pattern._ -import akka.testkit.{TestKit, TestProbe} -import dispatch.url +import org.apache.pekko.Done +import org.apache.pekko.actor.{Actor, ActorSystem, Props} +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model.{HttpRequest, HttpResponse} +import org.apache.pekko.pattern._ +import org.apache.pekko.stream.Materializer +import org.apache.pekko.testkit.{TestKit, TestProbe} +import dispatch._ import org.scalatest.{BeforeAndAfterAll, Ignore} import org.scalatest.flatspec.AnyFlatSpecLike import rhttpc.transport.{Deserializer, InboundQueueData, OutboundQueueData, QueueType, Serializer} @@ -34,15 +35,11 @@ import scala.util.{Random, Try} class AmqpSubscriberPerfSpec extends TestKit(ActorSystem("AmqpSubscriberPerfSpec")) with AnyFlatSpecLike with BeforeAndAfterAll { import system.dispatcher - implicit val materializer = akka.stream.Materializer.matFromSystem + implicit val materializer: Materializer = org.apache.pekko.stream.Materializer.matFromSystem - implicit def serializer[Msg] = new Serializer[Msg] { - override def serialize(obj: Msg): String = obj.toString - } + implicit def serializer[Msg]: Serializer[Msg] = (obj: Msg) => obj.toString - implicit def deserializer[Msg] = new Deserializer[Msg] { - override def deserialize(value: String): Try[Msg] = Try(value.asInstanceOf[Msg]) - } + implicit def deserializer[Msg]: Deserializer[Msg] = (value: String) => Try(value.asInstanceOf[Msg]) val queueName = "request" val outboundQueueData = OutboundQueueData(queueName, autoDelete = true, durability = false, queueType = QueueType.ClassicQueue) diff --git a/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/ArgonautSerializer.scala b/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/ArgonautSerializer.scala deleted file mode 100644 index 3b2b94c..0000000 --- a/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/ArgonautSerializer.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.argonaut - -import java.text.ParseException - -import _root_.argonaut.Argonaut._ -import _root_.argonaut.{DecodeJson, EncodeJson, PrettyParams} -import rhttpc.transport.{Deserializer, Serializer} - -import scala.util.{Failure, Success, Try} - -class ArgonautSerializer[Msg: EncodeJson](implicit prettyParams: PrettyParams = defaultPrettyParams) - extends Serializer[Msg] { - - override def serialize(msg: Msg): String = { - msg.asJson.pretty(prettyParams) - } -} - -class ArgonautDeserializer[Msg: DecodeJson] extends Deserializer[Msg] { - override def deserialize(value: String): Try[Msg] = { - value.decodeWithMessage[Try[Msg], Msg](Success(_), msg => Failure(new ParseException(msg, -1))) - } -} \ No newline at end of file diff --git a/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/package.scala b/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/package.scala deleted file mode 100644 index b86081a..0000000 --- a/rhttpc-argonaut_6.2/src/main/scala/rhttpc/transport/argonaut/package.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport - -import _root_.argonaut.PrettyParams -import _root_.argonaut.EncodeJson -import _root_.argonaut.DecodeJson - -package object argonaut { - - implicit def serializer[Msg](implicit encodeJson: EncodeJson[Msg], - prettyParams: PrettyParams = defaultPrettyParams): Serializer[Msg] = - new ArgonautSerializer[Msg]()(encodeJson, prettyParams) - - implicit def deserializer[Msg: DecodeJson]: Deserializer[Msg] = - new ArgonautDeserializer[Msg]() - - private[argonaut] val defaultPrettyParams: PrettyParams = - PrettyParams - .spaces2 - .copy(preserveOrder = true, dropNullKeys = true) - -} \ No newline at end of file diff --git a/rhttpc-client/src/main/scala/rhttpc/client/ReliableClient.scala b/rhttpc-client/src/main/scala/rhttpc/client/ReliableClient.scala index 2033b85..0a581d9 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/ReliableClient.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/ReliableClient.scala @@ -17,7 +17,7 @@ package rhttpc.client import java.util.UUID -import akka.actor._ +import org.apache.pekko.actor._ import org.slf4j.LoggerFactory import rhttpc.client.config.ConfigParser import rhttpc.client.consume.MessageConsumerFactory diff --git a/rhttpc-client/src/main/scala/rhttpc/client/config/ConfigParser.scala b/rhttpc-client/src/main/scala/rhttpc/client/config/ConfigParser.scala index aeadf69..2f1a0b6 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/config/ConfigParser.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/config/ConfigParser.scala @@ -15,14 +15,15 @@ */ package rhttpc.client.config -import akka.actor.ActorSystem import com.typesafe.config.Config -import net.ceedubs.ficus.Ficus._ -import net.ceedubs.ficus.readers.ArbitraryTypeReader._ -import net.ceedubs.ficus.readers.ValueReader +import org.apache.pekko.actor.ActorSystem +import rhttpc.client.config.ConfigParserUtils._ import rhttpc.client.proxy.{BackoffRetry, FailureResponseHandleStrategyChooser, HandleAll, SkipAll} import rhttpc.transport.QueueType +import java.time.Duration +import java.util.concurrent.TimeUnit +import scala.concurrent.duration.FiniteDuration import scala.util.{Success, Try} object ConfigParser { @@ -31,37 +32,64 @@ object ConfigParser { } def parse(config: Config, path: String): RhttpcConfig = { - config.as[RhttpcConfig](path) + val configAtPath = if (path == ".") config else config.getConfig(path) + RhttpcConfig( + queuesPrefix = configAtPath.getString("queuesPrefix"), + batchSize = configAtPath.getInt("batchSize"), + parallelConsumers = configAtPath.getInt("parallelConsumers"), + retryStrategy = RetryStrategyValueReader.getRetryStrategy(configAtPath, "retryStrategy"), + queueType = QueueTypeValueReader.getQueueType(configAtPath, "queueType"), + ) } - - private implicit def failureResponseHandleStrategyChooserReader: ValueReader[FailureResponseHandleStrategyChooser] = RetryStrategyValueReader - private implicit def queueTypeReader: ValueReader[QueueType] = QueueTypeValueReader } -object RetryStrategyValueReader extends ValueReader[FailureResponseHandleStrategyChooser] { - override def read(config: Config, path: String): FailureResponseHandleStrategyChooser = { - config.as[Try[String]](path) match { +object RetryStrategyValueReader { + def getRetryStrategy(config: Config, path: String): FailureResponseHandleStrategyChooser = { + Try(config.getString(path)) match { case Success("handle-all") => HandleAll case Success("skip-all") => SkipAll - case _ => config.as[BackoffRetry](path) + case _ => + BackoffRetry( + initialDelay = toFiniteDuration(config.getDuration(s"$path.initialDelay")), + multiplier = BigDecimal(config.getDouble(s"$path.multiplier")), + maxRetries = config.getInt(s"$path.maxRetries"), + deadline = getOptionFromConfig(s"$path.deadline", config, _.getDuration(_)).map(toFiniteDuration), + ) } } } -object QueueTypeValueReader extends ValueReader[QueueType] { - override def read(config: Config, path: String): QueueType = { - config.getAs[String](path).fold[QueueType](QueueType.ClassicQueue) { +object QueueTypeValueReader { + def getQueueType(config: Config, path: String): QueueType = { + getOptionFromConfig(path, config, _.getString(_)).fold[QueueType](QueueType.ClassicQueue) { case "classic" => QueueType.ClassicQueue case "quorum" => QueueType.QuorumQueue - case other => throw InvalidConfigValueException(s"Invalid value as QueueType=[$other]. Should be one of: classic, quorum.") + case other => + throw InvalidConfigValueException(s"Invalid value as QueueType=[$other]. Should be one of: classic, quorum.") } } } +private object ConfigParserUtils { + def toFiniteDuration(duration: Duration): FiniteDuration = + FiniteDuration(duration.toMillis, TimeUnit.MILLISECONDS) + + def getOptionFromConfig[T](path: String, config: Config, extract: (Config, String) => T): Option[T] = { + getFirstDefinedFromConfig(List(path), config, extract) + } + + def getFirstDefinedFromConfig[T](paths: List[String], config: Config, extract: (Config, String) => T): Option[T] = { + paths + .find(config.hasPath) + .map(extract(config, _)) + } + +} + case class RhttpcConfig(queuesPrefix: String, batchSize: Int, parallelConsumers: Int, retryStrategy: FailureResponseHandleStrategyChooser, queueType: QueueType) -final case class InvalidConfigValueException(message: String) extends Exception(message) \ No newline at end of file +final case class InvalidConfigValueException(message: String) extends Exception(message) diff --git a/rhttpc-client/src/main/scala/rhttpc/client/consume/MessageConsumer.scala b/rhttpc-client/src/main/scala/rhttpc/client/consume/MessageConsumer.scala index 0054ecb..506d9ce 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/consume/MessageConsumer.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/consume/MessageConsumer.scala @@ -15,8 +15,8 @@ */ package rhttpc.client.consume -import akka.actor._ -import akka.pattern._ +import org.apache.pekko.actor._ +import org.apache.pekko.pattern._ import rhttpc.utils.Recovered import Recovered._ import rhttpc.client._ diff --git a/rhttpc-client/src/main/scala/rhttpc/client/proxy/ReliableProxy.scala b/rhttpc-client/src/main/scala/rhttpc/client/proxy/ReliableProxy.scala index a7b2c04..4c57355 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/proxy/ReliableProxy.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/proxy/ReliableProxy.scala @@ -17,8 +17,8 @@ package rhttpc.client.proxy import java.time.Instant -import akka.actor._ -import akka.pattern._ +import org.apache.pekko.actor._ +import org.apache.pekko.pattern._ import org.slf4j.LoggerFactory import rhttpc.client._ import rhttpc.client.config.ConfigParser diff --git a/rhttpc-client/src/main/scala/rhttpc/client/subscription/MessageDispatcherActor.scala b/rhttpc-client/src/main/scala/rhttpc/client/subscription/MessageDispatcherActor.scala index 38ceb3a..a6e42f5 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/subscription/MessageDispatcherActor.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/subscription/MessageDispatcherActor.scala @@ -15,7 +15,7 @@ */ package rhttpc.client.subscription -import akka.actor.{Actor, ActorLogging, ActorRef, Status} +import org.apache.pekko.actor.{Actor, ActorLogging, ActorRef, Status} import rhttpc.client.protocol.{Correlated, Exchange} import scala.util.{Failure, Success} diff --git a/rhttpc-client/src/main/scala/rhttpc/client/subscription/PromiseSubscriptionCommandsListener.scala b/rhttpc-client/src/main/scala/rhttpc/client/subscription/PromiseSubscriptionCommandsListener.scala index d59ed17..f0e2a86 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/subscription/PromiseSubscriptionCommandsListener.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/subscription/PromiseSubscriptionCommandsListener.scala @@ -15,7 +15,7 @@ */ package rhttpc.client.subscription -import akka.actor.{Actor, Props, Status} +import org.apache.pekko.actor.{Actor, Props, Status} import scala.concurrent.Promise diff --git a/rhttpc-client/src/main/scala/rhttpc/client/subscription/PublicationListener.scala b/rhttpc-client/src/main/scala/rhttpc/client/subscription/PublicationListener.scala index 11c4ae0..bca2433 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/subscription/PublicationListener.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/subscription/PublicationListener.scala @@ -15,7 +15,7 @@ */ package rhttpc.client.subscription -import akka.actor.Actor +import org.apache.pekko.actor.Actor trait PublicationListener extends Actor { def subscriptionPromiseRegistered(sub: SubscriptionOnResponse): Unit diff --git a/rhttpc-client/src/main/scala/rhttpc/client/subscription/SubscriptionManager.scala b/rhttpc-client/src/main/scala/rhttpc/client/subscription/SubscriptionManager.scala index e0fea04..5b32b47 100644 --- a/rhttpc-client/src/main/scala/rhttpc/client/subscription/SubscriptionManager.scala +++ b/rhttpc-client/src/main/scala/rhttpc/client/subscription/SubscriptionManager.scala @@ -16,9 +16,9 @@ package rhttpc.client.subscription import java.util.concurrent.TimeoutException -import akka.actor._ -import akka.pattern._ -import akka.util.Timeout +import org.apache.pekko.actor._ +import org.apache.pekko.pattern._ +import org.apache.pekko.util.Timeout import rhttpc.utils.Recovered import Recovered._ import rhttpc.client._ diff --git a/rhttpc-client/src/test/resources/application.conf b/rhttpc-client/src/test/resources/application.conf index 49653a0..92ffbd0 100644 --- a/rhttpc-client/src/test/resources/application.conf +++ b/rhttpc-client/src/test/resources/application.conf @@ -1,8 +1,8 @@ akka { loglevel = "DEBUG" - loggers = ["akka.event.slf4j.Slf4jLogger"] - event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger"] + event-handlers = ["org.apache.pekko.event.slf4j.Slf4jEventHandler"] + logging-filter = "org.apache.pekko.event.slf4j.Slf4jLoggingFilter" log-dead-letters = on } \ No newline at end of file diff --git a/rhttpc-client/src/test/scala/rhttpc/client/MockTransport.scala b/rhttpc-client/src/test/scala/rhttpc/client/MockTransport.scala index 218e92b..99a5b60 100644 --- a/rhttpc-client/src/test/scala/rhttpc/client/MockTransport.scala +++ b/rhttpc-client/src/test/scala/rhttpc/client/MockTransport.scala @@ -15,9 +15,9 @@ */ package rhttpc.client -import akka.actor.ActorRef -import akka.pattern._ -import akka.util.Timeout +import org.apache.pekko.actor.ActorRef +import org.apache.pekko.pattern._ +import org.apache.pekko.util.Timeout import rhttpc.client.protocol.{Correlated, FailureExchange, SuccessExchange} import rhttpc.transport._ @@ -55,7 +55,7 @@ class MockTransport(awaitCond: (() => Boolean) => Unit)(implicit ec: ExecutionCo case Correlated(msg, correlationId) => _publicationPromise = Promise[Unit]() _replySubscriptionPromise = Promise[String]() - implicit val timeout = Timeout(5 seconds) + implicit val timeout: Timeout = Timeout(5 seconds) _replySubscriptionPromise.future.onComplete { case Success(result) => _ackOnReplySubscriptionFuture = consumer ? Correlated(SuccessExchange(msg, result), correlationId) diff --git a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientBaseSpec.scala b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientBaseSpec.scala index c2f4552..6b1351a 100644 --- a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientBaseSpec.scala +++ b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientBaseSpec.scala @@ -15,7 +15,7 @@ */ package rhttpc.client -import akka.testkit.TestKit +import org.apache.pekko.testkit.TestKit import org.scalatest._ import org.scalatest.flatspec.FixtureAnyFlatSpecLike @@ -31,7 +31,7 @@ trait ReliableClientBaseSpec extends FixtureAnyFlatSpecLike { self: TestKit => case class FixtureParam(client: InOutReliableClient[String], transport: MockTransport) override protected def withFixture(test: OneArgTest): Outcome = { - implicit val mockTransport = new MockTransport((cond: () => Boolean) => awaitCond(cond())) + implicit val mockTransport: MockTransport = new MockTransport((cond: () => Boolean) => awaitCond(cond())) val client = ReliableClientFactory().inOutWithSubscriptions[String, String]( _ => Future.successful("not used") ) diff --git a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientFutureSpec.scala b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientFutureSpec.scala index e46ebae..0f3d786 100644 --- a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientFutureSpec.scala +++ b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientFutureSpec.scala @@ -15,9 +15,9 @@ */ package rhttpc.client -import akka.actor.ActorSystem -import akka.testkit.TestKit -import akka.util.Timeout +import org.apache.pekko.actor.ActorSystem +import org.apache.pekko.testkit.TestKit +import org.apache.pekko.util.Timeout import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ @@ -26,7 +26,7 @@ import scala.concurrent.{Await, ExecutionContext, Future} class ReliableClientFutureSpec extends TestKit(ActorSystem("ReliableClientFutureSpec")) with ReliableClientBaseSpec with Matchers { override protected implicit def ec: ExecutionContext = system.dispatcher - implicit val timeout = Timeout(3 seconds) + implicit val timeout: Timeout = Timeout(3 seconds) it should "send request and reply after subscription registration" in { fixture => val sendFuture = fixture.client.send("foo").toFuture diff --git a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientWithSubscriptionActorSpec.scala b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientWithSubscriptionActorSpec.scala index 8e556e8..8292494 100644 --- a/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientWithSubscriptionActorSpec.scala +++ b/rhttpc-client/src/test/scala/rhttpc/client/ReliableClientWithSubscriptionActorSpec.scala @@ -15,8 +15,8 @@ */ package rhttpc.client -import akka.actor.{ActorRef, ActorSystem, Props} -import akka.testkit._ +import org.apache.pekko.actor.{ActorRef, ActorSystem, Props} +import org.apache.pekko.testkit._ import org.scalatest.matchers.should.Matchers import rhttpc.client.subscription._ diff --git a/rhttpc-client/src/test/scala/rhttpc/client/subscription/MessageDispatcherActorSpec.scala b/rhttpc-client/src/test/scala/rhttpc/client/subscription/MessageDispatcherActorSpec.scala index 4734d8e..b7c6142 100644 --- a/rhttpc-client/src/test/scala/rhttpc/client/subscription/MessageDispatcherActorSpec.scala +++ b/rhttpc-client/src/test/scala/rhttpc/client/subscription/MessageDispatcherActorSpec.scala @@ -17,8 +17,8 @@ package rhttpc.client.subscription import java.util.UUID -import akka.actor.{ActorSystem, Props} -import akka.testkit.{ImplicitSender, TestKit, TestProbe} +import org.apache.pekko.actor.{ActorSystem, Props} +import org.apache.pekko.testkit.{ImplicitSender, TestKit, TestProbe} import org.scalatest.matchers.should.Matchers import org.scalatest.flatspec.AnyFlatSpecLike import rhttpc.client.protocol.{Correlated, SuccessExchange} diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemPublisher.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemPublisher.scala index b6489b0..94c1223 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemPublisher.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemPublisher.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport.inmem -import akka.actor.{ActorRef, ActorSystem} +import org.apache.pekko.actor.{ActorRef, ActorSystem} import rhttpc.transport.{DelayedMessage, Message, Publisher} import scala.concurrent.Future diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemSubscriber.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemSubscriber.scala index 27365af..2b32fad 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemSubscriber.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemSubscriber.scala @@ -15,9 +15,9 @@ */ package rhttpc.transport.inmem -import akka.actor.ActorRef -import akka.pattern._ -import akka.util.Timeout +import org.apache.pekko.actor.ActorRef +import org.apache.pekko.pattern._ +import org.apache.pekko.util.Timeout import rhttpc.transport.Subscriber import scala.concurrent.Future diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemTransport.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemTransport.scala index 682ebfa..68cd9ba 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemTransport.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/InMemTransport.scala @@ -15,9 +15,9 @@ */ package rhttpc.transport.inmem -import akka.actor.{ActorRef, ActorSystem} -import akka.pattern._ -import akka.util.Timeout +import org.apache.pekko.actor.{ActorRef, ActorSystem} +import org.apache.pekko.pattern._ +import org.apache.pekko.util.Timeout import rhttpc.transport.{InboundQueueData, Publisher, _} import scala.concurrent.duration.FiniteDuration diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/QueueActor.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/QueueActor.scala index 9a5d5c7..ba8bd01 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/QueueActor.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/QueueActor.scala @@ -15,10 +15,10 @@ */ package rhttpc.transport.inmem -import akka.pattern._ -import akka.actor.{Actor, ActorLogging, ActorRef, Props, Stash} -import akka.routing.{RoundRobinRoutingLogic, Routee, Router} -import akka.util.Timeout +import org.apache.pekko.pattern._ +import org.apache.pekko.actor.{Actor, ActorLogging, ActorRef, Props, Stash} +import org.apache.pekko.routing.{RoundRobinRoutingLogic, Routee, Router} +import org.apache.pekko.util.Timeout import rhttpc.transport.{Message, RejectingMessage} import scala.concurrent.Future diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/TransportActor.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/TransportActor.scala index 9720b26..c3cf935 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/TransportActor.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/TransportActor.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport.inmem -import akka.actor.{Actor, Props, Status} +import org.apache.pekko.actor.{Actor, Props, Status} import scala.util.control.NonFatal diff --git a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/package.scala b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/package.scala index d914d4f..c7f96c9 100644 --- a/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/package.scala +++ b/rhttpc-inmem/src/main/scala/rhttpc/transport/inmem/package.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem package object inmem { diff --git a/rhttpc-inmem/src/test/resources/application.conf b/rhttpc-inmem/src/test/resources/application.conf index 49653a0..92ffbd0 100644 --- a/rhttpc-inmem/src/test/resources/application.conf +++ b/rhttpc-inmem/src/test/resources/application.conf @@ -1,8 +1,8 @@ akka { loglevel = "DEBUG" - loggers = ["akka.event.slf4j.Slf4jLogger"] - event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger"] + event-handlers = ["org.apache.pekko.event.slf4j.Slf4jEventHandler"] + logging-filter = "org.apache.pekko.event.slf4j.Slf4jLoggingFilter" log-dead-letters = on } \ No newline at end of file diff --git a/rhttpc-inmem/src/test/scala/rhttpc/transport/inmem/InMemTransportSpec.scala b/rhttpc-inmem/src/test/scala/rhttpc/transport/inmem/InMemTransportSpec.scala index 55255a8..7b935be 100644 --- a/rhttpc-inmem/src/test/scala/rhttpc/transport/inmem/InMemTransportSpec.scala +++ b/rhttpc-inmem/src/test/scala/rhttpc/transport/inmem/InMemTransportSpec.scala @@ -15,8 +15,8 @@ */ package rhttpc.transport.inmem -import akka.actor.{ActorSystem, Status} -import akka.testkit.{TestKit, TestProbe} +import org.apache.pekko.actor.{ActorSystem, Status} +import org.apache.pekko.testkit.{TestKit, TestProbe} import org.scalatest._ import org.scalatest.flatspec.FixtureAnyFlatSpecLike import rhttpc.transport.PubSubTransport diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/AllTypeHints.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/AllTypeHints.scala deleted file mode 100644 index beb172d..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/AllTypeHints.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.TypeHints -import org.json4s.reflect.Reflector - -object AllTypeHints extends TypeHints { - override def containsHint(clazz: Class[_]): Boolean = true - - override def classFor(hint: String): Option[Class[_]] = Reflector.scalaTypeOf(hint).map(_.erasure) - - override def hintFor(clazz: Class[_]): String = clazz.getName - - override def shouldExtractHints(clazz: Class[_]): Boolean = true - - override val hints: List[Class[_]] = Nil -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CommonFormats.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CommonFormats.scala deleted file mode 100644 index 52081f1..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CommonFormats.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.{DefaultFormats, Formats, TypeHints} - -object CommonFormats { - - implicit val formats: Formats = - new DefaultFormats { - override def dateFormatter = DefaultFormats.losslessDate() - override val typeHints: TypeHints = AllTypeHints - override val strictOptionParsing: Boolean = true - } + - ExceptionSerializer + - ObjectSerializer + - IndexedSeqSerializer - -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSerializerWithTypeHints.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSerializerWithTypeHints.scala deleted file mode 100644 index 92049f9..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSerializerWithTypeHints.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.JsonAST.{JObject, JString} -import org.json4s._ - -import scala.reflect.ClassTag - -class CustomSerializerWithTypeHints[T: Manifest, JV <: JValue: ClassTag]( - ser: Formats => (PartialFunction[JV, T], PartialFunction[T, JV])) - extends CustomSubTypesSerializer[T, JObject](implicit formats => { - val (deserialize, serialize) = ser(formats) - ( - { - case JObject(_ :: ("value", jValue: JV) :: Nil) if deserialize.isDefinedAt(jValue) => - deserialize(jValue) - }, - { - case obj: T if serialize.isDefinedAt(obj) => - JObject( - formats.typeHintFieldName -> JString(obj.getClass.getName), - "value" -> serialize(obj) - ) - } - ) -}) \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSubTypesSerializer.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSubTypesSerializer.scala deleted file mode 100644 index 651d948..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/CustomSubTypesSerializer.scala +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.reflect.TypeInfo -import org.json4s.{Formats, Serializer, _} - -import scala.reflect.ClassTag - -/** - * With contrary to org.json4s.CustomSerializer it has symmetric behaviour: if partial function for deserialization - * is not defined in values, serialization will be chained instead of Exception throwing. - * Also it handles subtypes - not only direct instances of T - */ -class CustomSubTypesSerializer[T: Manifest, JV <: JValue: ClassTag]( - ser: Formats => (PartialFunction[JV, T], PartialFunction[T, JV])) extends Serializer[T] { - - private val Class = implicitly[Manifest[T]].runtimeClass - - def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), T] = { - val d = ser(format)._1 - val pf: PartialFunction[(TypeInfo, JValue), T] = { - case (TypeInfo(clazz, _), jValue: JV) if Class.isAssignableFrom(clazz) && d.isDefinedAt(jValue) => - d(jValue) - } - pf - } - - def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { - val s = ser(format)._2 - val pf: PartialFunction[Any, JValue] = { - case obj: T if s.isDefinedAt(obj) => - s(obj) - } - pf - } - -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ExceptionSerializer.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ExceptionSerializer.scala deleted file mode 100644 index 89c6666..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ExceptionSerializer.scala +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import java.lang.reflect.Constructor - -import org.json4s.{CustomSerializer, Extraction, Formats, Serializer, TypeInfo} -import org.json4s.JsonAST._ - -import scala.util.Try - -object ExceptionSerializer extends Serializer[Throwable] { - override def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Throwable] = { - case ( - TypeInfo(clazz, _), - JObject(("jsonClass", JString(ExceptionClassHavingConstructorWithMessageAndCause(constructor))) :: - ("message", JString(message)) :: - ("cause", cause) :: - Nil)) if classOf[Throwable].isAssignableFrom(clazz) => - constructor.newInstance(message, Extraction.extract[Throwable](cause)) - case ( - TypeInfo(clazz, _), - JObject(("jsonClass", JString(ExceptionClassHavingConstructorWithMessageAndCause(constructor))) :: - ("message", JNull) :: - ("cause", cause) :: - Nil)) if classOf[Throwable].isAssignableFrom(clazz) => - constructor.newInstance(null, Extraction.extract[Throwable](cause)) - case ( - TypeInfo(clazz, _), - JObject(("jsonClass", JString(ExceptionClassHavingConstructorWithMessageOnly(constructor))) :: - ("message", JString(message)) :: - Nil)) if classOf[Throwable].isAssignableFrom(clazz) => - constructor.newInstance(message) - case ( - TypeInfo(clazz, _), - JObject(("jsonClass", JString(ExceptionClassHavingConstructorWithMessageOnly(constructor))) :: - ("message", JNull) :: - Nil)) if classOf[Throwable].isAssignableFrom(clazz) => - constructor.newInstance(null) - } - - override def serialize(implicit formats: Formats): PartialFunction[Any, JValue] = { - case ExceptionInstanceHavingConstructorWithMessageAndCause(ex) => - JObject( - formats.typeHintFieldName -> JString(ex.getClass.getName), - "message" -> Option(ex.getMessage).map(JString).getOrElse(JNull), - "cause" -> Extraction.decompose(ex.getCause) - ) - case ExceptionInstanceHavingConstructorWithMessageOnly(ex) => - JObject( - formats.typeHintFieldName -> JString(ex.getClass.getName), - "message" -> Option(ex.getMessage).map(JString).getOrElse(JNull) - ) - } -} - - -object ExceptionClassHavingConstructorWithMessageAndCause { - def unapply(className: String): Option[Constructor[Throwable]] = { - (for { - clazz <- Try(Class.forName(className)) - if classOf[Throwable].isAssignableFrom(clazz) - constructor <- constructorWithMessageAndCause(clazz) - } yield constructor).toOption - } - - def constructorWithMessageAndCause(clazz: Class[_]): Try[Constructor[Throwable]] = - Try(clazz.getDeclaredConstructor(classOf[String], classOf[Throwable]).asInstanceOf[Constructor[Throwable]]) -} - -object ExceptionInstanceHavingConstructorWithMessageAndCause { - - def unapply(instance: Throwable): Option[Throwable] = { - ExceptionClassHavingConstructorWithMessageAndCause.constructorWithMessageAndCause(instance.getClass).map(_ => instance).toOption - } - -} - -object ExceptionClassHavingConstructorWithMessageOnly { - def unapply(className: String): Option[Constructor[Throwable]] = { - (for { - clazz <- Try(Class.forName(className)) - if classOf[Throwable].isAssignableFrom(clazz) - constructor <- constructorWithMessageOnly(clazz) - } yield constructor).toOption - } - - def constructorWithMessageOnly(clazz: Class[_]): Try[Constructor[Throwable]] = - Try(clazz.getDeclaredConstructor(classOf[String]).asInstanceOf[Constructor[Throwable]]) -} - -object ExceptionInstanceHavingConstructorWithMessageOnly { - - def unapply(instance: Throwable): Option[Throwable] = { - ExceptionClassHavingConstructorWithMessageOnly.constructorWithMessageOnly(instance.getClass).map(_ => instance).toOption - } - -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/IndexedSeqSerializer.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/IndexedSeqSerializer.scala deleted file mode 100644 index f8adac7..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/IndexedSeqSerializer.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.JsonAST.JArray -import org.json4s._ -import org.json4s.reflect.TypeInfo - -object IndexedSeqSerializer extends Serializer[IndexedSeq[_]] { - def deserialize(implicit format: Formats) = { - case (TypeInfo(clazz, optionalParamType), json) if classOf[IndexedSeq[_]].isAssignableFrom(clazz) => - json match { - case JArray(elems) => - val paramType = optionalParamType.getOrElse(throw new MappingException("Parametrized type not known")) - val elemTypeInfo = TypeInfo(paramType.getActualTypeArguments()(0).asInstanceOf[Class[_]], None) - elems.map(Extraction.extract(_, elemTypeInfo)).toIndexedSeq - case other => - throw new MappingException(s"Can't convert $other to IndexedSeq") - } - } - - def serialize(implicit format: Formats) = { - case seq: IndexedSeq[_] => JArray(seq.map(Extraction.decompose).toList) - } -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/Json4sSerializer.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/Json4sSerializer.scala deleted file mode 100644 index d5f163d..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/Json4sSerializer.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.Formats -import org.json4s.native.Serialization -import rhttpc.transport.{Deserializer, Serializer} - -import scala.util.Try - -class Json4sSerializer[Msg <: AnyRef](implicit formats: Formats) extends Serializer[Msg] { - override def serialize(msg: Msg): String = { - Serialization.write(msg)(formats) - } -} - -class Json4sDeserializer[Msg: Manifest](implicit formats: Formats) extends Deserializer[Msg] { - override def deserialize(value: String): Try[Msg] = { - Try(Serialization.read[Msg](value)) - } -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ObjectSerializer.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ObjectSerializer.scala deleted file mode 100644 index ab74e35..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/ObjectSerializer.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s._ - -import scala.reflect.runtime.universe._ - -object ObjectSerializer extends Serializer[Any] { - private final val ID_FIELD = "jsonObject" - - override def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Any] = { - case (TypeInfo(clazz, _), JObject(List(JField(ID_FIELD, JString(className))))) if clazz.isAssignableFrom(Class.forName(className)) => - val typeMirror = runtimeMirror(ClassLoader.getSystemClassLoader) - val sym = typeMirror.moduleSymbol(Class.forName(className)) - typeMirror.reflectModule(sym).instance - } - - override def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { - case obj if obj.getClass.getName.endsWith("$") => - JObject(ID_FIELD -> JString(obj.getClass.getName)) - } -} \ No newline at end of file diff --git a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/package.scala b/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/package.scala deleted file mode 100644 index 89a68bb..0000000 --- a/rhttpc-json4s/src/main/scala/rhttpc/transport/json4s/package.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport - -import org.json4s.Formats - -package object json4s { - - implicit def serializer[Msg <: AnyRef](implicit formats: Formats): Serializer[Msg] = new Json4sSerializer() - - implicit def deserializer[Msg](implicit formats: Formats): Deserializer[Msg] = new Json4sDeserializer() - -} \ No newline at end of file diff --git a/rhttpc-json4s/src/test/scala/rhttpc/transport/json4s/ExceptionSerializerSpec.scala b/rhttpc-json4s/src/test/scala/rhttpc/transport/json4s/ExceptionSerializerSpec.scala deleted file mode 100644 index d842f20..0000000 --- a/rhttpc-json4s/src/test/scala/rhttpc/transport/json4s/ExceptionSerializerSpec.scala +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.transport.json4s - -import org.json4s.{DefaultFormats, TypeHints} -import org.scalatest.TryValues -import org.scalatest.matchers.should.Matchers -import org.scalatest.flatspec.AnyFlatSpec - -class ExceptionSerializerSpec extends AnyFlatSpec with Matchers with TryValues { - - it should "round-trip serialize case class exception" in { - roundTrip(CaseClassException(123)) - } - - it should "round-trip serialize exception with message" in { - roundTrip(new ExceptionWithMessage("foo")) - } - - it should "round-trip serialize exception with null message" in { - roundTrip(new ExceptionWithMessage(null)) - } - - it should "round-trip serialize exception with message and cause" in { - roundTrip(new ExceptionWithMessageAndCause("foo", CaseClassException(123))) - } - - private def roundTrip(ex: Throwable): Unit = { - implicit val formats = new DefaultFormats { - override val typeHints: TypeHints = AllTypeHints - } + ExceptionSerializer - val serializer = new Json4sSerializer[Throwable]() - val deserializer = new Json4sDeserializer[Throwable]() - val serialized = serializer.serialize(ex) - val deserialized = deserializer.deserialize(serialized) - deserialized.success.value shouldEqual ex - } - -} - -case class CaseClassException(x: Int) extends Exception(s"x: $x") - -class ExceptionWithMessage(msg: String) extends Exception(msg) { - def canEqual(other: Any): Boolean = other.isInstanceOf[ExceptionWithMessage] - - override def equals(other: Any): Boolean = other match { - case that: ExceptionWithMessage => - (that canEqual this) && - getMessage == that.getMessage - case _ => false - } - - override def hashCode(): Int = { - val state = Seq(getMessage) - state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b) - } -} - -class ExceptionWithMessageAndCause(msg: String, cause: Throwable) extends Exception(msg, cause) { - def canEqual(other: Any): Boolean = other.isInstanceOf[ExceptionWithMessageAndCause] - - override def equals(other: Any): Boolean = other match { - case that: ExceptionWithMessageAndCause => - (that canEqual this) && - getMessage == that.getMessage && - getCause == that.getCause - case _ => false - } - - override def hashCode(): Int = { - val state = Seq(getMessage, getCause) - state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b) - } -} \ No newline at end of file diff --git a/rhttpc-transport/src/main/scala/rhttpc/transport/PubSubTransport.scala b/rhttpc-transport/src/main/scala/rhttpc/transport/PubSubTransport.scala index 417155b..b9cccad 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/transport/PubSubTransport.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/transport/PubSubTransport.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport -import akka.actor.ActorRef +import org.apache.pekko.actor.ActorRef import scala.concurrent.{ExecutionContext, Future} import scala.util.Try diff --git a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackPublisher.scala b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackPublisher.scala index a4b2616..a0ea938 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackPublisher.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackPublisher.scala @@ -15,8 +15,8 @@ */ package rhttpc.transport.fallback -import akka.actor.{ActorSystem, Scheduler} -import akka.pattern.CircuitBreaker +import org.apache.pekko.actor.{ActorSystem, Scheduler} +import org.apache.pekko.pattern.CircuitBreaker import org.slf4j.LoggerFactory import rhttpc.transport.{Message, Publisher} diff --git a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackTransport.scala b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackTransport.scala index 9247eb3..e105f1b 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackTransport.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/FallbackTransport.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport.fallback -import akka.actor.{ActorRef, ActorSystem} +import org.apache.pekko.actor.{ActorRef, ActorSystem} import rhttpc.transport._ import scala.concurrent.Future diff --git a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/package.scala b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/package.scala index 333a4a3..21173cc 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/package.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/transport/fallback/package.scala @@ -15,7 +15,7 @@ */ package rhttpc.transport -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem import scala.concurrent.duration.FiniteDuration diff --git a/rhttpc-transport/src/main/scala/rhttpc/utils/Agent.scala b/rhttpc-transport/src/main/scala/rhttpc/utils/Agent.scala index 73eda04..49a7b15 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/utils/Agent.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/utils/Agent.scala @@ -50,7 +50,7 @@ object Agent { def alterOff(f: T => T)(implicit ec: ExecutionContext): Future[T] = { val result = Promise[T]() withinTransaction(new Runnable { - def run = { + def run() = { updater.suspend() result.completeWith( Future(try ref.single.transformAndGet(f) diff --git a/rhttpc-transport/src/main/scala/rhttpc/utils/SerializedSuspendableExecutionContext.scala b/rhttpc-transport/src/main/scala/rhttpc/utils/SerializedSuspendableExecutionContext.scala index c8a9d01..b1b155f 100644 --- a/rhttpc-transport/src/main/scala/rhttpc/utils/SerializedSuspendableExecutionContext.scala +++ b/rhttpc-transport/src/main/scala/rhttpc/utils/SerializedSuspendableExecutionContext.scala @@ -10,7 +10,7 @@ import scala.annotation.{ switch, tailrec } import scala.concurrent.ExecutionContext import scala.util.control.NonFatal -import akka.dispatch.AbstractNodeQueue +import org.apache.pekko.dispatch.AbstractNodeQueue private[utils] object SerializedSuspendableExecutionContext { final val Off = 0 diff --git a/rhttpc-transport/src/test/scala/rhttpc/transport/DelayedMessageSpec.scala b/rhttpc-transport/src/test/scala/rhttpc/transport/DelayedMessageSpec.scala index 13289e8..fb0452f 100644 --- a/rhttpc-transport/src/test/scala/rhttpc/transport/DelayedMessageSpec.scala +++ b/rhttpc-transport/src/test/scala/rhttpc/transport/DelayedMessageSpec.scala @@ -23,10 +23,18 @@ import scala.concurrent.duration._ class DelayedMessageSpec extends AnyFlatSpec with Matchers { it should "extract delayed message from properties in various numeric formats" in { - val DelayedMessage(_, fromLongDuration, _, _) = Message("fooMsg", Map(MessagePropertiesNaming.delayProperty -> 100L)) - fromLongDuration shouldEqual (100 millis) - val DelayedMessage(_, fromIntDuration, _, _) = Message("fooMsg", Map(MessagePropertiesNaming.delayProperty -> 100)) - fromIntDuration shouldEqual (100 millis) + Message("fooMsg", Map(MessagePropertiesNaming.delayProperty -> 100L)) match { + case DelayedMessage(_, fromLongDuration, _, _) => + fromLongDuration shouldEqual (100 millis) + case _ => + fail("Not a delayed message") + } + Message("fooMsg", Map(MessagePropertiesNaming.delayProperty -> 100)) match { + case DelayedMessage(_, fromIntDuration, _, _) => + fromIntDuration shouldEqual (100 millis) + case _ => + fail("Not a delayed message") + } } } \ No newline at end of file diff --git a/sample/sample-app/src/main/resources/application.conf b/sample/sample-app/src/main/resources/application.conf deleted file mode 100644 index 37005bc..0000000 --- a/sample/sample-app/src/main/resources/application.conf +++ /dev/null @@ -1,40 +0,0 @@ -akka { - loglevel = "DEBUG" - loggers = ["akka.event.slf4j.Slf4jLogger"] - event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" - - log-dead-letters = on - - persistence { - journal { - plugin = "akka.persistence.journal.leveldb" - leveldb.native = off - } - - snapshot-store { - plugin = "akka.persistence.snapshot-store.local" - local.dir = "/akka-persistence" - } - } - - stream { - materializer { - subscription-timeout { - timeout = 30s - } - } - } -} - -amqp { - hosts = ["rabbitmq"] -} - -rhttpc { - retryStrategy { - initialDelay = 5 seconds - multiplier = 1.0 - maxRetries = 3 - } -} \ No newline at end of file diff --git a/sample/sample-app/src/main/resources/logback.xml b/sample/sample-app/src/main/resources/logback.xml deleted file mode 100644 index 3f094db..0000000 --- a/sample/sample-app/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - diff --git a/sample/sample-app/src/main/scala/rhttpc/sample/DelayedEchoClient.scala b/sample/sample-app/src/main/scala/rhttpc/sample/DelayedEchoClient.scala deleted file mode 100644 index 9ef0357..0000000 --- a/sample/sample-app/src/main/scala/rhttpc/sample/DelayedEchoClient.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.sample - -import rhttpc.client.subscription.ReplyFuture - -import scala.concurrent.ExecutionContext - -trait DelayedEchoClient { - def requestResponse(msg: String): ReplyFuture -} \ No newline at end of file diff --git a/sample/sample-app/src/main/scala/rhttpc/sample/FooBarActor.scala b/sample/sample-app/src/main/scala/rhttpc/sample/FooBarActor.scala deleted file mode 100644 index a39cb2c..0000000 --- a/sample/sample-app/src/main/scala/rhttpc/sample/FooBarActor.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.sample - -import akka.actor._ -import akka.http.scaladsl.model.{HttpEntity, HttpResponse} -import rhttpc.akkapersistence.ReliableFSM -import rhttpc.client.subscription.SubscriptionManager - -import scala.concurrent.duration._ - -private class FooBarActor(protected val id: String, protected val subscriptionManager: SubscriptionManager, client: DelayedEchoClient) extends ReliableFSM[FooBarState, FooBarData] { - import context.dispatcher - - override protected def persistenceCategory: String = FooBarActor.persistenceCategory - - startWith(InitState, EmptyData) - - when(InitState) { - case Event(SendMsg(msg), _) => - client.requestResponse(msg) pipeTo this - goto(WaitingForResponseState) replyingAfterSave() - } - - when(WaitingForResponseState) { - case Event(httpResponse: HttpResponse, _) => - self forward httpResponse.entity.asInstanceOf[HttpEntity.Strict].data.utf8String - stay() - case Event("foo", _) => goto(FooState).acknowledgingAfterSave() - case Event("bar", _) => goto(BarState).acknowledgingAfterSave() - } - - when(FooState, stateTimeout = 5 minutes) { - case Event(StateTimeout, _) => stop() - } - - when(BarState, stateTimeout = 5 minutes) { - case Event(StateTimeout, _) => stop() - } - - whenUnhandled { - case Event(CurrentState, _) => - sender() ! stateName - stay() - case Event(StopYourself, _) => - stop() - } -} - -object FooBarActor { - val persistenceCategory = "foobar" - - def props(id: String, subscriptionManager: SubscriptionManager, client: DelayedEchoClient): Props = Props(new FooBarActor(id, subscriptionManager, client)) -} - -sealed trait FooBarState - -case object InitState extends FooBarState -case object WaitingForResponseState extends FooBarState -case object FooState extends FooBarState -case object BarState extends FooBarState - -sealed trait FooBarData - -case object EmptyData extends FooBarData - -case class SendMsg(msg: String) -case object CurrentState -case object StopYourself \ No newline at end of file diff --git a/sample/sample-app/src/main/scala/rhttpc/sample/SampleApp.scala b/sample/sample-app/src/main/scala/rhttpc/sample/SampleApp.scala deleted file mode 100644 index 2d14273..0000000 --- a/sample/sample-app/src/main/scala/rhttpc/sample/SampleApp.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.sample - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.model._ -import akka.http.scaladsl.server._ -import akka.pattern._ -import akka.util.Timeout -import rhttpc.akkahttp.ReliableHttpClientFactory -import rhttpc.akkapersistence.{RecoverAllActors, RecoverableActorsManager, SendMsgToChild} -import rhttpc.client.subscription.ReplyFuture - -import scala.concurrent.Await -import scala.concurrent.duration._ -import scala.language.reflectiveCalls - -object SampleApp extends App with Directives { - implicit val system = ActorSystem("rhttpc-sample") - implicit val materializer = akka.stream.Materializer.matFromSystem - import system.dispatcher - - val rhttpc = Await.result(ReliableHttpClientFactory().withOwnAmqpConnection.inOutWithSubscriptions(), 20 seconds) - - val client = new DelayedEchoClient { - override def requestResponse(msg: String): ReplyFuture = { - rhttpc.send(HttpRequest().withUri("http://sampleecho:8082").withMethod(HttpMethods.POST).withEntity(msg)) - } - } - - val manager = system.actorOf(RecoverableActorsManager.props( - FooBarActor.persistenceCategory, - id => FooBarActor.props(id, rhttpc.subscriptionManager, client) - ), "foobar") - - Await.result((manager ? RecoverAllActors)(Timeout(20 seconds)), 15 seconds) - - rhttpc.start() - - val route = - path("healthcheck") { - get { - complete("OK") - } - } ~ - path(Segment) { id => - (post & entity(as[String])) { msg => - complete { - implicit val sendMsgTimeout = Timeout(5 seconds) - (manager ? SendMsgToChild(id, SendMsg(msg))).map(_ => "OK") - } - } ~ - get { - complete { - implicit val currentStateTimeout = Timeout(5 seconds) - (manager ? SendMsgToChild(id, CurrentState)).mapTo[FooBarState].map(_.toString) - } - } - } - - Http().newServerAt(interface = "0.0.0.0", port = 8081).bind(route).map { binding => - Runtime.getRuntime.addShutdownHook(new Thread { - override def run(): Unit = { - Await.result(rhttpc.stop(), 10 seconds) - } - }) - } -} diff --git a/sample/sample-app/src/test/scala/rhttpc/sample/FooBarActorSpec.scala b/sample/sample-app/src/test/scala/rhttpc/sample/FooBarActorSpec.scala deleted file mode 100644 index 4dae6c1..0000000 --- a/sample/sample-app/src/test/scala/rhttpc/sample/FooBarActorSpec.scala +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.sample - -import java.util.concurrent.atomic.AtomicInteger -import akka.actor._ -import akka.testkit._ -import org.scalatest._ -import org.scalatest.flatspec.AnyFlatSpecLike -import rhttpc.akkapersistence.{ActorsRecovered, RecoverAllActors, RecoverableActorsManager, SendMsgToChild, StateSaved} - -import scala.concurrent.duration._ -import scala.reflect.io.Directory - -class FooBarActorSpec extends TestKit(ActorSystem()) with ImplicitSender with AnyFlatSpecLike with BeforeAndAfterAll { - import system.dispatcher - - // FIXME: tests doesn't pass on circle-ci - ignore should "be in init state initially" in withNextFooBar { fooBarActor => - fooBarActor ! CurrentState - expectMsg(InitState) - } - - ignore should "go into waiting state after send msg command" in withNextFooBar { fooBarActor => - fooBarActor ! SendMsg("foo") - fooBarActor ! CurrentState - expectMsg(WaitingForResponseState) - } - - ignore should "go into foo state after echo response" in withNextFooBar { fooBarActor => - TestProbe().send(fooBarActor, SendMsg("foo")) - val scheduled = system.scheduler.scheduleAtFixedRate(0.millis, 100.millis, fooBarActor, CurrentState) - fishForMessage(10 seconds) { - case WaitingForResponseState => false - case FooState => true - } - scheduled.cancel() - } - - ignore should "restore persited waiting state and continue with response" in { - val id = "persisted" - val fooBarActor = createFooBar(id) - fooBarActor ! SendMsg("foo") - expectMsg(10 seconds, StateSaved) - - watch(fooBarActor) - fooBarActor ! PoisonPill - expectTerminated(fooBarActor) - - val restoredActor = createFooBar(id) - restoredActor ! CurrentState - expectMsg(WaitingForResponseState) - restoredActor ! "foo" - restoredActor ! CurrentState - expectMsg(FooState) - gracefulStop(restoredActor) - } - - // FIXME: manager is not killed, from time to time there is bad state of foobar - ignore should "restore persisted actors just after manager init" in { - (0 to 9).foreach { i => - val mgr = createFooBarManager() - - val id = s"saved_$i" - mgr ! SendMsgToChild(id, SendMsg("foo")) - expectMsg(10 seconds, StateSaved) - - watch(mgr) - mgr ! PoisonPill - expectTerminated(mgr) - - val restoredMgr = createFooBarManager() - restoredMgr ! SendMsgToChild(id, CurrentState) - expectMsg(WaitingForResponseState) - restoredMgr ! SendMsgToChild(id, "foo") - expectMsg(StateSaved) - restoredMgr ! SendMsgToChild(id, CurrentState) - expectMsg(FooState) - - watch(restoredMgr) - mgr ! PoisonPill - expectTerminated(restoredMgr, 10 seconds) - } - () - } - - val id = new AtomicInteger(0) - - def withNextFooBar(test: ActorRef => Unit) = { - val fooBarACtor = createFooBar(id.getAndIncrement().toString) - test(fooBarACtor) - gracefulStop(fooBarACtor) - } - - def gracefulStop(fooBarActor: ActorRef): Unit = { - watch(fooBarActor) - fooBarActor ! StopYourself - expectTerminated(fooBarActor) - } - - def createFooBar(id: String): ActorRef = { - val client = new InMemDelayedEchoClient(3 second) - system.actorOf(FooBarActor.props(id.toString, client.subscriptionManager, client), "foobar-" + id) - } - - def createFooBarManager(): ActorRef = { - val client = new InMemDelayedEchoClient(3 second) - val ref = system.actorOf(RecoverableActorsManager.props( - FooBarActor.persistenceCategory, - id => FooBarActor.props(id, client.subscriptionManager, client) - ), FooBarActor.persistenceCategory) - ref ! RecoverAllActors - expectMsg(ActorsRecovered) - ref - } - - override protected def beforeAll(): Unit = { - Directory("snapshots").deleteRecursively() - Directory("journal").deleteRecursively() - } - - override protected def afterAll(): Unit = { - shutdown() - } -} diff --git a/sample/sample-app/src/test/scala/rhttpc/sample/InMemDelayedEchoClient.scala b/sample/sample-app/src/test/scala/rhttpc/sample/InMemDelayedEchoClient.scala deleted file mode 100644 index a6713a1..0000000 --- a/sample/sample-app/src/test/scala/rhttpc/sample/InMemDelayedEchoClient.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rhttpc.sample - -import java.util.UUID - -import akka.actor.{ActorRef, ActorSystem} -import akka.util.Timeout -import rhttpc.client.subscription._ - -import scala.concurrent.duration.FiniteDuration -import scala.concurrent.{ExecutionContext, Future} - -class InMemDelayedEchoClient(delay: FiniteDuration)(implicit system: ActorSystem) extends DelayedEchoClient { - import system.dispatcher - - private val subOnMsg: collection.concurrent.Map[SubscriptionOnResponse, String] = collection.concurrent.TrieMap() - - val subscriptionManager: SubscriptionManager = - new SubscriptionManager { - - override def confirmOrRegister(subscription: SubscriptionOnResponse, consumer: ActorRef): Unit = { - system.scheduler.scheduleOnce(delay) { - subOnMsg.remove(subscription).foreach { msg => - consumer ! msg - } - } - } - - override def start(): Unit = {} - - override def stop(): Future[Unit] = Future.unit - } - - override def requestResponse(msg: String): ReplyFuture = { - val uniqueSubOnResponse = SubscriptionOnResponse(UUID.randomUUID().toString) - subOnMsg.put(uniqueSubOnResponse, msg) - new ReplyFuture { - override def pipeTo(listener: PublicationListener) - (implicit ec: ExecutionContext): Unit = { - listener.subscriptionPromiseRegistered(uniqueSubOnResponse) - listener.self ! RequestPublished(uniqueSubOnResponse) - } - - override def toFuture(implicit system: ActorSystem, timeout: Timeout): Future[Any] = ??? - } - } -} \ No newline at end of file diff --git a/sample/sample-echo/src/main/resources/application.conf b/sample/sample-echo/src/main/resources/application.conf index 53cd603..ffdb248 100644 --- a/sample/sample-echo/src/main/resources/application.conf +++ b/sample/sample-echo/src/main/resources/application.conf @@ -1,8 +1,8 @@ akka { loglevel = "DEBUG" - loggers = ["akka.event.slf4j.Slf4jLogger"] - event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger"] + event-handlers = ["org.apache.pekko.event.slf4j.Slf4jEventHandler"] + logging-filter = "org.apache.pekko.event.slf4j.Slf4jLoggingFilter" log-dead-letters = on diff --git a/sample/sample-echo/src/main/scala/rhttpc/echo/EchoApp.scala b/sample/sample-echo/src/main/scala/rhttpc/echo/EchoApp.scala index c194842..ded4dab 100644 --- a/sample/sample-echo/src/main/scala/rhttpc/echo/EchoApp.scala +++ b/sample/sample-echo/src/main/scala/rhttpc/echo/EchoApp.scala @@ -15,23 +15,24 @@ */ package rhttpc.echo -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem import rhttpc.utils.Agent -import akka.http.scaladsl.Http -import akka.http.scaladsl.server._ -import akka.pattern._ -import com.github.ghik.silencer.silent +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.server._ +import org.apache.pekko.pattern._ +import org.apache.pekko.stream.Materializer +import scala.annotation.nowarn import scala.concurrent.Future import scala.concurrent.duration._ object EchoApp extends App with Directives { - implicit val system = ActorSystem("rhttpc-echo") - implicit val materializer = akka.stream.Materializer.matFromSystem + implicit val system: ActorSystem = ActorSystem("rhttpc-echo") + implicit val materializer: Materializer = org.apache.pekko.stream.Materializer.matFromSystem import system.dispatcher - @silent val retryAgent = Agent(Map.empty[String, Int]) + @nowarn val retryAgent = Agent(Map.empty[String, Int]) val route = (post & entity(as[String])) { case request@FailNTimesThanReplyWithMessage(failsCount, eventualMessage) => @@ -68,7 +69,7 @@ object EchoApp extends App with Directives { object FailNTimesThanReplyWithMessage { - private val Regex = "fail-(\\d*)-times-than-reply-with-(.*)".r("failsCount", "eventualMessage") + @nowarn private val Regex = "fail-(\\d*)-times-than-reply-with-(.*)".r("failsCount", "eventualMessage") def unapply(str: String): Option[(Int, String)] = str match { case Regex(failsCount, eventualMessage) => Some(failsCount.toInt, eventualMessage) diff --git a/sample/sample-echo/src/test/scala/rhttpc/echo/FailNTimesThanReplyWithMessageSpec.scala b/sample/sample-echo/src/test/scala/rhttpc/echo/FailNTimesThanReplyWithMessageSpec.scala index dfb9e8a..34bac8f 100644 --- a/sample/sample-echo/src/test/scala/rhttpc/echo/FailNTimesThanReplyWithMessageSpec.scala +++ b/sample/sample-echo/src/test/scala/rhttpc/echo/FailNTimesThanReplyWithMessageSpec.scala @@ -15,15 +15,19 @@ */ package rhttpc.echo -import org.scalatest.matchers.should.Matchers import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers class FailNTimesThanReplyWithMessageSpec extends AnyFlatSpec with Matchers { it should "recognize pattern" in { - val FailNTimesThanReplyWithMessage(count, message) = "fail-3-times-than-reply-with-foo" - count shouldEqual 3 - message shouldEqual "foo" + "fail-3-times-than-reply-with-foo" match { + case FailNTimesThanReplyWithMessage(count, message) => + count shouldEqual 3 + message shouldEqual "foo" + case _ => + fail("Not a FailNTimesThanReplyWithMessage") + } } } \ No newline at end of file diff --git a/sample/test/src/test/scala/rhttpc/test/FooBarClient.scala b/sample/test/src/test/scala/rhttpc/test/FooBarClient.scala index d7bbd1f..3f8f7ba 100644 --- a/sample/test/src/test/scala/rhttpc/test/FooBarClient.scala +++ b/sample/test/src/test/scala/rhttpc/test/FooBarClient.scala @@ -15,12 +15,13 @@ */ package rhttpc.test +import dispatch.retry.Success import dispatch.{Future => DispatchFuture, _} import scala.concurrent._ class FooBarClient(baseUrl: => Req) { - implicit val successPredicate = new retry.Success[Unit.type](_ => true) + implicit val successPredicate: Success[Unit.type] = new retry.Success[Unit.type](_ => true) private val httpClient = Http.default .closeAndConfigure( diff --git a/sample/test/src/test/scala/rhttpc/test/HttpProbe.scala b/sample/test/src/test/scala/rhttpc/test/HttpProbe.scala index e1e312f..c0350c5 100644 --- a/sample/test/src/test/scala/rhttpc/test/HttpProbe.scala +++ b/sample/test/src/test/scala/rhttpc/test/HttpProbe.scala @@ -18,7 +18,7 @@ package rhttpc.test import dispatch._ import dispatch.Defaults.timer import org.asynchttpclient.DefaultAsyncHttpClientConfig - +import java.time.Duration import scala.concurrent._ import scala.concurrent.duration._ import scala.util.control.NonFatal @@ -26,8 +26,9 @@ import scala.util.control.NonFatal case class HttpProbe(urlStr: String) { private val httpClient = new Http( new DefaultAsyncHttpClientConfig.Builder() - .setConnectTimeout(500) - .setRequestTimeout(500)) + .setConnectTimeout(Duration.ofMillis(500)) + .setRequestTimeout(Duration.ofMillis(500)) + ) def await(atMostSeconds: Int = 15)(implicit ec: ExecutionContext) = { val future = retry.Pause(max = atMostSeconds * 2) { () => // default delay is 0,5 sec diff --git a/version.sbt b/version.sbt index 1b9f6b1..12dd689 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.11.1-SNAPSHOT" +version in ThisBuild := "0.12.0-SNAPSHOT"