Как конвертировать отменяемую подписку в Cat's IO - PullRequest
2 голосов
/ 20 марта 2020

В одном из моих проектов я должен использовать асинхронный API на основе обратного вызова. Я хотел представить cats IO, но у меня есть некоторые проблемы с ним:

IO.cancelable { cb =>
  val subscription = createSubscription(
     ...,
     (msg: Message) => cb { Right("SomeResult") }
  )
  IO {subscription.unsubscribe()}
}

Это выглядит довольно хорошо, однако мне также нужно unsubscribe после получения сообщения. К сожалению IO {subscription.unsubscribe()} оценивается только в случае отмены. Я могу сделать быстрый обходной путь, но он кажется очень не интуитивным:

IO.cancelable { cb =>
  lazy val subscription = createSubscription(
     ...,
     (msg: Message) => cb {
       subscription.unsubscribe() //I can't be really sure if subscription is already initialized
       Right("SomeResult")
     }
  )
  subscribe //I have to ensure evalutaion of lazy val
  IO {subscription.unsubscribe()}
}

Я проверил эффекты кошек на c, к сожалению, я не нашел ничего, что могло бы помочь мне с этой проблемой. Я могу подумать о некоторых пуленепробиваемых решениях для этой проблемы, но это кажется настолько типичным, что я не могу поверить, что это еще не было решено.

Есть ли какой-нибудь простой способ достичь этого поведения выпуска ресурса, используя cats

1 Ответ

0 голосов
/ 20 марта 2020

Попробуйте Resource s:

import cats.effect.{ IO, Resource }

val subscriptionResource: Resource[IO, Subscription] =
  Resource.make {
    IO { createSubscription(...) }
  } { subscription =>
    IO { subscription.unsubscribe() }
  }

используется как:

subscriptionResource.use { subscription =>
  // your IO routine
}

Это (составной) способ убедиться, что ваш ресурс будет освобожден, независимо от того, есть ли это ошибка или успех. (Хотя я не помню, что происходит в случае отмены, так как это была тема для подвоха - вероятно, в этом случае блок release не будет вызван).

...