[英]Best way to sequence a pair of external service calls in Akka
我需要對一個Address對象進行地理編碼,然后將更新后的Address存儲在搜索引擎中。 這可以簡化為獲取一個對象,對該對象執行一項長時間運行的操作,然后保留該對象。 這意味着有一個操作順序要求在持久性發生之前完成第一個操作。
我想使用Akka將其移出執行主線程。
我最初的想法是使用一對Future來完成此操作,但是Future文檔並不完全清楚哪種行為(折疊,映射等)可以保證一個Future在另一個行為之前執行。
我首先創建了兩個函數defferedGeocode
和deferredWriteToSearchEngine
,它們分別為相應的操作返回Futures。 我使用Future<>.andThen(new OnComplete...)
它們鏈接在一起,但這很快就變得笨拙:
Future<Address> geocodeFuture = defferedGeocode(ec, address);
geocodeFuture.andThen(new OnComplete<Address>() {
public void onComplete(Throwable failure, Address geocodedAddress) {
if (geocodedAddress != null) {
Future<Address> searchEngineFuture = deferredWriteToSearchEngine(ec, addressSearchService, geocodedAddress);
searchEngineFuture.andThen(new OnComplete<Address>() {
public void onComplete(Throwable failure, Address savedAddress) {
// process search engine results
}
});
}
}
}, ec);
然后像這樣實現deferredGeocode
:
private Future<Address> defferedGeocode(
final ExecutionContext ec,
final Address address) {
return Futures.future(new Callable<Address>() {
public Address call() throws Exception {
log.debug("Geocoding Address...");
return address;
}
}, ec);
};
deferredWriteToSearchEngine
是相當類似deferredGeocode
,不同的是它的搜索引擎服務作為額外的最后一個參數。
我的理解是,應該將期貨用於執行計算,並且不應有副作用。 在這種情況下,對地址進行地理編碼是計算,因此我認為使用Future是合理的,但寫入搜索引擎絕對是副作用。
Akka的最佳做法是什么? 如何避免所有嵌套的調用,但要確保地理編碼和搜索引擎的寫操作都在主線程之外完成?
有沒有更合適的工具?
更新:
根據以下Viktor的評論,我正在嘗試以下代碼:
ExecutionContext ec;
private Future<Address> addressBackgroundProcess(Address address) {
Future<Address> geocodeFuture = addressGeocodeFutureFactory.defferedGeocode(address);
return geocodeFuture.flatMap(new Mapper<Address, Future<Address>>() {
@Override
public Future<Address> apply(Address geoAddress) {
return addressSearchEngineFutureFactory.deferredWriteToSearchEngine(geoAddress);
}
}, ec);
}
除了一個我不感到興奮的問題,這似乎還可以。 我們正在Spring IOC代碼庫中工作,因此我想將ExecutionContext注入到FutureFactory對象中,但是此功能(在我們的DAO中)需要了解ExecutionContext似乎是錯誤的。
在我看來,flatMap()函數完全需要EC,因為兩個期貨都提供了EC。
有沒有辦法保持關注點分離? 我是否對代碼進行了錯誤的構造,或者這僅僅是它所需要的方式嗎?
我考慮過在FutureFactory的接口中創建一個允許鏈接FutureFactory的接口,因此flatMap()調用將封裝在FutureFactory的基類中,但這似乎有意破壞了故意的Akka設計決策。
警告:偽代碼前面。
Future<Address> myFutureResult = deferredGeocode(ec, address).flatMap(
new Mapper<Address, Future<Address>>() {
public Future<Address> apply(Address geocodedAddress) {
return deferredWriteToSearchEngine(ec, addressSearchService, geocodedAddress);
}
}, ec).map(
new Mapper<Address, SomeResult>() {
public SomeResult apply(Address savedAddress) {
// Create SomeResult after deferredWriteToSearchEngine is done
}
}, ec);
看看它是不是嵌套的。 flatMap和map用於對操作進行排序。 當您希望僅將副作用操作運行到傳遞結果之前完全完成時,“ andThen”很有用。 當然,如果您在SAME future-instance上映射兩次,則無法保證訂購,但是由於我們是flatMapping並映射了返回的期貨(根據文檔為新期貨),因此程序中存在清晰的數據流。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.