2014-09-16 49 views
5

Aşağıdaki testimde bir zaman aşımını simüle etmeye çalıştım ve ardından normal bir istek gönderdim. ancak, spray.can.Http $ ConnectionException var: bunu buldum

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

: Erken bağlantı kapatma

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")) 
     } 
    } 
    } 


} 

ve test için My yapılandırma (sunucu isteği borulama desteklemek için görünmüyor) Her iki durumda da, "conn" nesnesi aynıdır. Yani RequestTimeoutException gerçekleştiğinde, sprey havuzu (arkadaki 4 varsayılan olarak) geri koymak ve sonraki durumda aynı bağlantıyı kullanacağız, ancak bu anda, bu bağlantı canlı tutulur, bu yüzden sunucu yığılmış olarak davranır sanırım istek.

İkinci durumda biraz uyku yaparsam, sadece geçecek. Bu yüzden RequestTimeoutException geldiğinde bağlantıyı kapatmalı ve ikinci davanın yeni bir bağlantı kullandığından emin olmalıyım, değil mi?

Nasıl yapmalıyım? Herhangi bir konfigürasyon var mı?

Teşekkür

Leon

cevap

5

Bir Aktör (sizin MockServer) içine engellememelidir. Engellendiğinde, herhangi bir mesaja cevap veremez. Thread.sleep ve yanıtı bir Geleceğin içine sarabilirsiniz. Veya daha da iyisi: Akka Scheduler'u kullanın. Göndereni bir zamana atadığınızdan, isteğinize uyumsuz olarak yanıt verdiğinizde değişebileceğinden emin olun. Bu hile:

+0

ah, benim hatam, aktörün tek iş parçacığı davranışını unutun :) Dikkat ettiğin için teşekkürler! – anuni

+0

hey! çok benzer bir sorunu olan ama oyuncuyu engellemiyorum .. ne olabilir acaba: https://stackoverflow.com/questions/29397293/how-to-fix-the-dropping-close-since- -ssl-bağlantı-is-zaten-kapama hatası – mayacr86