Scala Future方法链中的吞咽异常

时间:2014-06-21 22:00:22

标签: scala amazon-s3

我有一种在Amazon S3上创建zip文件的方法,该文件使用Rinofly的play-s3抽象(不是真的很重要 - 主要是使用Future)。该方法如下所示:

def createZip(key: String): Future[String] = {
    val bucket = //get S3 bucket
    val zipFileName = //name of zip file
    val futureFile = bucket get key //Returns Future[BucketFile]
    futureFile
      .map(bucketFile => newZipFile(bucketFile.name, bucketFile.content) //Create zip file from original key
      .map(newZipFile => bucket + newZipFile) //Does an S3 PUT of the zip file in the bucket and returns Unit
      .map(unit => zipFileName) //Maps the returned unit to the zip file name once the zip file has been created and properly uploaded to S3
}

如您所见,该方法采用S3键并返回已创建的相应zip文件的名称。

我通过REPL发现第二个map方法执行新zip文件的S3 put会抛出异常,因为S3凭据没有权限。没问题 - 我知道如何解决这个问题。

问题是我不知道是这种情况,直到我在REPL中逐行运行所有内容。换句话说,该方法给出了成功的误报。

当我在REPL中运行整个方法时,我得到了这个:

scala> val a = createZip("test.zip")
a: scala.concurrent.Future[String] = scala.concurrent.impl.Promise$DefaultPromise@3174c2d7
scala> import scala.concurrent.Await
Await.result(a, 120.seconds)
scala> res1: String = "test.zip"

结果应该是ThrowableS3Exception FWIW)的一个实例。

此外,当我在REPL中应用onSuccessonFailure个回调时,会触发onSuccess

显然,我正在做一些事情,以便在存储桶添加调用中吞下或隐藏异常的生成。

我很想知道如何确保所有错误都暴露出来。

1 个答案:

答案 0 :(得分:1)

bucket.add返回Future[Unit]而不是Unit。所以在这一行:

.map(unit => zipFileName)

您实际上正在将Future[Unit]映射到String,这就是错误丢失的原因,因为您正在丢弃该响应。这map

.map(newZipFile => bucket + newZipFile)

应该成为flatMapFuture[Future[Unit]]Future[Unit]正确展平。

编译器不够聪明,无法推断您不想映射Future[Unit] => B,但是如果您要添加类型注释,则无法编译。

.map{unit: Unit => zipFileName} // Would complain the type is not Future[Unit]