fd4s / fs2-kafka

Functional Kafka Streams for Scala
https://fd4s.github.io/fs2-kafka
Apache License 2.0
295 stars 100 forks source link

Separate initialization effect in the constructors #553

Open LMnet opened 3 years ago

LMnet commented 3 years ago

Many of the components of the library have the constructor in the following form:

class Component[F]
object Component {
  def apply[F[_]: SomeConstraints]: F[Component[F]]
}

The problem with this form of a constructor is that the initialization effect and execution effect are the same effects. But in fact, they may be different. Moreover, they may have different constraints.

I suggest to change in 2.0.0 all these constructors to the following form:

class Component[F]
object Component {
  def apply[F[_]: ExecConstraints, G[_]: InitConsraints]: G[Component[F]]
}

This change will be especially helpful for the complex tagless final codebases which use multiple different reader-like effects in the same codebase.

bplommer commented 3 years ago

Just to be clear - you're talking about allocating KafkaConsumer/KafkaProducer etc as Resource[G, KafkaConsumer[F, K, V]] etc, right?

LMnet commented 3 years ago

Yes, exactly.

catostrophe commented 3 years ago

I would also keep a form of this method with the same effects passed, e.g.

def make[F[_]: ExecConstraints, G[_]: InitConsraints]: G[Component[F]] = ???
def apply[F[_]: ExecConstraints: InitConsraints]: F[Component[F]] = make[F, F] 
bplommer commented 3 years ago

Agreed. I think we should keep the current methods as they are and add variants with names suffixed with In with the extra type parameter.

bplommer commented 3 years ago

I’ve put this in the v3.0.0 milestone, but hopefully we can do it in a non-breaking way as part of the 2.x series.

bplommer commented 3 years ago

This is done for KafkaAdminClient and for KafkaProducerConnection, with the caveat that for KafkaProducerConnection it requires Async for the allocating effect purely so that close can be run on a custom ExecutionContext if provided.

Doing this for KafkaConsumer is going to be much harder, if it's possible at all, because the actor is initialized and terminated as part of the allocation.

TODO: