MapRef

MapRef is used internally as a small wrapper around an immutable Map inside of a cats.effect.concurrent.Ref. You can use it as a map of concurrent values that you can access across your application.

import cats.effect.IO
import dev.rpeters.fs2.es.data.MapRef

//Create a concurrent MapRef
val example = MapRef[IO].empty[String, String].flatMap { map =>
  for {
    _ <- map.add("key" -> "value") //Upsert a value to the map
    res1 <- map.get("key")
    _ <- map.del("key")
    res2 <- map.get("key")
  } yield (res1, res2)
}
example.unsafeRunSync()
// res0: (Option[String], Option[String]) = (Some(value = "value"), None)

It has a couple handy extra operators besides just add/get/del operations that you might find useful. MapRef#modify allows you to atomically modify the contents of an entry by-key and return a result value:

val exampleModify = MapRef[IO].of(Map("key" -> "value")).flatMap { map =>
  for {
    resFromModify <- map.modify("key")(v => s"$v but modified" -> "result")
    resFromGet <- map.get("key")
  } yield (resFromModify, resFromGet)
}
exampleModify.unsafeRunSync()
// res1: (Option[String], Option[String]) = (
//   Some(value = "result"),
//   Some(value = "value but modified")
// )

As well as MapRef#upsertOpt that conditionally either modifies or upserts a value for a given key:

val exampleUpsertOpt = MapRef[IO].of(Map("key" -> "value")).flatMap { map =>
  //A helper function for either modifying or inserting a new value
  def upsertFunc(optV: Option[String]): (String, String) = optV match {
      case Some(_) => "value exists" -> "value exists result"
      case None => "new value" -> "new value result"
  }
  for {
    upsertExisting <- map.upsertOpt("key")(upsertFunc)
    upsertNew <- map.upsertOpt("newKey")(upsertFunc)
    resExisting <- map.get("key")
    resNew <- map.get("newKey")
  } yield (upsertExisting, upsertNew, resExisting, resNew)
}
exampleUpsertOpt.unsafeRunSync()
// res2: (String, String, Option[String], Option[String]) = (
//   "value exists result",
//   "new value result",
//   Some(value = "value exists"),
//   Some(value = "new value")
// )