如何结合Context Receivers与Arrow 1.2.0的parZipOrAccumulate并行调用带Raise上下文的函数并累积错误?
如何结合Context Receivers与Arrow 1.2.0的parZipOrAccumulate并行调用带Raise上下文的函数并累积错误?
嘿,我完全懂你遇到的这个编译问题——那些带context(Raise<ApplicationError>)的getUser和getDepartment函数,没法直接塞进parZipOrAccumulate的lambda里,因为当前函数的上下文是Raise<Nel<ApplicationError>>,类型根本不匹配嘛!别着急,咱们一步步搞定它。
问题根源
getUser和getDepartment期望的是一个能抛出单个ApplicationError的上下文,但你的execute函数运行在一个能抛出Nel<ApplicationError>(非空错误列表)的上下文中。两者的上下文要求不兼容,所以编译器才会报错说找不到所需的上下文接收器。
解决方案:上下文转换+错误包装
我们需要做的就是把单个错误的上下文,适配成能累积成错误列表的上下文。Arrow的Raise提供了withRaise函数,正好能帮我们完成这个转换——它会把当前的Raise<Nel<ApplicationError>>上下文,临时转换成getUser/getDepartment需要的Raise<ApplicationError>上下文,同时把抛出的单个错误自动包装成Nel(非空列表),传递回上层上下文供parZipOrAccumulate累积。
修改后的代码如下:
context(Raise<Nel<ApplicationError>>) override suspend fun execute(param: AddUserToDepartmentInfo): Department { val pair: Pair<User, Department> = parZipOrAccumulate( // 合并两个错误列表 { e1: Nel<ApplicationError>, e2: Nel<ApplicationError> -> e1 + e2 }, // 适配getUser的上下文,把单个错误包装成Nel { raise.withRaise({ err -> Nel.of(err) }) { getUser(param.userLegalId) } }, // 同理适配getDepartment的上下文 { raise.withRaise({ err -> Nel.of(err) }) { getDepartment(param.departmentCode) } } ) { a, b -> Pair(a, b) } saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode)) return pair.second }
优化:抽成扩展函数让代码更简洁
如果需要多次做这种转换,咱们可以把逻辑抽成一个扩展函数,避免重复代码:
// 定义扩展函数,把单个错误的Raise上下文适配成Nel错误的上下文 context(Raise<Nel<E>>) suspend fun <E : Throwable, A> context(Raise<E>) suspend () -> A.toNelRaise(): A = raise.withRaise({ Nel.of(it) }) { this() }
之后调用的时候就可以简化成:
context(Raise<Nel<ApplicationError>>) override suspend fun execute(param: AddUserToDepartmentInfo): Department { val pair: Pair<User, Department> = parZipOrAccumulate( { e1, e2 -> e1 + e2 }, { getUser(param.userLegalId).toNelRaise() }, { getDepartment(param.departmentCode).toNelRaise() } ) { a, b -> Pair(a, b) } saveUserDrivenPort.save(pair.first.copy(departmentId = param.departmentCode)) return pair.second }
这样代码看起来清爽多了,而且完全符合你的需求——并行调用两个函数,同时把各自的错误累积成一个非空列表。
备注:内容来源于stack exchange,提问作者codependent
相关产品推荐
相关产品推荐

