Có một vài câu hỏi tôi có thể thấy ở đây dựa trên các câu hỏi trong mẫu mã của bạn:
Tôi có thể làm gì loại của sự vật khi tôi ghi đè lên các hành vi giám sát mặc định trong định nghĩa của làm thế nào để xử lý ngoại lệ?
Khi sử dụng ask
, tôi có thể làm gì khi nhận được kết quả Failure
trên số Future
mà tôi đang đợi?
Hãy bắt đầu với câu hỏi đầu tiên trước (thường là ý tưởng hay). Khi bạn ghi đè chiến lược giám sát mặc định, bạn có khả năng thay đổi cách một số loại ngoại lệ không được giải quyết trong diễn viên con được xử lý liên quan đến việc phải làm gì với diễn viên con không thành công đó. Từ khóa trong câu trước đó là unhandled
. Đối với các tác nhân đang thực hiện yêu cầu/phản hồi, bạn có thể thực sự muốn xử lý (bắt) các ngoại lệ cụ thể và trả về các kiểu phản hồi nhất định (hoặc thất bại tương lai ngược dòng, nhiều hơn về sau) thay vì để chúng không được giải quyết. Khi một ngoại lệ không được giải quyết xảy ra, về cơ bản bạn sẽ mất khả năng trả lời người gửi với mô tả về vấn đề và người gửi có thể sẽ nhận được TimeoutException
thay vì Future
của họ sẽ không bao giờ được hoàn thành. Khi bạn đã tìm ra những gì bạn xử lý một cách rõ ràng, bạn có thể xem xét tất cả các trường hợp ngoại lệ còn lại khi xác định chiến lược giám sát tùy chỉnh của bạn. Bên trong khối này ở đây:
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
case x: Exception => ???
}
Bạn nhận được một cơ hội để ánh xạ một loại ngoại lệ đối với một thất bại Directive
, trong đó xác định như thế nào sự thất bại sẽ bị xử lý từ một quan điểm giám sát.Các tùy chọn là:
Stop - Hoàn toàn ngăn chặn các diễn viên nhí và không gửi bất kỳ tin nhắn nhiều đến nó
Chạy lại - Resume đứa trẻ thất bại, không khởi động lại vì thế nó giữ trạng thái nội bộ hiện tại của nó
Restart - tương tự để tiếp tục, nhưng trong trường hợp này, ví dụ cũ phải ném ra ngoài một trường hợp mới được xây dựng và tình trạng nội bộ được thiết lập lại (preStart)
leo thang - leo thang lên chuỗi để cha mẹ của người giám sát
Vì vậy, chúng ta hãy nói rằng đưa một SQLException
bạn muốn tiếp tục và cho tất cả những người khác bạn muốn khởi động lại sau đó mã của bạn sẽ trông như thế này:
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
case x: SQLException => Resume
case other => Restart
}
Bây giờ cho câu hỏi thứ hai liên quan đến việc cần làm khi bản thân số Future
trả về phản hồi Failure
. Trong trường hợp này, tôi đoán nó phụ thuộc vào những gì được cho là sẽ xảy ra do kết quả của Future
. Nếu diễn viên còn lại tự chịu trách nhiệm hoàn thành các yêu cầu http (giả sử rằng httpCtx có chức năng complete(statusCode:Int, message:String)
trên đó), sau đó bạn có thể làm một cái gì đó như thế này:
ask(dbActor, ReadCommand(reqCtx, id)).mapTo[SomeObject] onComplete {
case Success(obj) => reqCtx.complete(200, "All good!")
case Failure(err:TimeoutException) => reqCtx.complete(500, "Request timed out")
case Failure(ex) => reqCtx.complete(500, ex.getMessage)
}
Bây giờ nếu diễn viên khác ở thượng nguồn chịu trách nhiệm hoàn thành yêu cầu http và bạn cần thiết để ứng phó với diễn viên đó, bạn có thể làm một cái gì đó như thế này:
val origin = sender
ask(dbActor, ReadCommand(reqCtx, id)).mapTo[SomeObject] onComplete {
case Success(obj) => origin ! someResponseObject
case Failure(ex) => origin ! Status.Failure(ex)
}
phương pháp này giả định rằng trong khối thành công lần đầu tiên bạn muốn để xoa bóp các đối tượng kết quả trước khi trả lời. Nếu bạn không muốn làm điều đó và bạn muốn trì hoãn việc xử lý kết quả cho người gửi thì bạn chỉ có thể làm:
val origin = sender
val fut = ask(dbActor, ReadCommand(reqCtx, id))
fut pipeTo origin
Tôi nghĩ rằng tôi nhận được nó, chìa khóa thực sự ở đây là để hiểu những gì là unhandled – graph1ZzLle