7mind / izumi

Productivity-oriented collection of lightweight fancy stuff for Scala toolchain

Home Page:https://izumi.7mind.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Simplify lifecycle definition for classes with init/cleanup method pair

pshirshov opened this issue · comments

It's pretty common to have a resource which can be built with .from[Clz] but requires .init to be invoked before it can be used and .cleanup before it can be released. Both init and cleanup are optional.

For now we have to type something like:

(worst-case version)

  make[GMStorage].fromResource {
    (config: StorageConfig, hash: GMHasher) =>
      Lifecycle.make[Identity, GMStorage] {
        val out = new GMStorage.GMStorageImpl(config, hash)
        out.init()
        out
      }(_ => ())
  }

or

(cleaner but still inconvenient)

  make[GMStorage.GMStorageImpl]
  make[GMStorage].fromResource {
    (underlying: GMStorage.GMStorageImpl) =>
      Lifecycle.make[Identity, GMStorage] {
        underlying.init()
        underlying
      }(_ => ())
  }

dirty idea:

  def makeInitializable[If: Tag, Impl <: If: Tag: AnyConstructor](lifecycle: Impl => Lifecycle[Identity, If]): Unit = {
    make[Impl]
    make[If].fromResource {
      (underlying: Impl) =>
        lifecycle(underlying)
    }
  }
commented

@pshirshov
You may try evalTap for that:

Lifecycle.makeSimple[GMStorage] {
  new GMStorage.GMStorageImpl(config, hash)
 }(_ => ())
  .evalTap(_.init())

Still, I think that explicit support for a pair of methods would be a good addition

commented

@pshirshov
When you have control of the implementation class you may use Lifecycle.Mutable for that:

class GMStorageImpl(config: StorageConfig, hash: GMHasher) extends GMStorage with Lifecycle.Mutable {
  def acquire: Unit = init()
  def release: Unit = ()
}

make[GMStorage].fromResource[GMStorageImpl]

And I've added Lifecycle.makeSimpleInit #1985 for cases where the implementation class is not controlled:

make[GMStorage].fromResource {
 (config: StorageConfig, hash: GMHasher) =>
   Lifecycle.makeSimpleInit(
     new GMStorageImpl(config, hash)
   )(_.init())(_ => ())
}