3

I created two versions of my service. First one uses Futures, other one uses ZIO as an effect.

I have a simple method which use Future as a result effect:

def get(id: String)(implicit executionContext: ExecutionContext): Future[Data]

I also has some other version which uses ZIO[SomeEnv, SomeError, Data]:

def get(id: String): ZIO[SomeEnv, SomeError, Data]

Now, I need to create some kind of adapter which will return data from one version or another one:

def returnDataFromServiceVersion(version: Int) : ??? = {
   if(version == 1) futureService.get(...)
   else zioService.get(...)
}

The problem here is with returned type. I do not know how to convert ZIO into future or Future into ZIO to have common return type. I tried use ZIO.fromFuture{...} or toFuture() but it did not help. My question is - how to create this returnDataFromServiceVersion method to use it with both services? I need to have common return type here.

Or maybe there is another way to solve this problem?

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
Developus
  • 1,400
  • 2
  • 14
  • 50

2 Answers2

6

You have to decide whether your function returns Future or ZIO and this cannot depend on a runtime value like version in your snippet (unless of course you define the return type as AnyRef - not very useful).
If the rest of your program is based on Futures, but you would like to start introducing ZIO in some services, you can do that by executing your effects yourself using runtime.unsafeRun(effect):

val runtime = Runtime.default

def returnDataFromServiceVersion(version: Int): Future[Data] = {
  runtime.unsafeRunToFuture(
    zioService.get(...)
  )
}

For more details refer to Running Effects in the official ZIO docs.

zagyi
  • 17,223
  • 4
  • 51
  • 48
3

If I understand correctly what you want is common ZIO type which would look like this ZIO[SomeEnv, SomeError, Data]

That can be achieved using ZIO.fromFuture and mapping Throwable (which is Future failure type) to your SomeError:

  case class Data(data: String)
  case class SomeEnv(env: String)
  case class SomeError(err: String)

  object SomeError {
    def fromThrowable(throwable: Throwable) = SomeError(throwable.toString)
  }

  def getFuture(id: String)(implicit executionContext: ExecutionContext): Future[Data] = ???
  def getZIO(id: String): ZIO[SomeEnv, SomeError, Data] = ???

  def returnDataFromServiceVersion(version: Int): ZIO[SomeEnv, SomeError, Data] =
    if (version == 1)
      ZIO
        .fromFuture(executionContext => getFuture("id")(executionContext))
        .mapError(SomeError.fromThrowable)
    else
      getZIO("id")
energi
  • 79
  • 8