0

I have a block of code that is a slight modification of the code snippet given in the ScalaDoc for TaskLocal [ original here: https://monix.io/api/3.0/monix/eval/TaskLocal.html ].

My code simply replaces the inline task (within the for comprehension) with a reference to a Task that is defined outside the scope of the for comprehension. Unfortunately, when my task runs, it does not see the binding, but instead sees the original value (0). I was hoping my slightly modified code (below) would produce the same result as the snippet from the ScalaDoc. But unexpectedly, I get "value3: 4", not value3: 200. My references to tlocal seem to be getting a different 'version' of that threadlocal-ish variable that is init'd to the default, and knows nothing about the binding.

CODE

class MonixTests extends FlatSpecLike with Matchers {

  "TaskLocal" should "not make me sad " in {
    val tlocal: Task[TaskLocal[Int]] = TaskLocal(0)

    val readTask: Task[Int] =
      tlocal.flatMap {
        taskLocal: TaskLocal[Int] =>
          taskLocal.read.map{ i => i  * 2 }
      }


    val task: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value4 <- local.read // value4 == 100
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value4)
        println("value5: " + value5)
      }

    import monix.execution.Scheduler.Implicits.global
    implicit val opts = Task.defaultOptions.enableLocalContextPropagation
    task.runToFutureOpt

    println("    TRY AGAIN a slightly different way, but no success ;^( ")

    val task3: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value44 <-  local.bind(200) (
          tlocal.flatMap {
            taskLocal: TaskLocal[Int] =>
              taskLocal.read.map{i => i  *  2}
          }
        )
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value44)
        println("value5: " + value5)
      }

    task3.runToFutureOpt
  }

Rationale:

The reason I want to do this is because I want to bind a value to my thread local, then create a map chain of tasks where some of those tasks pull the current value of the thread local which I understand is 'fronted' by TaskLocal. And, just to be clear, some of those tasks are defined in other classes in my code base, not inlined within the scope of any particular for comprehension.

thanks ! /chris

Chris Bedford
  • 2,560
  • 3
  • 28
  • 60

1 Answers1

0

I am now happy as I figured out how to do more or less what I wanted to do. The solution below uses straight up "Local" not TaskLocal. But it has the desired effect of the bound value (200) being visible in a code block that makes reference to the thread local variable 'tlocal'.

I don't really need to do stuff in 'Task context', so this puts me on the right track.

  "TaskLocal" should "not make me sad today" in {
    import monix.execution.misc.Local

    val tlocal = Local(0)

    def doubleTlocal: Int = {tlocal.get * 2}

    val value1 = tlocal.get // value1 == 0
    tlocal.update(100)
    val value2 = tlocal.get // value2 == 100
    val value3 = tlocal.bind(200)(doubleTlocal)
    val value4 = tlocal.get // value4 == 100

     tlocal.clear
    val value5 = tlocal.get // value5 == 0

    println("value1: " + value1)
    println("value2: " + value2)
    println("value3: " + value3)
    println("value4: " + value4)
    println("value5: " + value5)
  }
Chris Bedford
  • 2,560
  • 3
  • 28
  • 60