All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tasks.caching.TaskResultCache.scala Maven / Gradle / Ivy

There is a newer version: 4.0.0-M6
Show newest version
/*
 * The MIT License
 *
 * Copyright (c) 2015 ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE, Switzerland,
 * Group Fellay
 * Modified work, Copyright (c) 2016 Istvan Bartha
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package tasks.caching
import tasks._
import tasks.fileservice._
import tasks.queue._
import tasks.wire._
import tasks.util.config.TasksConfig
import cats.effect.IO

private[tasks] case class AnswerFromCache(
    message: Either[String, Option[UntypedResult]],
    sender: Proxy,
    sch: ScheduleTask
)

private[tasks] class TaskResultCache(
    cacheMap: Cache,
    fileService: FileServiceComponent,
    config: TasksConfig
) {
  def checkResult(
      scheduleTask: ScheduleTask,
      originalSender: Proxy
  ): IO[AnswerFromCache] = {
    val taskId = scheduleTask.description.taskId
    val queryFileServicePrefix =
      config.cachePath match {
        case None => scheduleTask.fileServicePrefix.append(taskId.id)
        case Some(path) =>
          path.append(taskId.id)
      }

    def lookup =
      cacheMap
        .get(scheduleTask.description)(queryFileServicePrefix)
        .handleError { case e =>
          scribe.error(e, "Error while looking up in cache")
          None
        }

    val answer = for {
      cacheLookup <- lookup
      answer <- cacheLookup match {
        case None =>
          scribe.debug(s"Checking: $taskId. Not found in cache.")
          IO.pure(
            AnswerFromCache(
              Left("TaskNotFoundInCache"),
              originalSender,
              scheduleTask
            )
          )
        case _ if !config.verifySharedFileInCache =>
          scribe.debug(s"Checking: $taskId. Got something (not verified).")
          IO.pure(
            AnswerFromCache(Right(cacheLookup), originalSender, scheduleTask)
          )
        case Some(cacheLookup) =>
          scribe.debug(
            s"Checking: $taskId. Got something $cacheLookup, verifying.."
          )
          val files = cacheLookup.files.toSeq.map(sf => (sf, true))
          val mutableFiles =
            cacheLookup.mutableFiles.toSeq.flatten.map(sf => (sf, false))
          IO
            .parTraverseN(config.parallelismOfCacheAccessibilityCheck)(
              files ++ mutableFiles
            ) { case (sf, checkContent) =>
              SharedFileHelper.isAccessible(sf, checkContent)(fileService)
            }
            .map(seq => (seq, seq.forall(identity)))
            .handleError { case e =>
              scribe.warn(
                s"Checking: $taskId. Got something ($cacheLookup), but failed to verify after cache with error: $e."
              )
              (Nil, false)
            }
            .map {
              case (accessibility, false) =>
                val inaccessibleFiles =
                  (files zip accessibility).filterNot(_._2)
                scribe.warn(
                  s"Checking: $taskId. Got something ($cacheLookup), but failed to verify after cache. Inaccessible files: ${inaccessibleFiles.size} : ${inaccessibleFiles
                      .mkString(", ")}"
                )
                AnswerFromCache(
                  Left("TaskNotFoundInCache"),
                  originalSender,
                  scheduleTask
                )
              case (_, true) =>
                scribe.debug(s"Checking: $taskId. Got something (verified).")
                AnswerFromCache(
                  Right(Some(cacheLookup)),
                  originalSender,
                  scheduleTask
                )

            }
      }
    } yield answer
    answer.onError { case e: Exception =>
      IO {
        scribe.error(e, "Cache check failed")
      }
    }

  }
  def saveResult(
      sch: HashedTaskDescription,
      result: UntypedResult,
      prefixFromTask: FileServicePrefix
  ): IO[Unit] = {
    scribe.debug("SavingResult")

    val prefix = config.cachePath match {
      case None => prefixFromTask
      case Some(path) =>
        path.append(sch.taskId.id)
    }
    cacheMap
      .set(sch, result)(prefix)
      .void
      .handleError { case e =>
        IO { scribe.error(e, "Error while saving into cache") }
      }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy