gpt4 book ai didi

java - 实现像这样的可重试调用的 Scala 方法是什么?

转载 作者:IT老高 更新时间:2023-10-28 20:31:41 29 4
gpt4 key购买 nike

仍然是 Scala 的新手,我现在正在寻找一种在其上实现以下代码的方法:

@Override
public void store(InputStream source, String destination, long size) {

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(size);
final PutObjectRequest request = new PutObjectRequest(
this.configuration.getBucket(), destination, source, metadata);

new RetryableService(3) {

@Override
public void call() throws Exception {
getClient().putObject(request);
}
};

}

在 Scala 中实现与 RetryableService 相同的功能的最佳方法是什么?

它基本上调用 call 方法 N 次,如果它们都失败,则引发异常,如果它们成功则继续。这个不返回任何东西,但是我有另一个版本允许返回一个值(所以,我在 Java 中有两个类),我相信我可以在 Scala 中使用单个类/函数。

有什么想法吗?

编辑

目前在java中的实现如下:

public abstract class RetryableService {

private static final JobsLogger log = JobsLogger
.getLogger(RetryableService.class);

private int times;

public RetryableService() {
this(3);
}

public RetryableService(int times) {
this.times = times;
this.run();
}

private void run() {

RuntimeException lastExceptionParent = null;

int x = 0;

for (; x < this.times; x++) {

try {
this.call();
lastExceptionParent = null;
break;
} catch (Exception e) {
lastExceptionParent = new RuntimeException(e);
log.errorWithoutNotice( e, "Try %d caused exception %s", x, e.getMessage() );

try {
Thread.sleep( 5000 );
} catch (InterruptedException e1) {
log.errorWithoutNotice( e1, "Sleep inside try %d caused exception %s", x, e1.getMessage() );
}

}

}

try {
this.ensure();
} catch (Exception e) {
log.error(e, "Failed while ensure inside RetryableService");
}

if ( lastExceptionParent != null ) {
throw new IllegalStateException( String.format( "Failed on try %d of %s", x, this ), lastExceptionParent);
}

}

public void ensure() throws Exception {
// blank implementation
}

public abstract void call() throws Exception;

}

最佳答案

递归 + 一等函数 按名称参数 == 真棒。

def retry[T](n: Int)(fn: => T): T = {
try {
fn
} catch {
case e =>
if (n > 1) retry(n - 1)(fn)
else throw e
}
}

用法是这样的:

retry(3) {
// insert code that may fail here
}

编辑:受@themel 启发的轻微变化的回答。少了一行代码:-)

def retry[T](n: Int)(fn: => T): T = {
try {
fn
} catch {
case e if n > 1 =>
retry(n - 1)(fn)
}
}

再次编辑:递归让我感到困扰,因为它向堆栈跟踪添加了几个调用。由于某种原因,编译器无法优化 catch 处理程序中的尾递归。但是,不在 catch 处理程序中的尾递归优化得很好:-)

@annotation.tailrec
def retry[T](n: Int)(fn: => T): T = {
val r = try { Some(fn) } catch { case e: Exception if n > 1 => None }
r match {
case Some(x) => x
case None => retry(n - 1)(fn)
}
}

再次编辑:显然,我打算将继续回来并为此答案添加替代方案作为一种爱好。这是一个尾递归版本,它比使用 Option 更简单,但使用 return 来短路函数并不是 Scala 惯用的。

@annotation.tailrec
def retry[T](n: Int)(fn: => T): T = {
try {
return fn
} catch {
case e if n > 1 => // ignore
}
retry(n - 1)(fn)
}

Scala 2.10 更新。作为我的爱好,我偶尔会重新审视这个答案。引入的 Scala 2.10 Try ,它提供了一种以尾递归方式实现重试的简洁方式。

// Returning T, throwing the exception on failure
@annotation.tailrec
def retry[T](n: Int)(fn: => T): T = {
util.Try { fn } match {
case util.Success(x) => x
case _ if n > 1 => retry(n - 1)(fn)
case util.Failure(e) => throw e
}
}

// Returning a Try[T] wrapper
@annotation.tailrec
def retry[T](n: Int)(fn: => T): util.Try[T] = {
util.Try { fn } match {
case util.Failure(_) if n > 1 => retry(n - 1)(fn)
case fn => fn
}
}

关于java - 实现像这样的可重试调用的 Scala 方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7930814/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com