Spray.can.Http $ ConnectionException: abort connection close

In my testing below, I tried to simulate a timeout and then send a normal request. however, I got spray.can.Http $ ConnectionException: closing the connection prematurely (the server does not seem to support pipelining the request)

class SprayCanTest extends ModuleTestKit("/SprayCanTest.conf") with FlatSpecLike with Matchers { import system.dispatcher var app = Actor.noSender protected override def beforeAll(): Unit = { super.beforeAll() app = system.actorOf(Props(new MockServer)) } override protected def afterAll(): Unit = { system.stop(app) super.afterAll() } "response time out" should "work" in { val setup = Http.HostConnectorSetup("localhost", 9101, false) connect(setup).onComplete { case Success(conn) => { conn ! HttpRequest(HttpMethods.GET, "/timeout") } } expectMsgPF() { case Status.Failure(t) => t shouldBe a[RequestTimeoutException] } } "normal http response" should "work" in { //Thread.sleep(5000) val setup = Http.HostConnectorSetup("localhost", 9101, false) connect(setup).onComplete { case Success(conn) => { conn ! HttpRequest(HttpMethods.GET, "/hello") } } expectMsgPF() { case HttpResponse(status, entity, _, _) => status should be(StatusCodes.OK) entity should be(HttpEntity("Helloworld")) } } def connect(setup: HostConnectorSetup)(implicit system: ActorSystem) = { // for the actor 'asks' import system.dispatcher implicit val timeout: Timeout = Timeout(1 second) (IO(Http) ? setup) map { case Http.HostConnectorInfo(connector, _) => connector } } class MockServer extends Actor { //implicit val timeout: Timeout = 1.second implicit val system = context.system // Register connection service IO(Http) ! Http.Bind(self, interface = "localhost", port = 9101) def receive: Actor.Receive = { case _: Http.Connected => sender ! Http.Register(self) case HttpRequest(GET, Uri.Path("/timeout"), _, _, _) => { Thread.sleep(3000) sender ! HttpResponse(entity = HttpEntity("ok")) } case HttpRequest(GET, Uri.Path("/hello"), _, _, _) => { sender ! HttpResponse(entity = HttpEntity("Helloworld")) } } } } 

and My config for the test:

 spray { can { client { response-chunk-aggregation-limit = 0 connecting-timeout = 1s request-timeout = 1s } host-connector { max-retries = 0 } } } 

I found that in both cases the "conn" object is the same. Thus, I assume that when a RequestTimeoutException occurs, the spray returned the connection to the pool (default 4?), And in the following case it will use the same contact, but this connection is maintained at this time, so the server will treat it as the requested request .

If I sleep in the second case, it just goes away. Therefore, I assume that I should close the connection when I receive a RequestTimeoutException and make sure that in the second case a new new connection is used, right?

How do i do Any configurations?

thanks

Leon

+5
source share
1 answer

You should not block yourself in the Actor (your MockServer). When it is locked, it cannot reply to any messages. You can wrap Thread.sleep and the answer inside the Future. Or even better: use Akka Scheduler . Be sure to set the sender to val because it can change when you respond to the request asynchronously. This should do the trick:

 val savedSender = sender() context.system.scheduler.scheduleOnce(3 seconds){ savedSender ! HttpResponse(entity = HttpEntity("ok")) } 
+5
source

Source: https://habr.com/ru/post/1202643/


All Articles