def getOMFileMd5()

in mxs-copy-components/src/main/scala/com/gu/multimedia/mxscopy/helpers/MatrixStoreHelper.scala [165:219]


  def getOMFileMd5(f:MxsObject, maxAttempts:Int=50)(implicit ec:ExecutionContext):Future[Try[String]] = {

    def lookup(attempt:Int=1):Try[String] = {
      if(attempt>maxAttempts) return Failure(new RuntimeException(s"Could not get valid checksum after $attempt tries"))
      logger.info(s"Requesting appliance-side MD5 checksum for ${f.getId} on attempt $attempt")
      val view = f.getAttributeView
      val result = Try {
        val buf = ByteBuffer.allocate(16)
        view.read("__mxs__calc_md5", buf)
        logger.debug(s"Appliance checksum request got buffer of length ${buf.array().length}")
        buf
      }

      result match {
        case Failure(err:TaggedIOException)=>
          if(err.getError==302){
            logger.warn(s"Got 302 (server busy) from appliance when requesting checksum, retrying after delay")
            Thread.sleep(30000*attempt) //we don't want to time out on a large file.Each retry takes 15s to time out, so add 30s per retry.
            lookup(attempt+1)
          } else {
            Failure(err)
          }
        case Failure(err:java.io.IOException)=>
          if(err.getMessage.contains("error 302")){
            logger.warn(s"Appliance side checksum request got an error containing 302 string, retrying after delay")
            Thread.sleep(30000*attempt)
            lookup(attempt+1)
          } else {
            Failure(err)
          }
        case Failure(otherError)=>Failure(otherError)
        case Success(buffer)=>
          val arr = buffer.array()
          if(arr.isEmpty) {
            logger.info(s"Empty string returned for file appliance-side checksum on attempt $attempt, assuming still calculating. Will retry...")
            Thread.sleep(30000*attempt) //this feels nasty but without resorting to actors i can't think of an elegant way
            //to delay and re-call in a non-blocking way
            lookup(attempt + 1)
          } else {
            logger.debug(s"Appliance-side checksum - byte string length was ${arr.length}")
            val converted = Hex.encodeHexString(arr)
            logger.debug(s"Appliance-side checksum - converted string was $converted")
            if (converted.length == 32)
              Success(converted)
            else {
              logger.warn(s"Returned appliance-side checksum $converted is wrong length (${converted.length}; should be 32).")
              Thread.sleep(1500)
              lookup(attempt + 1)
            }
          }
      }
    }

    Future { lookup() }
  }