Caching side effects Is this a proper way to cache side effects (occurring on job.tryLoad)?

case class DFStorage(private var cache: Map[String, DataFrame] = Map()) {
  def tryLoad(job: Job): Kleisli[IO, MakeContext, \/[List[String], Unit]] = {
    if(!cache.contains(job.id)) {
      job.tryLoad.map(_.map(df =&gt; add(job, df)))
    } else {
      IO(().right[List[String]]).liftKleisli
    }
  }
  def add(job: Job, df: DataFrame): IO[Unit] = {
    IO(cache += (job.id -&gt; df))
  }
  def toMap = IO(cache)
}
Looks good to me.

Although, having cache as a simple Map might lay claim to more memory that you like. Associating an LRU with it would allow each addition to evict an ancient job's cached dataframe.