Monix TaskLocal, по-видимому, не отражает значения из вызова bind (), когда на него ссылается Task из другой лексической области - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть блок кода, который представляет собой небольшую модификацию фрагмента кода, приведенного в ScalaDoc для TaskLocal [оригинал здесь: https://monix.io/api/3.0/monix/eval/TaskLocal.html].

Мой код просто заменяет встроенную задачу (в пределах для понимания) со ссылкой на задачу, которая определена за пределами области понимания.К сожалению, когда моя задача выполняется, она не видит привязку, а вместо этого видит исходное значение (0).Я надеялся, что мой слегка измененный код (ниже) даст тот же результат, что и фрагмент из ScalaDoc.Но неожиданно я получаю «значение3: 4», а не значение3: 200. Кажется, мои ссылки на tlocal получают другую «версию» этой переменной threadlocal-ish, которая по умолчанию имеет значение init'd и ничего не знает о привязке.

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
  }

Обоснование:

Причина, по которой я хочу это сделать, заключается в том, что я хочу привязать значение к локальному потокузатем создайте цепочку задач, в которой некоторые из этих задач извлекают текущее значение локального потока, которое, как я понимаю, передано TaskLocal.И, чтобы было ясно, некоторые из этих задач определены в других классах в моей кодовой базе, и не включены в рамки какого-либо конкретного для понимания.

спасибо!/ * Крис 1016 *

1 Ответ

0 голосов
/ 20 февраля 2019

Я теперь счастлив, когда я понял, как сделать более или менее то, что я хотел сделать.Решение ниже использует "Local", а не TaskLocal.Но он имеет желаемый эффект отображения связанного значения (200) в блоке кода, который ссылается на локальную переменную потока 'tlocal'.

Мне действительно не нужно ничего делать в контексте задачи', так что это ставит меня на правильный путь.

  "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)
  }
...