Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Akka中对一对外部服务调用进行排序的最佳方法_Java_Spring_Concurrency_Akka_Future - Fatal编程技术网

Java 在Akka中对一对外部服务调用进行排序的最佳方法

Java 在Akka中对一对外部服务调用进行排序的最佳方法,java,spring,concurrency,akka,future,Java,Spring,Concurrency,Akka,Future,我需要对地址对象进行地理编码,然后将更新后的地址存储在搜索引擎中。这可以简化为获取一个对象,对该对象执行一个长时间运行的操作,然后持久化该对象。这意味着有一个操作顺序要求第一个操作在持久化发生之前完成 我想用Akka把它从执行的主线上移开 我最初的想法是使用一对期货来实现这一点,但目前还不完全清楚哪种行为(折叠、映射等)可以保证一个期货在另一个期货之前执行 我首先创建了两个函数,defferedGeocode和deferredWriteToSearchEngine,它们为各自的操作返回未来。我使

我需要对地址对象进行地理编码,然后将更新后的地址存储在搜索引擎中。这可以简化为获取一个对象,对该对象执行一个长时间运行的操作,然后持久化该对象。这意味着有一个操作顺序要求第一个操作在持久化发生之前完成

我想用Akka把它从执行的主线上移开

我最初的想法是使用一对期货来实现这一点,但目前还不完全清楚哪种行为(折叠、映射等)可以保证一个期货在另一个期货之前执行

我首先创建了两个函数,
defferedGeocode
deferredWriteToSearchEngine
,它们为各自的操作返回未来。我使用
Future.和(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);
deferredWriteToSearchEngine
deferredGeocode
非常相似,只是它将搜索引擎服务作为附加的最终参数

我的理解是,期货应该用来进行计算,不应该有副作用。在这种情况下,对地址进行地理编码是一种计算,因此我认为使用未来是合理的,但写入搜索引擎肯定是一种副作用

阿克卡的最佳实践是什么?如何避免所有嵌套调用,但确保地理编码和搜索引擎写入都在主线程之外完成

有没有更合适的工具

更新:

基于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);
}
ExecutionContext;
私有未来地址背景过程(地址){
Future geocodeFuture=地址GeocodeFutureFactory.defferedGeocode(地址);
返回geocodeFuture.flatMap(新映射器(){
@凌驾
公共未来申请(地址geoAddress){
返回地址SearchEngineFutureFactory.deferredWriteToSearchEngine(地理地址);
}
},欧共体);
}
除了一个我不感兴趣的问题外,这似乎还可以。我们在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);
Future myFutureResult=延迟地理编码(ec,地址).flatMap(
新映射器(){
公共未来申请(地址:geocodedAddress){
返回延迟的WriteToSearchEngine(ec、addressSearchService、geocodedAddress);
}
},欧共体)地图(
新映射器(){
公共结果应用(地址保存地址){
//在DelferredWriteToSearchEngine完成后创建一些结果
}
},欧共体);

看看它是如何不嵌套的。flatMap和map用于对操作进行排序。“and then”用于在传递结果之前希望一个只产生副作用的操作运行到完全完成的情况。当然,如果您在同一个未来实例上映射两次,则无法保证订购,但由于我们正在对返回的期货(根据文档中的新期货)进行flatMapping和映射,因此我们的程序中有一个清晰的数据流。

DelferredWriteToSearchEngine执行副作用是否有问题?我对map()调用有点困惑。。。这是否只是我们需要在写操作之后再做一次操作?不,延迟写搜索引擎执行副作用不是问题。是的,最后一张地图是在副作用后做一些事情的例子。嗨@Viktor,请看我的最新评论。我对如何保留国际奥委会的原则和继续使用未来感到有点困惑。也许这应该是一个单独的问题,但它似乎是相关的。@JBCP:听起来像是另一个问题,请作为一个新问题提问。
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);