cats.effect.ConcurrentEffect Scala Examples

The following examples show how to use cats.effect.ConcurrentEffect. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: package.scala    From fs2-aws   with MIT License 5 votes vote down vote up
package fs2.aws

import cats.effect.ConcurrentEffect
import cats.effect.concurrent.Deferred
import eu.timepit.refined.auto._
import fs2.aws.sqs.SqsConfig
import javax.jms.{ Message, MessageListener }
import scala.concurrent.duration._

package object testkit {
  def sqsStream[F[_]: ConcurrentEffect, O](
    d: Deferred[F, MessageListener]
  )(implicit decoder: Message => Either[Throwable, O]): fs2.Stream[F, O] =
    fs2.aws.sqsStream(
      SqsConfig("dummy"),
      (_: SqsConfig, _: MessageListener) => new TestSqsConsumerBuilder[F],
      Some(d)
    )

  val TestRecordProcessor = new kinesis.SingleRecordProcessor(_ => (), 10.seconds)
} 
Example 2
Source File: BookingConfirmationProcessWiring.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.booking.process

import aecor.data._
import aecor.distributedprocessing.DistributedProcessing
import cats.effect.ConcurrentEffect
import cats.implicits._
import ru.pavkin.booking.booking.entity.{ BookingEvent, BookingPlaced }
import ru.pavkin.booking.booking.process.BookingConfirmationProcessWiring.EventSource
import ru.pavkin.booking.common.models.BookingKey
import ru.pavkin.booking.common.streaming.Fs2Process

class BookingConfirmationProcessWiring[F[_]: ConcurrentEffect](
  eventSource: (EventTag, ConsumerId) => EventSource[F],
  tagging: Tagging[BookingKey],
  process: (BookingKey, BookingPlaced) => F[Unit]
) {

  val consumerId = ConsumerId("BookingConfirmationProcess")

  def tagProcess(tag: EventTag): fs2.Stream[F, Unit] =
    eventSource(tag, consumerId)
      .collect(Committable.collector { case EntityEvent(k, _, e: BookingPlaced) => k -> e })
      .evalMap(c => process(c.value._1, c.value._2) >> c.commit)

  def processes: List[DistributedProcessing.Process[F]] =
    tagging.tags.map(tag => Fs2Process(tagProcess(tag)))

}

object BookingConfirmationProcessWiring {
  type EventSource[F[_]] = fs2.Stream[F, Committable[F, EntityEvent[BookingKey, BookingEvent]]]
} 
Example 3
Source File: EndpointWirings.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking

import cats.effect.{ConcurrentEffect, Timer}
import org.http4s.HttpRoutes
import org.http4s.implicits._
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder
import ru.pavkin.booking.booking.endpoint.{BookingRoutes, DefaultBookingEndpoint}
import ru.pavkin.booking.config.HttpServer

import scala.concurrent.duration.{Duration => _}

final class EndpointWirings[F[_] : ConcurrentEffect : Timer](
  httpServer: HttpServer,
  postgresWirings: PostgresWirings[F],
  entityWirings: EntityWirings[F]) {

  import entityWirings._
  import postgresWirings._

  val bookingsEndpoint = new DefaultBookingEndpoint(bookings, bookingViewRepo)

  val bookingRoutes = new BookingRoutes(bookingsEndpoint)

  val routes: HttpRoutes[F] = bookingRoutes.routes

  def launchHttpService: F[Unit] =
    BlazeServerBuilder[F]
      .bindHttp(httpServer.port, httpServer.interface)
      .withHttpApp(Router("/" -> routes).orNotFound)
      .serve
      .compile
      .drain

} 
Example 4
Source File: StaticLoggerBinder.scala    From odin   with Apache License 2.0 5 votes vote down vote up
package org.slf4j.impl

import cats.effect.{ConcurrentEffect, ContextShift, IO, Timer}
import io.odin._
import io.odin.slf4j.{BufferingLogger, OdinLoggerBinder}

import scala.concurrent.ExecutionContext

class StaticLoggerBinder extends OdinLoggerBinder[IO] {

  val ec: ExecutionContext = scala.concurrent.ExecutionContext.global
  implicit val timer: Timer[IO] = IO.timer(ec)
  implicit val cs: ContextShift[IO] = IO.contextShift(ec)
  implicit val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect

  val loggers: PartialFunction[String, Logger[IO]] = {
    case Level.Trace.toString => new BufferingLogger[IO](Level.Trace)
    case Level.Debug.toString => new BufferingLogger[IO](Level.Debug)
    case Level.Info.toString  => new BufferingLogger[IO](Level.Info)
    case Level.Warn.toString  => new BufferingLogger[IO](Level.Warn)
    case Level.Error.toString => new BufferingLogger[IO](Level.Error)
    case _ =>
      new BufferingLogger[IO](Level.Trace)
  }
}

object StaticLoggerBinder extends StaticLoggerBinder {

  var REQUESTED_API_VERSION: String = "1.7"

  def getSingleton: StaticLoggerBinder = this

} 
Example 5
Source File: Fs2AkkaStreamInterop.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.example.common

import akka.stream.Materializer
import akka.stream.scaladsl.{ Keep, Sink, Source }
import cats.effect.ConcurrentEffect
import fs2.Stream
import fs2.interop.reactivestreams._
import cats.implicits._

object Fs2AkkaStreamInterop {
  implicit final class SourceToStream[A, Mat](val self: Source[A, Mat]) extends AnyVal {
    def materializeToStream[F[_]](
      materializer: Materializer
    )(implicit F: ConcurrentEffect[F]): F[(Mat, Stream[F, A])] = F.delay {
      val (mat, publisher) = self.toMat(Sink.asPublisher(false))(Keep.both).run()(materializer)
      (mat, publisher.toStream[F])
    }
    def toStream[F[_]](materializer: Materializer)(implicit F: ConcurrentEffect[F]): Stream[F, A] =
      Stream.force(materializeToStream[F](materializer).map(_._2))
  }
} 
Example 6
Source File: DistributedProcessing.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.kafkadistributedprocessing

import java.util.Properties

import aecor.kafkadistributedprocessing.internal.Kafka
import aecor.kafkadistributedprocessing.internal.Kafka._
import cats.effect.{ ConcurrentEffect, ContextShift, Timer }
import cats.implicits._
import cats.effect.implicits._
import fs2.Stream
import org.apache.kafka.clients.consumer.ConsumerConfig

import scala.concurrent.duration._

final class DistributedProcessing(settings: DistributedProcessingSettings) {

  private def assignRange(size: Int, partitionCount: Int, partition: Int): Option[(Int, Int)] = {
    val even = size / partitionCount
    val reminder = size % partitionCount
    if (partition >= partitionCount) {
      none
    } else {
      if (partition < reminder) {
        (partition * (even + 1), even + 1).some
      } else if (even > 0) {
        (reminder + partition * even, even).some
      } else none
    }
  }

  
  def start[F[_]: ConcurrentEffect: Timer: ContextShift](name: String,
                                                         processes: List[F[Unit]]): F[Unit] =
    Kafka
      .assignPartitions(
        settings.asProperties(name),
        settings.topicName,
        settings.pollingInterval,
        settings.pollTimeout
      )
      .parEvalMapUnordered(Int.MaxValue) {
        case AssignedPartition(partition, partitionCount, watchRevocation, release) =>
          assignRange(processes.size, partitionCount, partition).fold(release) {
            case (offset, processCount) =>
              Stream
                .range[F](offset, offset + processCount)
                .parEvalMapUnordered(processCount)(processes)
                .compile
                .drain
                .race(watchRevocation)
                .flatMap {
                  case Left(_)         => release
                  case Right(callback) => callback
                }
          }
      }
      .compile
      .drain
}

object DistributedProcessing {
  def apply(settings: DistributedProcessingSettings): DistributedProcessing =
    new DistributedProcessing(settings)
}

final case class DistributedProcessingSettings(brokers: Set[String],
                                               topicName: String,
                                               pollingInterval: FiniteDuration = 500.millis,
                                               pollTimeout: FiniteDuration = 50.millis,
                                               consumerSettings: Map[String, String] = Map.empty) {
  def withClientId(clientId: String): DistributedProcessingSettings =
    withConsumerSetting(ConsumerConfig.CLIENT_ID_CONFIG, clientId)

  def clientId: Option[String] = consumerSettings.get(ConsumerConfig.CLIENT_ID_CONFIG)

  def withConsumerSetting(key: String, value: String): DistributedProcessingSettings =
    copy(consumerSettings = consumerSettings.updated(key, value))

  def asProperties(groupId: String): Properties = {
    val properties = new Properties()
    consumerSettings.foreach {
      case (key, value) => properties.setProperty(key, value)
    }
    properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers.mkString(","))
    properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, groupId)
    properties
  }

} 
Example 7
Source File: RebalanceEvents.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.kafkadistributedprocessing.internal

import java.util

import aecor.data.Committable
import cats.effect.concurrent.Deferred
import cats.effect.implicits._
import cats.effect.{ ConcurrentEffect, Effect }
import cats.implicits._
import fs2.Stream
import fs2.concurrent.Queue
import org.apache.kafka.clients.consumer.ConsumerRebalanceListener
import org.apache.kafka.common
import org.apache.kafka.common.TopicPartition

import scala.collection.JavaConverters._

private[kafkadistributedprocessing] object RebalanceEvents {
  final class UsePartiallyApplied[F[_]] {
    def subscribe[A](
      f: ConsumerRebalanceListener => F[Unit]
    )(implicit F: ConcurrentEffect[F]): F[Stream[F, Committable[F, RebalanceEvent]]] =
      for {
        queue <- Queue.unbounded[F, Committable[F, RebalanceEvent]]
        listener = new Listener[F](
          event =>
            Deferred[F, Unit]
              .flatMap { completion =>
                queue.enqueue1(Committable(completion.complete(()), event)) >> completion.get
            }
        )
        _ <- f(listener)
      } yield queue.dequeue
  }

  def apply[F[_]]: UsePartiallyApplied[F] = new UsePartiallyApplied[F]

  sealed abstract class RebalanceEvent
  object RebalanceEvent {
    final case class PartitionsRevoked(partitions: Set[TopicPartition]) extends RebalanceEvent
    final case class PartitionsAssigned(partitions: Set[TopicPartition]) extends RebalanceEvent
  }

  private final class Listener[F[_]: Effect](processEvent: RebalanceEvent => F[Unit])
      extends ConsumerRebalanceListener {

    override def onPartitionsRevoked(partitions: util.Collection[common.TopicPartition]): Unit =
      processEvent(RebalanceEvent.PartitionsRevoked(partitions.asScala.toSet)).toIO
        .unsafeRunSync()

    override def onPartitionsAssigned(partitions: util.Collection[common.TopicPartition]): Unit =
      processEvent(RebalanceEvent.PartitionsAssigned(partitions.asScala.toSet)).toIO
        .unsafeRunSync()
  }
} 
Example 8
Source File: JobsApiTest.scala    From kubernetes-client   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kubernetes.client.api

import cats.effect.{ConcurrentEffect, IO}
import com.goyeau.kubernetes.client.operation._
import com.goyeau.kubernetes.client.KubernetesClient
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import io.k8s.api.batch.v1.{Job, JobList, JobSpec}
import io.k8s.api.core.v1._
import io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class JobsApiTest
    extends AnyFlatSpec
    with Matchers
    with OptionValues
    with CreatableTests[IO, Job]
    with GettableTests[IO, Job]
    with ListableTests[IO, Job, JobList]
    with ReplaceableTests[IO, Job]
    with DeletableTests[IO, Job, JobList]
    with DeletableTerminatedTests[IO, Job, JobList]
    with WatchableTests[IO, Job]
    with ContextProvider {

  implicit lazy val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect
  implicit lazy val logger: Logger[IO]      = Slf4jLogger.getLogger[IO]
  lazy val resourceName                     = classOf[Job].getSimpleName

  override def api(implicit client: KubernetesClient[IO]) = client.jobs
  override def namespacedApi(namespaceName: String)(implicit client: KubernetesClient[IO]) =
    client.jobs.namespace(namespaceName)

  override def sampleResource(resourceName: String, labels: Map[String, String]) =
    Job(
      metadata = Option(ObjectMeta(name = Option(resourceName), labels = Option(labels))),
      spec = Option(
        JobSpec(
          template = PodTemplateSpec(
            metadata = Option(ObjectMeta(name = Option(resourceName))),
            spec = Option(
              PodSpec(containers = Seq(Container("test", image = Option("docker"))), restartPolicy = Option("Never"))
            )
          )
        )
      )
    )
  val labels = Map("app" -> "test")
  override def modifyResource(resource: Job) = resource.copy(
    metadata = Option(ObjectMeta(name = resource.metadata.flatMap(_.name), labels = Option(labels)))
  )
  override def checkUpdated(updatedResource: Job) =
    (updatedResource.metadata.value.labels.value.toSeq should contain).allElementsOf(labels.toSeq)

  override def deleteApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Deletable[IO] =
    client.jobs.namespace(namespaceName)

  override def watchApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Watchable[IO, Job] =
    client.jobs.namespace(namespaceName)
} 
Example 9
Source File: DeploymentsApiTest.scala    From kubernetes-client   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kubernetes.client.api

import cats.effect.{ConcurrentEffect, IO}
import com.goyeau.kubernetes.client.operation._
import com.goyeau.kubernetes.client.{IntValue, KubernetesClient, StringValue}
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import io.k8s.api.apps.v1._
import io.k8s.api.core.v1._
import io.k8s.apimachinery.pkg.apis.meta.v1.{LabelSelector, ObjectMeta}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers

class DeploymentsApiTest
    extends AnyFlatSpec
    with Matchers
    with OptionValues
    with CreatableTests[IO, Deployment]
    with GettableTests[IO, Deployment]
    with ListableTests[IO, Deployment, DeploymentList]
    with ReplaceableTests[IO, Deployment]
    with DeletableTests[IO, Deployment, DeploymentList]
    with DeletableTerminatedTests[IO, Deployment, DeploymentList]
    with WatchableTests[IO, Deployment]
    with ContextProvider {

  implicit lazy val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect
  implicit lazy val logger: Logger[IO]      = Slf4jLogger.getLogger[IO]
  lazy val resourceName                     = classOf[Deployment].getSimpleName

  override def api(implicit client: KubernetesClient[IO]) = client.deployments
  override def namespacedApi(namespaceName: String)(implicit client: KubernetesClient[IO]) =
    client.deployments.namespace(namespaceName)

  override def sampleResource(resourceName: String, labels: Map[String, String]) = {
    val label = Option(Map("app" -> "test"))
    Deployment(
      metadata = Option(ObjectMeta(name = Option(resourceName), labels = Option(labels))),
      spec = Option(
        DeploymentSpec(
          selector = LabelSelector(matchLabels = label),
          template = PodTemplateSpec(
            metadata = Option(ObjectMeta(name = Option(resourceName), labels = label)),
            spec = Option(PodSpec(containers = Seq(Container("test", image = Option("docker")))))
          )
        )
      )
    )
  }
  val strategy = Option(
    DeploymentStrategy(
      `type` = Option("RollingUpdate"),
      rollingUpdate =
        Option(RollingUpdateDeployment(maxSurge = Option(StringValue("25%")), maxUnavailable = Option(IntValue(10))))
    )
  )
  override def modifyResource(resource: Deployment) = resource.copy(
    metadata = Option(ObjectMeta(name = resource.metadata.flatMap(_.name))),
    spec = resource.spec.map(_.copy(strategy = strategy))
  )
  override def checkUpdated(updatedResource: Deployment) =
    updatedResource.spec.value.strategy shouldBe strategy

  override def deleteApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Deletable[IO] =
    client.deployments.namespace(namespaceName)

  override def watchApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Watchable[IO, Deployment] =
    client.deployments.namespace(namespaceName)
} 
Example 10
Source File: CronJobsApiTest.scala    From kubernetes-client   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kubernetes.client.api

import cats.effect.{ConcurrentEffect, IO}
import com.goyeau.kubernetes.client.operation._
import com.goyeau.kubernetes.client.KubernetesClient
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import io.k8s.api.batch.v1.JobSpec
import io.k8s.api.batch.v1beta1.{CronJob, CronJobList, CronJobSpec, JobTemplateSpec}
import io.k8s.api.core.v1._
import io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers

class CronJobsApiTest
    extends AnyFlatSpec
    with Matchers
    with OptionValues
    with CreatableTests[IO, CronJob]
    with GettableTests[IO, CronJob]
    with ListableTests[IO, CronJob, CronJobList]
    with ReplaceableTests[IO, CronJob]
    with DeletableTests[IO, CronJob, CronJobList]
    with DeletableTerminatedTests[IO, CronJob, CronJobList]
    with WatchableTests[IO, CronJob]
    with ContextProvider {

  implicit lazy val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect
  implicit lazy val logger: Logger[IO]      = Slf4jLogger.getLogger[IO]
  lazy val resourceName                     = classOf[CronJob].getSimpleName

  override def api(implicit client: KubernetesClient[IO]) = client.cronJobs
  override def namespacedApi(namespaceName: String)(implicit client: KubernetesClient[IO]) =
    client.cronJobs.namespace(namespaceName)

  override def sampleResource(resourceName: String, labels: Map[String, String]) =
    CronJob(
      metadata = Option(ObjectMeta(name = Option(resourceName), labels = Option(labels))),
      spec = Option(
        CronJobSpec(
          schedule = "1 * * * *",
          jobTemplate = JobTemplateSpec(
            spec = Option(
              JobSpec(
                template = PodTemplateSpec(
                  metadata = Option(ObjectMeta(name = Option(resourceName))),
                  spec = Option(
                    PodSpec(
                      containers = Seq(Container("test", image = Option("docker"))),
                      restartPolicy = Option("Never")
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  val schedule = "2 * * * *"
  override def modifyResource(resource: CronJob) = resource.copy(
    metadata = Option(ObjectMeta(name = resource.metadata.flatMap(_.name))),
    spec = resource.spec.map(_.copy(schedule = schedule))
  )
  override def checkUpdated(updatedResource: CronJob) =
    updatedResource.spec.value.schedule shouldBe schedule

  override def deleteApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Deletable[IO] =
    client.cronJobs.namespace(namespaceName)

  override def watchApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Watchable[IO, CronJob] =
    client.cronJobs.namespace(namespaceName)
} 
Example 11
Source File: ReplicaSetsApiTest.scala    From kubernetes-client   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kubernetes.client.api

import cats.effect.{ConcurrentEffect, IO}
import com.goyeau.kubernetes.client.KubernetesClient
import com.goyeau.kubernetes.client.operation._
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import io.k8s.api.apps.v1._
import io.k8s.api.core.v1._
import io.k8s.apimachinery.pkg.apis.meta.v1.{LabelSelector, ObjectMeta}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers

class ReplicaSetsApiTest
    extends AnyFlatSpec
    with Matchers
    with OptionValues
    with CreatableTests[IO, ReplicaSet]
    with GettableTests[IO, ReplicaSet]
    with ListableTests[IO, ReplicaSet, ReplicaSetList]
    with ReplaceableTests[IO, ReplicaSet]
    with DeletableTests[IO, ReplicaSet, ReplicaSetList]
    with DeletableTerminatedTests[IO, ReplicaSet, ReplicaSetList]
    with WatchableTests[IO, ReplicaSet]
    with ContextProvider {

  implicit lazy val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect
  implicit lazy val logger: Logger[IO]      = Slf4jLogger.getLogger[IO]
  lazy val resourceName                     = classOf[ReplicaSet].getSimpleName

  override def api(implicit client: KubernetesClient[IO]) = client.replicaSets
  override def namespacedApi(namespaceName: String)(implicit client: KubernetesClient[IO]) =
    client.replicaSets.namespace(namespaceName)

  override def sampleResource(resourceName: String, labels: Map[String, String]) = {
    val label = Option(Map("app" -> "test"))
    ReplicaSet(
      metadata = Option(ObjectMeta(name = Option(resourceName), labels = Option(labels))),
      spec = Option(
        ReplicaSetSpec(
          selector = LabelSelector(matchLabels = label),
          template = Option(
            PodTemplateSpec(
              metadata = Option(ObjectMeta(name = Option(resourceName), labels = label)),
              spec = Option(PodSpec(containers = Seq(Container("test", image = Option("docker")))))
            )
          )
        )
      )
    )
  }
  val replicas = Option(5)
  override def modifyResource(resource: ReplicaSet) = resource.copy(
    metadata = Option(ObjectMeta(name = resource.metadata.flatMap(_.name))),
    spec = resource.spec.map(_.copy(replicas = replicas))
  )
  override def checkUpdated(updatedResource: ReplicaSet) =
    updatedResource.spec.value.replicas shouldBe replicas

  override def deleteApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Deletable[IO] =
    client.replicaSets.namespace(namespaceName)

  override def watchApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Watchable[IO, ReplicaSet] =
    client.replicaSets.namespace(namespaceName)
} 
Example 12
Source File: StatefulSetsApiTest.scala    From kubernetes-client   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kubernetes.client.api

import cats.effect.{ConcurrentEffect, IO}
import com.goyeau.kubernetes.client.KubernetesClient
import com.goyeau.kubernetes.client.operation._
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import io.k8s.api.apps.v1._
import io.k8s.api.core.v1._
import io.k8s.apimachinery.pkg.apis.meta.v1.{LabelSelector, ObjectMeta}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers

class StatefulSetsApiTest
    extends AnyFlatSpec
    with Matchers
    with OptionValues
    with CreatableTests[IO, StatefulSet]
    with GettableTests[IO, StatefulSet]
    with ListableTests[IO, StatefulSet, StatefulSetList]
    with ReplaceableTests[IO, StatefulSet]
    with DeletableTests[IO, StatefulSet, StatefulSetList]
    with DeletableTerminatedTests[IO, StatefulSet, StatefulSetList]
    with WatchableTests[IO, StatefulSet]
    with ContextProvider {

  implicit lazy val F: ConcurrentEffect[IO] = IO.ioConcurrentEffect
  implicit lazy val logger: Logger[IO]      = Slf4jLogger.getLogger[IO]
  lazy val resourceName                     = classOf[StatefulSet].getSimpleName

  override def api(implicit client: KubernetesClient[IO]) = client.statefulSets
  override def namespacedApi(namespaceName: String)(implicit client: KubernetesClient[IO]) =
    client.statefulSets.namespace(namespaceName)

  override def sampleResource(resourceName: String, labels: Map[String, String]) = {
    val label = Option(Map("app" -> "test"))
    StatefulSet(
      metadata = Option(ObjectMeta(name = Option(resourceName), labels = Option(labels))),
      spec = Option(
        StatefulSetSpec(
          serviceName = "service-name",
          selector = LabelSelector(matchLabels = label),
          template = PodTemplateSpec(
            metadata = Option(ObjectMeta(name = Option(resourceName), labels = label)),
            spec = Option(PodSpec(containers = Seq(Container("test", image = Option("docker")))))
          )
        )
      )
    )
  }
  val updateStrategy = Option(
    StatefulSetUpdateStrategy(
      `type` = Option("RollingUpdate"),
      rollingUpdate = Option(RollingUpdateStatefulSetStrategy(partition = Option(10)))
    )
  )
  override def modifyResource(resource: StatefulSet) = resource.copy(
    metadata = Option(ObjectMeta(name = resource.metadata.flatMap(_.name))),
    spec = resource.spec.map(_.copy(updateStrategy = updateStrategy))
  )
  override def checkUpdated(updatedResource: StatefulSet) =
    updatedResource.spec.value.updateStrategy shouldBe updateStrategy

  override def deleteApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Deletable[IO] =
    client.statefulSets.namespace(namespaceName)

  override def watchApi(namespaceName: String)(implicit client: KubernetesClient[IO]): Watchable[IO, StatefulSet] =
    client.statefulSets.namespace(namespaceName)
} 
Example 13
Source File: unlift.scala    From tofu   with Apache License 2.0 5 votes vote down vote up
package tofu.syntax

import cats.effect.{CancelToken, ConcurrentEffect, Effect, ExitCase, Fiber, IO, SyncIO}
import cats.{FlatMap, Functor, ~>}
import tofu.lift.Unlift

object unlift {

  implicit final class UnliftEffectOps[F[_], G[_]](private val U: Unlift[F, G]) extends AnyVal {
    def effect(implicit G: Functor[G], E: Effect[F]): G[Effect[G]] =
      G.map(U.unlift) { unliftF =>
        new EffectInstance[F, G] {
          def toG: F ~> G           = U.liftF
          def toF: G ~> F           = unliftF
          implicit def F: Effect[F] = E
        }
      }

    def effectWith[A](f: Effect[G] => G[A])(implicit G: FlatMap[G], E: Effect[F]): G[A] =
      G.flatMap(U.unlift) { unliftF =>
        val eff = new EffectInstance[F, G] {
          def toG: F ~> G           = U.liftF
          def toF: G ~> F           = unliftF
          implicit def F: Effect[F] = E
        }
        f(eff)
      }

    def concurrentEffect(implicit G: Functor[G], CE: ConcurrentEffect[F]): G[ConcurrentEffect[G]] =
      G.map(U.unlift) { unliftF =>
        new ConcurrentEffectInstance[F, G] {
          def toG: F ~> G                     = U.liftF
          def toF: G ~> F                     = unliftF
          implicit def F: ConcurrentEffect[F] = CE
        }
      }

    def concurrentEffectWith[A](f: ConcurrentEffect[G] => G[A])(implicit G: FlatMap[G], CE: ConcurrentEffect[F]): G[A] =
      G.flatMap(U.unlift) { unliftF =>
        val ce = new ConcurrentEffectInstance[F, G] {
          def toG: F ~> G                     = U.liftF
          def toF: G ~> F                     = unliftF
          implicit def F: ConcurrentEffect[F] = CE
        }
        f(ce)
      }

  }

  private[unlift] trait EffectInstance[F[_], G[_]] extends Effect[G] {
    def toG: F ~> G
    def toF: G ~> F
    implicit def F: Effect[F]

    def pure[A](x: A): G[A] = toG(F.pure(x))

    def flatMap[A, B](ga: G[A])(f: A => G[B]): G[B] = toG(F.flatMap(toF(ga))(a => toF(f(a))))

    def tailRecM[A, B](a: A)(f: A => G[Either[A, B]]): G[B] = toG(F.tailRecM(a)(a => toF(f(a))))

    def raiseError[A](e: Throwable): G[A] = toG(F.raiseError(e))

    def handleErrorWith[A](ga: G[A])(f: Throwable => G[A]): G[A] = toG(F.handleErrorWith(toF(ga))(t => toF(f(t))))

    def bracketCase[A, B](acquire: G[A])(use: A => G[B])(release: (A, ExitCase[Throwable]) => G[Unit]): G[B] =
      toG(F.bracketCase(toF(acquire))(a => toF(use(a)))((a, e) => toF(release(a, e))))

    def suspend[A](thunk: => G[A]): G[A] = toG(F.suspend(toF(thunk)))

    def async[A](k: (Either[Throwable, A] => Unit) => Unit): G[A] = toG(F.async(k))

    def asyncF[A](k: (Either[Throwable, A] => Unit) => G[Unit]): G[A] = toG(F.asyncF[A](cb => toF(k(cb))))

    def runAsync[A](ga: G[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] = F.runAsync(toF(ga))(cb)
  }

  private[unlift] trait ConcurrentEffectInstance[F[_], G[_]] extends EffectInstance[F, G] with ConcurrentEffect[G] {
    implicit def F: ConcurrentEffect[F]

    def start[A](ga: G[A]): G[Fiber[G, A]] = toG(F.map(F.start(toF(ga)))(_.mapK(toG)))

    def racePair[A, B](ga: G[A], gb: G[B]): G[Either[(A, Fiber[G, B]), (Fiber[G, A], B)]] =
      toG(F.map(F.racePair(toF(ga), toF(gb))) {
        case Left((a, fb))  => Left((a, fb.mapK(toG)))
        case Right((fa, b)) => Right((fa.mapK(toG), b))
      })

    def runCancelable[A](ga: G[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[CancelToken[G]] =
      F.runCancelable(toF(ga))(cb).map(toG(_))
  }

} 
Example 14
Source File: UnliftSuite.scala    From tofu   with Apache License 2.0 5 votes vote down vote up
package tofu

import cats.Monad
import cats.effect.{ConcurrentEffect, Effect}
import tofu.lift.Unlift
import tofu.syntax.unlift._

object UnliftSuite {

  private def needsEffect[G[_]: Effect]: G[Unit] = Effect[G].unit

  private def needsConcurrentEffect[G[_]: ConcurrentEffect]: G[Unit] = ConcurrentEffect[G].unit

  def checkUnliftEffectSyntax[F[_]: Effect, G[_]: Monad](implicit U: Unlift[F, G]): Unit = {
    Unlift[F, G].effect: G[Effect[G]]
    Unlift[F, G].effectWith(implicit E => needsEffect[G])
    ()
  }

  def checkUnliftCESyntax[F[_]: ConcurrentEffect, G[_]: Monad](implicit U: Unlift[F, G]): Unit = {
    Unlift[F, G].concurrentEffect: G[ConcurrentEffect[G]]
    Unlift[F, G].concurrentEffectWith(implicit CE => needsConcurrentEffect[G])
    ()
  }

} 
Example 15
Source File: BookingExpirationProcessWiring.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.booking.process

import java.time.Instant
import java.util.concurrent.TimeUnit

import aecor.distributedprocessing.DistributedProcessing
import cats.effect.{Clock, ConcurrentEffect, Timer}
import cats.implicits._
import ru.pavkin.booking.common.streaming.Fs2Process

import scala.concurrent.duration.FiniteDuration

class BookingExpirationProcessWiring[F[_]: ConcurrentEffect: Timer](clock: Clock[F],
                                                                    frequency: FiniteDuration,
                                                                    process: Instant => F[Unit]) {

  val processStream: fs2.Stream[F, Unit] =
    fs2.Stream
      .fixedDelay[F](frequency)
      .evalMap(_ => clock.realTime(TimeUnit.MILLISECONDS).map(Instant.ofEpochMilli))
      .evalMap(process)

  def processes: List[DistributedProcessing.Process[F]] =
    List(Fs2Process(processStream))

} 
Example 16
Source File: package.scala    From fs2-aws   with MIT License 5 votes vote down vote up
package fs2

import cats.effect.concurrent.Deferred
import cats.effect.{ ConcurrentEffect, IO }
import fs2.aws.sqs.{ ConsumerBuilder, ReceiverCallback, SqsConfig }
import fs2.concurrent.Queue
import javax.jms.{ Message, MessageListener }

package object aws {

  def sqsStream[F[_], O](
    sqsConfig: SqsConfig,
    builder: (SqsConfig, MessageListener) => ConsumerBuilder[F],
    d: Option[Deferred[F, MessageListener]] = None
  )(implicit F: ConcurrentEffect[F], decoder: Message => Either[Throwable, O]): fs2.Stream[F, O] =
    for {
      q        <- fs2.Stream.eval(Queue.unbounded[F, Either[Throwable, O]])
      callback <- fs2.Stream.eval(callback(q))
      _        <- fs2.Stream.eval(d.map(_.complete(callback)).getOrElse(F.unit))
      item     <- builder(sqsConfig, callback).serve(q.dequeue.rethrow)
    } yield item

  def callback[F[_], O](queue: Queue[F, Either[Throwable, O]])(
    implicit F: ConcurrentEffect[F],
    decoder: Message => Either[Throwable, O]
  ): F[ReceiverCallback[Either[Throwable, O]]] =
    F.delay(
      new ReceiverCallback[Either[Throwable, O]](r =>
        F.runAsync(queue.enqueue1(r))(_ => IO.unit).unsafeRunSync()
      )
    )

} 
Example 17
Source File: Fs2WebSocketHandler.scala    From sttp   with Apache License 2.0 5 votes vote down vote up
package sttp.client.httpclient.fs2

import cats.effect.{ConcurrentEffect, Sync}
import fs2.concurrent.InspectableQueue
import sttp.client.httpclient.WebSocketHandler
import sttp.client.httpclient.internal.NativeWebSocketHandler
import sttp.client.impl.cats.CatsMonadAsyncError
import sttp.client.impl.cats.implicits._
import sttp.client.impl.fs2.Fs2AsyncQueue
import sttp.client.monad.syntax._
import sttp.client.ws.{WebSocket, WebSocketEvent}

object Fs2WebSocketHandler {

  
  def apply[F[_]: ConcurrentEffect](
      createQueue: F[InspectableQueue[F, WebSocketEvent]]
  ): F[WebSocketHandler[WebSocket[F]]] =
    createQueue.flatMap { queue =>
      Sync[F].delay {
        NativeWebSocketHandler[F](
          new Fs2AsyncQueue[F, WebSocketEvent](queue),
          new CatsMonadAsyncError
        )
      }
    }

} 
Example 18
Source File: JvmMonitoring.scala    From datadog4s   with MIT License 5 votes vote down vote up
package com.avast.datadog4s.extension.jvm

import java.time.Duration

import cats.effect.{ ConcurrentEffect, Resource, Sync, Timer }
import com.avast.cloud.datadog4s.helpers.Repeated
import com.avast.datadog4s.api.MetricFactory

object JvmMonitoring {
  type ErrorHandler[F[_]] = Throwable => F[Unit]

  case class Config(
    delay: Duration = Duration.ofSeconds(60),
    timeout: Duration = Duration.ofSeconds(10)
  )

  def default[F[_]: ConcurrentEffect: Timer](factory: MetricFactory[F]): Resource[F, Unit] =
    configured(factory, Config(), defaultErrorHandler)

  def configured[F[_]: ConcurrentEffect: Timer](
    factory: MetricFactory[F],
    config: Config,
    errorHandler: ErrorHandler[F]
  ): Resource[F, Unit] = {
    val reporter = new JvmReporter[F](factory)

    Repeated.run[F](config.delay, config.timeout, errorHandler)(reporter.collect).map(_ => ())
  }

  private def defaultErrorHandler[F[_]: Sync]: ErrorHandler[F] =
    err =>
      Sync[F].delay {
        println(s"Error during metrics collection: ${err.getMessage}")
        err.printStackTrace()
      }
} 
Example 19
Source File: package.scala    From caliban   with Apache License 2.0 5 votes vote down vote up
package caliban.interop.monix

import caliban.schema.{ Schema, SubscriptionSchema }
import caliban.{ CalibanError, GraphQL, GraphQLInterpreter, GraphQLResponse, InputValue }
import cats.effect.ConcurrentEffect
import monix.eval.Task
import monix.reactive.Observable
import zio.Runtime

package object implicits {

  implicit class MonixGraphQLInterpreter[R, E](underlying: GraphQLInterpreter[R, E]) {

    def executeAsync(
      query: String,
      operationName: Option[String] = None,
      variables: Map[String, InputValue] = Map(),
      extensions: Map[String, InputValue] = Map(),
      skipValidation: Boolean = false,
      enableIntrospection: Boolean = true
    )(implicit runtime: Runtime[R]): Task[GraphQLResponse[E]] =
      MonixInterop.executeAsync(underlying)(
        query,
        operationName,
        variables,
        extensions,
        skipValidation = skipValidation,
        enableIntrospection = enableIntrospection
      )

    def checkAsync(query: String)(implicit runtime: Runtime[R]): Task[Unit] =
      MonixInterop.checkAsync(underlying)(query)
  }

  implicit class MonixGraphQL[R, E](underlying: GraphQL[R]) {

    def interpreterAsync(implicit runtime: Runtime[R]): Task[GraphQLInterpreter[R, CalibanError]] =
      MonixInterop.interpreterAsync(underlying)
  }

  implicit def effectSchema[R, A](implicit ev: Schema[R, A], ev2: ConcurrentEffect[Task]): Schema[R, Task[A]] =
    MonixInterop.taskSchema

  implicit def observableSchema[R, A](
    implicit ev: Schema[R, A],
    ev2: ConcurrentEffect[Task]
  ): Schema[R, Observable[A]] =
    MonixInterop.observableSchema(16) // Size of the internal buffer. Use a power of 2 for best performance.

  implicit def observableSubscriptionSchema[A]: SubscriptionSchema[Observable[A]] =
    new SubscriptionSchema[Observable[A]] {}
} 
Example 20
Source File: MonixInterop.scala    From caliban   with Apache License 2.0 5 votes vote down vote up
package caliban.interop.monix

import caliban.introspection.adt.__Type
import caliban.schema.Step.{ QueryStep, StreamStep }
import caliban.schema.{ Schema, Step, Types }
import caliban.{ CalibanError, GraphQL, GraphQLInterpreter, GraphQLResponse, InputValue }
import cats.effect.ConcurrentEffect
import monix.eval.{ Task => MonixTask }
import monix.reactive.Observable
import zio._
import zio.interop.catz._
import zio.interop.reactivestreams._
import zio.stream.ZStream
import zio.query.ZQuery

object MonixInterop {

  def executeAsync[R, E](graphQL: GraphQLInterpreter[R, E])(
    query: String,
    operationName: Option[String] = None,
    variables: Map[String, InputValue] = Map(),
    extensions: Map[String, InputValue] = Map(),
    skipValidation: Boolean = false,
    enableIntrospection: Boolean = true
  )(implicit runtime: Runtime[R]): MonixTask[GraphQLResponse[E]] =
    MonixTask.async { cb =>
      val execution = graphQL.execute(
        query,
        operationName,
        variables,
        extensions,
        skipValidation = skipValidation,
        enableIntrospection = enableIntrospection
      )
      runtime.unsafeRunAsync(execution)(exit => cb(exit.toEither))
    }

  def checkAsync[R](graphQL: GraphQLInterpreter[R, Any])(query: String)(implicit runtime: Runtime[R]): MonixTask[Unit] =
    MonixTask.async(cb => runtime.unsafeRunAsync(graphQL.check(query))(exit => cb(exit.toEither)))

  def interpreterAsync[R](
    graphQL: GraphQL[R]
  )(implicit runtime: Runtime[R]): MonixTask[GraphQLInterpreter[R, CalibanError]] =
    MonixTask.async(cb => runtime.unsafeRunAsync(graphQL.interpreter)(exit => cb(exit.toEither)))

  def taskSchema[R, A](implicit ev: Schema[R, A], ev2: ConcurrentEffect[MonixTask]): Schema[R, MonixTask[A]] =
    new Schema[R, MonixTask[A]] {
      override def toType(isInput: Boolean, isSubscription: Boolean): __Type = ev.toType(isInput, isSubscription)
      override def optional: Boolean                                         = ev.optional
      override def resolve(value: MonixTask[A]): Step[R] =
        QueryStep(ZQuery.fromEffect(value.to[Task].map(ev.resolve)))
    }

  def observableSchema[R, A](
    queueSize: Int
  )(implicit ev: Schema[R, A], ev2: ConcurrentEffect[MonixTask]): Schema[R, Observable[A]] =
    new Schema[R, Observable[A]] {
      override def optional: Boolean = true
      override def toType(isInput: Boolean, isSubscription: Boolean): __Type = {
        val t = ev.toType(isInput, isSubscription)
        if (isSubscription) t else Types.makeList(if (ev.optional) t else Types.makeNonNull(t))
      }
      override def resolve(value: Observable[A]): Step[R] =
        StreamStep(
          ZStream
            .fromEffect(
              MonixTask
                .deferAction(implicit sc =>
                  MonixTask.eval(value.toReactivePublisher.toStream(queueSize).map(ev.resolve))
                )
                .to[Task]
            )
            .flatten
        )
    }
} 
Example 21
Source File: LaserdiscFs2Suite.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package fs2

import cats.effect.syntax.effect._
import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import laserdisc.auto._
import munit.FunSuite

abstract class LaserdiscFs2Suite[F[_]: ContextShift: Timer: ConcurrentEffect](p: Port) extends FunSuite {

  private var cleanUp: F[Unit]               = _
  protected final var client: RedisClient[F] = _

  override final def beforeAll(): Unit = {
    val (cl, cu) = RedisClient.to("127.0.0.1", p).allocated.toIO.unsafeRunSync()
    cleanUp = cu
    client = cl
  }

  override final def afterAll(): Unit =
    cleanUp.toIO.unsafeRunSync()

  protected def assertAllEqual[A](as: List[A], a: A): Unit =
    as.foreach(assertEquals(_, a))
} 
Example 22
Source File: TestTeamThreeCacheApi.scala    From http4s-poc-api   with MIT License 5 votes vote down vote up
package interpreters

import cats.effect.{ConcurrentEffect, IO, Timer}
import cats.syntax.flatMap._
import external.TeamThreeCacheApi
import log.effect.LogWriter
import model.DomainModel.{Product, ProductId}
import zio.clock.Clock
import zio.interop.catz._
import zio.{Runtime, Task}

import scala.concurrent.duration._

object TestTeamThreeCacheApi {
  @inline def make(productsInCache: Map[ProductId, Product])(testLogger: LogWriter[Task])(
    implicit t: Timer[IO],
    rt: Runtime[Clock]
  ): TeamThreeCacheApi[ProductId, Product] =
    new TeamThreeCacheApi[ProductId, Product] {
      def get: ProductId => IO[Option[Product]] = { id =>
        ConcurrentEffect[Task].toIO(
          testLogger.debug(s"DEP cachedProduct -> Getting the product $id from the cache in test")
        ) >> t.sleep(200.milliseconds) >> IO(productsInCache.get(id))
      }

      def put: ProductId => Product => IO[Unit] = { id => _ =>
        ConcurrentEffect[Task].toIO(
          testLogger.debug(s"DEP storeProductToCache -> Storing the product $id to the repo in test")
        ) >> t.sleep(200.milliseconds) >> IO.unit
      }
    }

  @inline def makeFail(implicit t: Timer[IO]): TeamThreeCacheApi[ProductId, Product] =
    new TeamThreeCacheApi[ProductId, Product] {
      def get: ProductId => IO[Option[Product]] = { _ =>
        t.sleep(300.milliseconds) >> IO.delay(
          throw new Throwable(
            "DependencyFailure. The dependency def cachedProduct: ProductId => Task[Option[Product]] failed with message not responding"
          )
        )
      }

      def put: ProductId => Product => IO[Unit] = { _ => _ =>
        t.sleep(150.milliseconds) >> IO.delay(
          throw new Throwable(
            "DependencyFailure. The dependency def storeProductToCache: ProductId => Product => Task[Unit] failed with message not responding"
          )
        )
      }
    }
} 
Example 23
Source File: TestTeamTwoHttpApi.scala    From http4s-poc-api   with MIT License 5 votes vote down vote up
package interpreters

import cats.effect.{ConcurrentEffect, IO, Timer}
import cats.syntax.flatMap._
import external.TeamTwoHttpApi
import log.effect.LogWriter
import model.DomainModel.{Product, ProductId, User, UserId}
import zio.clock.Clock
import zio.interop.catz._
import zio.{Runtime, Task}

import scala.concurrent.duration._

object TestTeamTwoHttpApi {
  @inline def make(aUser: User, productsInStore: Map[ProductId, Product])(testLogger: LogWriter[Task])(
    implicit t: Timer[IO],
    rt: Runtime[Clock]
  ): TeamTwoHttpApi =
    new TeamTwoHttpApi {
      def user: UserId => IO[User] = { id =>
        ConcurrentEffect[Task].toIO(
          testLogger.debug(s"DEP user -> Getting the user $id in test")
        ) >> t.sleep(1.second) >> IO.delay(aUser)
      }

      def product: ProductId => IO[Option[Product]] = { id =>
        ConcurrentEffect[Task].toIO(
          testLogger.debug(s"DEP product -> Getting the product $id from the store in test")
        ) >> t.sleep(1.second) >> IO(productsInStore.get(id))
      }
    }

  @inline def makeFail(implicit t: Timer[IO]): TeamTwoHttpApi =
    new TeamTwoHttpApi {
      def user: UserId => IO[User] = { _ =>
        t.sleep(200.milliseconds) >> IO.delay(
          throw new Throwable(
            "DependencyFailure. The dependency `UserId => IO[User]` failed with message network failure"
          )
        )
      }

      def product: ProductId => IO[Option[Product]] = { _ =>
        t.sleep(400.milliseconds) >> IO.delay(
          throw new Throwable(
            "DependencyFailure. The dependency `ProductId => IO[Option[Product]]` failed with message network failure"
          )
        )
      }
    }
} 
Example 24
Source File: CatsConcurrentEffectSyntax.scala    From interop-cats   with Apache License 2.0 5 votes vote down vote up
package zio.interop

import cats.effect.ConcurrentEffect
import zio.{ IO, RIO, Runtime, Task, ZIO }

import scala.language.implicitConversions

trait CatsConcurrentEffectSyntax {
  implicit final def ZIOConcurrentEffectOps(@deprecated("", "") zio: ZIO.type): CatsConcurrentEffectSyntax.zioOps.type =
    CatsConcurrentEffectSyntax.zioOps
  implicit final def RIOConcurrentEffectOps(@deprecated("", "") rio: RIO.type): CatsConcurrentEffectSyntax.zioOps.type =
    CatsConcurrentEffectSyntax.zioOps

  implicit final def IOConcurrentEffectOps(@deprecated("", "") io: IO.type): CatsConcurrentEffectSyntax.ioOps.type =
    CatsConcurrentEffectSyntax.ioOps
  implicit final def TaskConcurrentEffectOps(@deprecated("", "") io: Task.type): CatsConcurrentEffectSyntax.ioOps.type =
    CatsConcurrentEffectSyntax.ioOps
}

private[interop] object CatsConcurrentEffectSyntax {
  object zioOps {
    final def concurrentEffect[R]: ZIO[R, Nothing, ConcurrentEffect[RIO[R, *]]] =
      ZIO.runtime.map(catz.taskEffectInstance(_: Runtime[R]))
    final def concurrentEffectWith[R, E, A](f: ConcurrentEffect[RIO[R, *]] => ZIO[R, E, A]): ZIO[R, E, A] =
      ZIO.runtime.flatMap(f apply catz.taskEffectInstance(_: Runtime[R]))
  }
  object ioOps {
    final def concurrentEffect: ZIO[Any, Nothing, ConcurrentEffect[RIO[Any, *]]] =
      ZIO.runtime.map(catz.taskEffectInstance(_: Runtime[Any]))
    def concurrentEffectWith[E, A](f: ConcurrentEffect[RIO[Any, *]] => ZIO[Any, E, A]): ZIO[Any, E, A] =
      ZIO.runtime.flatMap(f apply catz.taskEffectInstance(_: Runtime[Any]))
  }
} 
Example 25
Source File: Http4sBlazeClientModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.http4s.client

import cats.effect.{ConcurrentEffect, Resource}
import javax.net.ssl.SSLContext
import org.http4s.client.Client
import org.http4s.client.blaze.BlazeClientBuilder

import scala.concurrent.ExecutionContext
object Http4sBlazeClientModule {

  
  def make[F[_]: ConcurrentEffect](
      config: Http4sBlazeClientConfig,
      executionContext: ExecutionContext,
      sslContext: Option[SSLContext] = None
  ): Resource[F, Client[F]] = {
    val builder = BlazeClientBuilder[F](executionContext)
      .withResponseHeaderTimeout(config.responseHeaderTimeout)
      .withIdleTimeout(config.idleTimeout)
      .withRequestTimeout(config.requestTimeout)
      .withConnectTimeout(config.connectTimeout)
      .withUserAgent(config.userAgent)
      .withMaxTotalConnections(config.maxTotalConnections)
      .withMaxWaitQueueLimit(config.maxWaitQueueLimit)
      .withMaxConnectionsPerRequestKey(Function.const(config.maxConnectionsPerRequestkey))
      .withCheckEndpointAuthentication(config.checkEndpointIdentification)
      .withMaxResponseLineSize(config.maxResponseLineSize)
      .withMaxHeaderLength(config.maxHeaderLength)
      .withMaxChunkSize(config.maxChunkSize)
      .withChunkBufferMaxSize(config.chunkBufferMaxSize)
      .withParserMode(config.parserMode)
      .withBufferSize(config.bufferSize)

    sslContext.map(builder.withSslContext).getOrElse(builder).resource
  }

} 
Example 26
Source File: Http4sBlazeServerModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.http4s.server

import java.net.{InetSocketAddress, StandardSocketOptions}

import cats.effect.{ConcurrentEffect, Resource, Timer}
import org.http4s.HttpApp
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.Duration

object Http4sBlazeServerModule {

  
  def make[F[_]: ConcurrentEffect: Timer](
      config: Http4sBlazeServerConfig,
      httpApp: HttpApp[F],
      executionContext: ExecutionContext
  ): Resource[F, Server[F]] = {
    for {
      inetSocketAddress <- Resource.liftF(
        ConcurrentEffect[F].delay(
          InetSocketAddress.createUnresolved(config.listenAddress, config.listenPort)
        )
      )
      server <-
        BlazeServerBuilder[F](executionContext)
          .bindSocketAddress(inetSocketAddress)
          .withHttpApp(httpApp)
          .withoutBanner
          .withNio2(config.nio2Enabled)
          .withWebSockets(config.webSocketsEnabled)
          .enableHttp2(config.http2Enabled)
          .withResponseHeaderTimeout(Duration.fromNanos(config.responseHeaderTimeout.toNanos))
          .withIdleTimeout(Duration.fromNanos(config.idleTimeout.toNanos))
          .withBufferSize(config.bufferSize)
          .withMaxRequestLineLength(config.maxRequestLineLength)
          .withMaxHeadersLength(config.maxHeadersLength)
          .withChunkBufferMaxSize(config.chunkBufferMaxSize)
          .withConnectorPoolSize(config.connectorPoolSize)
          .withChannelOption[java.lang.Boolean](StandardSocketOptions.TCP_NODELAY, config.socketOptions.tcpNoDelay)
          .resource
    } yield server
  }
} 
Example 27
Source File: Fs2KafkaModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.fs2kafka

import cats.effect.{Blocker, ConcurrentEffect, ContextShift, Resource, Timer}
import fs2.kafka._

object Fs2KafkaModule {

  def makeConsumer[F[_]: ConcurrentEffect: ContextShift: Timer, K: Deserializer[F, *], V: Deserializer[F, *]](
      config: ConsumerConfig,
      blocker: Option[Blocker] = None,
      createConsumer: Option[Map[String, String] => F[KafkaByteConsumer]] = None
  ): Resource[F, KafkaConsumer[F, K, V]] = {
    def setOpt[A](maybeValue: Option[A])(
        setter: (ConsumerSettings[F, K, V], A) => ConsumerSettings[F, K, V]
    )(initial: ConsumerSettings[F, K, V]): ConsumerSettings[F, K, V] =
      maybeValue match {
        case Some(value) => setter(initial, value)
        case None        => initial
      }

    val settings = ConsumerSettings(implicitly[Deserializer[F, K]], implicitly[Deserializer[F, V]])
      .withBootstrapServers(config.bootstrapServers.mkString(","))
      .withGroupId(config.groupId)
      .pipe(setOpt(config.groupInstanceId)(_.withGroupInstanceId(_)))
      .pipe(setOpt(config.clientId)(_.withClientId(_)))
      .pipe(setOpt(config.clientRack)(_.withClientRack(_)))
      .withAutoOffsetReset(config.autoOffsetReset)
      .withEnableAutoCommit(config.enableAutoCommit)
      .withAutoCommitInterval(config.autoCommitInterval)
      .withAllowAutoCreateTopics(config.allowAutoCreateTopics)
      .withCloseTimeout(config.closeTimeout)
      .withCommitRecovery(config.commitRecovery)
      .withCommitTimeout(config.closeTimeout)
      .withDefaultApiTimeout(config.defaultApiTimeout)
      .withHeartbeatInterval(config.heartbeatInterval)
      .withIsolationLevel(config.isolationLevel)
      .withMaxPrefetchBatches(config.maxPrefetchBatches)
      .withPollInterval(config.pollInterval)
      .withPollTimeout(config.pollTimeout)
      .withMaxPollInterval(config.maxPollInterval)
      .withMaxPollRecords(config.maxPollRecords)
      .withRequestTimeout(config.requestTimeout)
      .withSessionTimeout(config.sessionTimeout)
      .pipe(setOpt(blocker)(_.withBlocker(_)))
      .withProperties(config.properties)
      .pipe(setOpt(createConsumer)(_.withCreateConsumer(_)))

    makeConsumer(settings)
  }

  def makeConsumer[F[_]: ConcurrentEffect: ContextShift: Timer, K, V](
      settings: ConsumerSettings[F, K, V]
  ): Resource[F, KafkaConsumer[F, K, V]] = consumerResource[F].using(settings)

  def makeProducer[F[_]: ConcurrentEffect: ContextShift, K: Serializer[F, *], V: Serializer[F, *]](
      config: ProducerConfig,
      blocker: Option[Blocker] = None,
      createProducer: Option[Map[String, String] => F[KafkaByteProducer]] = None
  ): Resource[F, KafkaProducer[F, K, V]] = {
    def setOpt[A](maybeValue: Option[A])(
        setter: (ProducerSettings[F, K, V], A) => ProducerSettings[F, K, V]
    )(initial: ProducerSettings[F, K, V]): ProducerSettings[F, K, V] =
      maybeValue match {
        case Some(value) => setter(initial, value)
        case None        => initial
      }

    val settings = ProducerSettings(implicitly[Serializer[F, K]], implicitly[Serializer[F, V]])
      .withBootstrapServers(config.bootstrapServers.mkString(","))
      .pipe(setOpt(config.clientId)(_.withClientId(_)))
      .withAcks(config.acks)
      .withBatchSize(config.batchSize)
      .withCloseTimeout(config.closeTimeout)
      .withDeliveryTimeout(config.deliveryTimeout)
      .withRequestTimeout(config.requestTimeout)
      .withLinger(config.linger)
      .withEnableIdempotence(config.enableIdempotence)
      .withMaxInFlightRequestsPerConnection(config.maxInFlightRequestsPerConnection)
      .withParallelism(config.parallelism)
      .withRetries(config.retries)
      .pipe(setOpt(blocker)(_.withBlocker(_)))
      .withProperties(config.properties)
      .pipe(setOpt(createProducer)(_.withCreateProducer(_)))

    makeProducer(settings)
  }

  def makeProducer[F[_]: ConcurrentEffect: ContextShift, K, V](settings: ProducerSettings[F, K, V]): Resource[F, KafkaProducer[F, K, V]] =
    producerResource[F].using(settings)

  
  implicit private final class ChainingOps[A](private val self: A) extends AnyVal {
    def pipe[B](f: A => B): B = f(self)
  }

} 
Example 28
Source File: Influx.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.modules.influx

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, ExitCode, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.AbstractCommand
import com.monovore.decline.Opts
import distage.TagK
import izumi.distage.model.recursive.LocatorRef


final class Influx[F[_]: Timer: Parallel: ContextShift: TagK](locatorOpt: Option[LocatorRef])(implicit
    F: ConcurrentEffect[F]
) extends AbstractCommand[F](locatorOpt) {

  def subcommand: Opts[F[ExitCode]] =
    Opts.subcommand("influxdb", "influxDB projection.") {
      run
    }

  def run: Opts[F[ExitCode]] =
    Opts.subcommand("run", "Runs the influxDB projection") {
      locatorResource.map { _.use { locator => locator.get[InfluxProjection[F]].run.as(ExitCode.Success) } }
    }

}

object Influx {

  final def apply[F[_]: TagK: ConcurrentEffect: Timer: Parallel: ContextShift](
      locatorOpt: Option[LocatorRef] = None
  ): Influx[F] =
    new Influx[F](locatorOpt)

} 
Example 29
Source File: Http4sRpcServer.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.network.rpc.http

import cats.effect.{ConcurrentEffect, Resource, Sync, Timer}
import cats.implicits._
import io.circe.Json
import io.circe.syntax._
import jbok.network.rpc.{RpcRequest, RpcService}
import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityCodec._
import org.http4s.dsl.Http4sDsl
import org.http4s.implicits._
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder

object Http4sRpcServer {
  def routes[F[_]](service: RpcService[F, Json])(implicit F: Sync[F]): HttpRoutes[F] = {
    val dsl = Http4sDsl[F]
    import dsl._

    HttpRoutes.of[F] {
      case req @ POST -> path =>
        for {
          json   <- req.as[Json]
          result <- service.handle(RpcRequest(path.toList, json))
          resp   <- Ok(result.asJson)
        } yield resp
    }
  }

  def server[F[_]](service: RpcService[F, Json])(implicit F: ConcurrentEffect[F], T: Timer[F]): Resource[F, Server[F]] =
    BlazeServerBuilder[F]
      .bindLocal(0)
      .withHttpApp(routes[F](service).orNotFound)
      .withWebSockets(true)
      .resource
} 
Example 30
Source File: CORSMiddleware.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.network.http.server.middleware

import cats.effect.ConcurrentEffect
import org.http4s.HttpApp
import org.http4s.server.middleware.{CORS, CORSConfig}

import scala.concurrent.duration._

object CORSMiddleware {
  val defaultConfig: CORSConfig = CORSConfig(
    anyOrigin = true,
    allowCredentials = true,
    maxAge = 1.day.toSeconds,
    anyMethod = true
  )

  private def corsConfig(allowedOriginsList: List[String]) =
    if (allowedOriginsList.isEmpty) {
      defaultConfig
    } else {
      defaultConfig.copy(anyOrigin = false, allowedOrigins = allowedOriginsList.toSet)
    }

  def apply[F[_]](http: HttpApp[F], allowedOrigins: List[String])(implicit F: ConcurrentEffect[F]): HttpApp[F] =
    CORS(http, corsConfig(allowedOrigins))
} 
Example 31
Source File: HttpService.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.service

import cats.effect.{ConcurrentEffect, Resource, Timer}
import io.circe.Json
import cats.implicits._
import fs2._
import javax.net.ssl.SSLContext
import jbok.network.http.server.middleware.{CORSMiddleware, GzipMiddleware, LoggerMiddleware, MetricsMiddleware}
import jbok.core.config.ServiceConfig
import jbok.core.api._
import jbok.crypto.ssl.SSLConfig
import jbok.network.rpc.RpcService
import jbok.network.rpc.http.Http4sRpcServer
import org.http4s.HttpRoutes
import org.http4s.implicits._
import org.http4s.server.{SSLClientAuthMode, Server}
import org.http4s.server.blaze.BlazeServerBuilder

final class HttpService[F[_]](
    config: ServiceConfig,
    sslConfig: SSLConfig,
    account: AccountAPI[F],
    admin: AdminAPI[F],
    block: BlockAPI[F],
    contract: ContractAPI[F],
    miner: MinerAPI[F],
    personal: PersonalAPI[F],
    transaction: TransactionAPI[F],
    sslOpt: Option[SSLContext]
)(implicit F: ConcurrentEffect[F], T: Timer[F]) {
  import jbok.codec.impl.circe._
  import _root_.io.circe.generic.auto._
  import jbok.codec.json.implicits._

  val rpcService: RpcService[F, Json] = {
    var service = RpcService[F, Json]
    if (config.apis.contains("account")) service = service.mount(account) else ()
    if (config.apis.contains("admin")) service = service.mount(admin) else ()
    if (config.apis.contains("block")) service = service.mount(block) else ()
    if (config.apis.contains("contract")) service = service.mount(contract) else ()
    if (config.apis.contains("miner")) service = service.mount(miner) else ()
    if (config.apis.contains("personal")) service = service.mount(personal) else ()
    if (config.apis.contains("transaction")) service = service.mount(transaction) else ()
    service
  }

  val routes: HttpRoutes[F] = Http4sRpcServer.routes(rpcService)

  private val builder: F[BlazeServerBuilder[F]] = {
    val httpApp = for {
      exportRoute <- MetricsMiddleware.exportService[F]
      withMetrics <- MetricsMiddleware[F](routes, config.enableMetrics)
      withLogger = LoggerMiddleware[F](config.logHeaders, config.logBody)((withMetrics <+> exportRoute).orNotFound)
      withCORS   = CORSMiddleware[F](withLogger, config.allowedOrigins)
      app        = GzipMiddleware[F](withCORS)
    } yield app

    val builder = httpApp.map { app =>
      BlazeServerBuilder[F]
        .withHttpApp(app)
        .withNio2(true)
        .enableHttp2(config.enableHttp2)
        .withWebSockets(config.enableWebsockets)
        .bindHttp(config.port, config.local)
    }

    val sslLClientAuthMode = sslConfig.clientAuth match {
      case "NotRequested" => SSLClientAuthMode.NotRequested
      case "Requested"    => SSLClientAuthMode.Requested
      case "Required"     => SSLClientAuthMode.Requested
      case x              => throw new IllegalArgumentException(s"SSLClientAuthMode ${x} is not supported")
    }

    sslOpt match {
      case Some(ssl) => builder.map(_.withSSLContext(ssl, sslLClientAuthMode))
      case None      => builder.map(_.enableHttp2(false))
    }
  }

  val resource: Resource[F, Server[F]] =
    Resource.liftF(builder).flatMap(_.resource)

  val stream: Stream[F, Unit] =
    if (config.enable) {
      Stream.eval(builder).flatMap(_.serve).drain
    } else {
      Stream.empty
    }
} 
Example 32
Source File: JbokClientPlatform.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app

import java.net.URI

import cats.effect.ConcurrentEffect
import io.circe.Json
import jbok.network.http.HttpTransport
import jbok.network.rpc.RpcClient
import jbok.core.api._

object JbokClientPlatform {
  import jbok.codec.impl.circe._
  import io.circe.generic.auto._
  import jbok.codec.json.implicits._

  def apply[F[_]](url: String)(implicit F: ConcurrentEffect[F]): JbokClient[F] = {
    val transport = HttpTransport[F](url)
    val rpc       = RpcClient[F, Json](transport)
    new JbokClient[F] {
      override def uri: URI                       = new URI(url)
      override def client: RpcClient[F, Json]     = rpc
      override def account: AccountAPI[F]         = rpc.use[AccountAPI[F]]
      override def admin: AdminAPI[F]             = rpc.use[AdminAPI[F]]
      override def block: BlockAPI[F]             = rpc.use[BlockAPI[F]]
      override def contract: ContractAPI[F]       = rpc.use[ContractAPI[F]]
      override def miner: MinerAPI[F]             = rpc.use[MinerAPI[F]]
      override def personal: PersonalAPI[F]       = rpc.use[PersonalAPI[F]]
      override def transaction: TransactionAPI[F] = rpc.use[TransactionAPI[F]]
    }
  }
} 
Example 33
Source File: CoreNode.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.core

import cats.effect.concurrent.Ref
import cats.effect.{ConcurrentEffect, Timer}
import cats.implicits._
import fs2._
import jbok.common.log.Logger
import jbok.core.config.FullConfig
import jbok.core.ledger.{BlockExecutor, History}
import jbok.core.mining.BlockMiner
import jbok.core.peer.{PeerManager, PeerMessageHandler}
import jbok.core.pool.TxPool
import jbok.core.sync.SyncClient
import scala.concurrent.duration._

final case class CoreNode[F[_]](
    config: FullConfig,
    nodeStatus: Ref[F, NodeStatus],
    history: History[F],
    peerManager: PeerManager[F],
    executor: BlockExecutor[F],
    miner: BlockMiner[F],
    txPool: TxPool[F],
    handler: PeerMessageHandler[F],
    syncClient: SyncClient[F]
)(implicit F: ConcurrentEffect[F], T: Timer[F]) {
  private val log = Logger[F]

  val logStatus: Stream[F, Unit] =
    Stream.eval {
      for {
        number <- history.getBestBlockNumber
        td     <- history.getTotalDifficultyByNumber(number).map(_.getOrElse(BigInt(0)))
        status <- nodeStatus.get
        _      <- log.i(s"status=${status},bestNumber=${number},td=${td}")
        _      <- T.sleep(10.seconds)
      } yield ()
    }.repeat

  val stream: Stream[F, Unit] = Stream(
    peerManager.stream,
    miner.stream,
    txPool.stream,
    executor.stream,
    handler.stream,
    syncClient.stream,
    syncClient.checkSeedConnect,
    syncClient.heartBeatStream,
    syncClient.statusStream,
    logStatus
  ).parJoinUnbounded
    .handleErrorWith(e => Stream.eval(log.e("CoreNode has an unhandled failure", e)))
} 
Example 34
Source File: SftpStore.scala    From fs2-blobstore   with Apache License 2.0 5 votes vote down vote up
package blobstore
package sftp

import java.util.Date

import com.jcraft.jsch._
import cats.instances.option._

import scala.util.Try
import java.io.OutputStream

import cats.Traverse
import cats.effect.{Blocker, ConcurrentEffect, ContextShift, IO, Resource}
import cats.effect.concurrent.{MVar, Semaphore}
import fs2.concurrent.Queue

final class SftpStore[F[_]](
  absRoot: String,
  session: Session,
  blocker: Blocker,
  mVar: MVar[F, ChannelSftp],
  semaphore: Option[Semaphore[F]],
  connectTimeout: Int
)(implicit F: ConcurrentEffect[F], CS: ContextShift[F]) extends Store[F] {
  import implicits._

  import Path.SEP

  private val openChannel: F[ChannelSftp] = {
    val openF = blocker.delay{
      val ch = session.openChannel("sftp").asInstanceOf[ChannelSftp]
      ch.connect(connectTimeout)
      ch
    }
    semaphore.fold(openF){s =>
      F.ifM(s.tryAcquire)(openF, getChannel)
    }
  }

  private val getChannel = F.flatMap(mVar.tryTake) {
    case Some(channel) => F.pure(channel)
    case None => openChannel
  }

  private def channelResource: Resource[F, ChannelSftp] = Resource.make{
    getChannel
  }{
    case ch if ch.isClosed => F.unit
    case ch => F.ifM(mVar.tryPut(ch))(F.unit, SftpStore.closeChannel(semaphore, blocker)(ch))
  }

  
  def apply[F[_]](
    absRoot: String,
    fa: F[Session],
    blocker: Blocker,
    maxChannels: Option[Long] = None,
    connectTimeout: Int = 10000
  )(implicit F: ConcurrentEffect[F], CS: ContextShift[F]): fs2.Stream[F, SftpStore[F]] =
    if (maxChannels.exists(_ < 1)) {
      fs2.Stream.raiseError[F](new IllegalArgumentException(s"maxChannels must be >= 1"))
    } else {
      for {
        session <- fs2.Stream.bracket(fa)(session => F.delay(session.disconnect()))
        semaphore <- fs2.Stream.eval(Traverse[Option].sequence(maxChannels.map(Semaphore.apply[F])))
        mVar <- fs2.Stream.bracket(MVar.empty[F, ChannelSftp])(mVar => F.flatMap(mVar.tryTake)(_.fold(F.unit)(closeChannel[F](semaphore, blocker))))
      } yield new SftpStore[F](absRoot, session, blocker, mVar, semaphore, connectTimeout)
    }

  private def closeChannel[F[_]](semaphore: Option[Semaphore[F]], blocker: Blocker)(ch: ChannelSftp)(implicit F: ConcurrentEffect[F], CS: ContextShift[F]): F[Unit] =
    F.productR(semaphore.fold(F.unit)(_.release))(blocker.delay(ch.disconnect()))
} 
Example 35
Source File: Hook.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.api.sources

import canoe.api.{TelegramClient}
import canoe.methods.webhooks.{DeleteWebhook, SetWebhook}
import canoe.models.{InputFile, Update}
import canoe.syntax.methodOps
import cats.Monad
import cats.effect.{ConcurrentEffect, Resource, Timer}
import cats.syntax.all._
import fs2.Stream
import fs2.concurrent.Queue
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import org.http4s._
import org.http4s.circe.jsonOf
import org.http4s.dsl.Http4sDsl
import org.http4s.implicits._
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder

class Hook[F[_]](queue: Queue[F, Update]) {
  def updates: Stream[F, Update] = queue.dequeue
}

object Hook {

  
  private def listenServer[F[_]: ConcurrentEffect: Timer: Logger](port: Int): Resource[F, Hook[F]] = {
    val dsl = Http4sDsl[F]
    import dsl._

    def app(queue: Queue[F, Update]): HttpApp[F] =
      HttpRoutes
        .of[F] {
          case req @ POST -> Root =>
            req
              .decodeWith(jsonOf[F, Update], strict = true)(queue.enqueue1(_) *> Ok())
              .recoverWith {
                case InvalidMessageBodyFailure(details, _) =>
                  F.error(s"Received unknown type of update. $details") *> Ok()
              }
        }
        .orNotFound

    def server(queue: Queue[F, Update]): Resource[F, Server[F]] =
      BlazeServerBuilder[F].bindHttp(port).withHttpApp(app(queue)).resource

    Resource.suspend(Queue.unbounded[F, Update].map(q => server(q).map(_ => new Hook[F](q))))
  }
} 
Example 36
Source File: Fs2StreamClientCallListener.scala    From fs2-grpc   with MIT License 5 votes vote down vote up
package org.lyranthe.fs2_grpc
package java_runtime
package client

import cats.effect.{Effect, ConcurrentEffect}
import cats.implicits._
import fs2.{Pull, Stream}
import fs2.concurrent.Queue
import io.grpc.{ClientCall, Metadata, Status}

class Fs2StreamClientCallListener[F[_]: Effect, Response](
    request: Int => Unit,
    queue: Queue[F, Either[GrpcStatus, Response]]
) extends ClientCall.Listener[Response] {

  override def onMessage(message: Response): Unit = {
    request(1)
    queue.enqueue1(message.asRight).unsafeRun()
  }

  override def onClose(status: Status, trailers: Metadata): Unit =
    queue.enqueue1(GrpcStatus(status, trailers).asLeft).unsafeRun()

  def stream: Stream[F, Response] = {

    def go(q: Stream[F, Either[GrpcStatus, Response]]): Pull[F, Response, Unit] = {
      q.pull.uncons1.flatMap {
        case Some((Right(v), tl)) => Pull.output1(v) >> go(tl)
        case Some((Left(GrpcStatus(status, trailers)), _)) =>
          if (!status.isOk)
            Pull.raiseError[F](status.asRuntimeException(trailers))
          else
            Pull.done
        case None => Pull.done
      }
    }

    go(queue.dequeue).stream
  }
}

object Fs2StreamClientCallListener {

  def apply[F[_]: ConcurrentEffect, Response](request: Int => Unit): F[Fs2StreamClientCallListener[F, Response]] =
    Queue.unbounded[F, Either[GrpcStatus, Response]].map(new Fs2StreamClientCallListener[F, Response](request, _))

} 
Example 37
Source File: Fs2StreamServerCallListener.scala    From fs2-grpc   with MIT License 5 votes vote down vote up
package org.lyranthe.fs2_grpc
package java_runtime
package server

import cats.effect.concurrent.Deferred
import cats.effect.{ConcurrentEffect, Effect}
import cats.implicits._
import io.grpc.ServerCall
import fs2.concurrent.Queue
import fs2._

class Fs2StreamServerCallListener[F[_], Request, Response] private (
    requestQ: Queue[F, Option[Request]],
    val isCancelled: Deferred[F, Unit],
    val call: Fs2ServerCall[F, Request, Response]
)(implicit F: Effect[F])
    extends ServerCall.Listener[Request]
    with Fs2ServerCallListener[F, Stream[F, ?], Request, Response] {

  override def onCancel(): Unit = {
    isCancelled.complete(()).unsafeRun()
  }

  override def onMessage(message: Request): Unit = {
    call.call.request(1)
    requestQ.enqueue1(message.some).unsafeRun()
  }

  override def onHalfClose(): Unit = requestQ.enqueue1(none).unsafeRun()

  override def source: Stream[F, Request] =
    requestQ.dequeue.unNoneTerminate
}

object Fs2StreamServerCallListener {
  class PartialFs2StreamServerCallListener[F[_]](val dummy: Boolean = false) extends AnyVal {

    def apply[Request, Response](
        call: ServerCall[Request, Response],
        options: ServerCallOptions = ServerCallOptions.default
    )(implicit
        F: ConcurrentEffect[F]
    ): F[Fs2StreamServerCallListener[F, Request, Response]] =
      for {
        inputQ <- Queue.unbounded[F, Option[Request]]
        isCancelled <- Deferred[F, Unit]
        serverCall <- Fs2ServerCall[F, Request, Response](call, options)
      } yield new Fs2StreamServerCallListener[F, Request, Response](inputQ, isCancelled, serverCall)
  }

  def apply[F[_]] = new PartialFs2StreamServerCallListener[F]

} 
Example 38
Source File: Fs2UnaryServerCallListener.scala    From fs2-grpc   with MIT License 5 votes vote down vote up
package org.lyranthe.fs2_grpc
package java_runtime
package server

import cats.effect.{ConcurrentEffect, Effect}
import cats.effect.concurrent.{Deferred, Ref}
import cats.syntax.all._
import io.grpc._

class Fs2UnaryServerCallListener[F[_], Request, Response] private (
    request: Ref[F, Option[Request]],
    isComplete: Deferred[F, Unit],
    val isCancelled: Deferred[F, Unit],
    val call: Fs2ServerCall[F, Request, Response]
)(implicit F: Effect[F])
    extends ServerCall.Listener[Request]
    with Fs2ServerCallListener[F, F, Request, Response] {

  import Fs2UnaryServerCallListener._

  override def onCancel(): Unit = {
    isCancelled.complete(()).unsafeRun()
  }

  override def onMessage(message: Request): Unit = {
    request.access
      .flatMap[Unit] {
        case (curValue, modify) =>
          if (curValue.isDefined)
            F.raiseError(statusException(TooManyRequests))
          else
            modify(message.some).void
      }
      .unsafeRun()

  }

  override def onHalfClose(): Unit =
    isComplete.complete(()).unsafeRun()

  override def source: F[Request] =
    for {
      _ <- isComplete.get
      valueOrNone <- request.get
      value <- valueOrNone.fold[F[Request]](F.raiseError(statusException(NoMessage)))(F.pure)
    } yield value
}

object Fs2UnaryServerCallListener {

  val TooManyRequests: String = "Too many requests"
  val NoMessage: String = "No message for unary call"

  private val statusException: String => StatusRuntimeException = msg =>
    new StatusRuntimeException(Status.INTERNAL.withDescription(msg))

  class PartialFs2UnaryServerCallListener[F[_]](val dummy: Boolean = false) extends AnyVal {

    def apply[Request, Response](
        call: ServerCall[Request, Response],
        options: ServerCallOptions = ServerCallOptions.default
    )(implicit
        F: ConcurrentEffect[F]
    ): F[Fs2UnaryServerCallListener[F, Request, Response]] =
      for {
        request <- Ref.of[F, Option[Request]](none)
        isComplete <- Deferred[F, Unit]
        isCancelled <- Deferred[F, Unit]
        serverCall <- Fs2ServerCall[F, Request, Response](call, options)
      } yield new Fs2UnaryServerCallListener[F, Request, Response](request, isComplete, isCancelled, serverCall)
  }

  def apply[F[_]] = new PartialFs2UnaryServerCallListener[F]
} 
Example 39
Source File: PubSubInternals.scala    From redis4cats   with Apache License 2.0 5 votes vote down vote up
package dev.profunktor.redis4cats.pubsub.internals

import cats.effect.ConcurrentEffect
import cats.effect.concurrent.Ref
import cats.effect.syntax.effect._
import cats.syntax.all._
import dev.profunktor.redis4cats.data.RedisChannel
import dev.profunktor.redis4cats.effect.Log
import fs2.concurrent.Topic
import io.lettuce.core.pubsub.{ RedisPubSubListener, StatefulRedisPubSubConnection }

object PubSubInternals {

  private[redis4cats] def defaultListener[F[_]: ConcurrentEffect, K, V](
      channel: RedisChannel[K],
      topic: Topic[F, Option[V]]
  ): RedisPubSubListener[K, V] =
    new RedisPubSubListener[K, V] {
      override def message(ch: K, msg: V): Unit =
        if (ch == channel.underlying) {
          topic.publish1(Option(msg)).toIO.unsafeRunAsync(_ => ())
        }
      override def message(pattern: K, channel: K, message: V): Unit = this.message(channel, message)
      override def psubscribed(pattern: K, count: Long): Unit        = ()
      override def subscribed(channel: K, count: Long): Unit         = ()
      override def unsubscribed(channel: K, count: Long): Unit       = ()
      override def punsubscribed(pattern: K, count: Long): Unit      = ()
    }

  private[redis4cats] def apply[F[_]: ConcurrentEffect: Log, K, V](
      state: Ref[F, PubSubState[F, K, V]],
      subConnection: StatefulRedisPubSubConnection[K, V]
  ): GetOrCreateTopicListener[F, K, V] = { channel => st =>
    st.get(channel.underlying)
      .fold {
        Topic[F, Option[V]](None).flatTap { topic =>
          val listener = defaultListener(channel, topic)
          F.info(s"Creating listener for channel: $channel") *>
            F.delay(subConnection.addListener(listener)) *>
            state.update(_.updated(channel.underlying, topic))
        }
      }(F.pure)
  }

} 
Example 40
Source File: Http4sRpcTransport.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.network.rpc.http

import cats.effect.ConcurrentEffect
import jbok.network.rpc.{RpcRequest, RpcResponse, RpcTransport}
import org.http4s.client.blaze.BlazeClientBuilder
import org.http4s.{EntityDecoder, EntityEncoder, Method, Request, Uri}

import scala.concurrent.ExecutionContext

final class Http4sRpcTransport[F[_], P](
    baseUri: Uri
)(implicit F: ConcurrentEffect[F], entityEncoder: EntityEncoder[F, P], entityDecoder: EntityDecoder[F, RpcResponse[P]])
    extends RpcTransport[F, P] {

  override def fetch(request: RpcRequest[P]): F[RpcResponse[P]] = {
    val uri = request.path.foldLeft(baseUri)(_ / _)

    val req = Request[F](Method.POST, uri = uri).withEntity(request.payload)

    BlazeClientBuilder[F](ExecutionContext.global).resource.use { client =>
      client.fetchAs[RpcResponse[P]](req)
    }
  }
} 
Example 41
Source File: Postgres.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.modules.postgres

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, ExitCode, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.AbstractCommand
import com.monovore.decline.Opts
import distage.TagK
import izumi.distage.model.recursive.LocatorRef


final class Postgres[F[_]: Timer: Parallel: ContextShift: TagK](locatorOpt: Option[LocatorRef])(implicit
    F: ConcurrentEffect[F]
) extends AbstractCommand[F](locatorOpt) {

  def subcommand: Opts[F[ExitCode]] =
    Opts.subcommand("postgres", "Postgres database projection.") {
      run
    }

  def run: Opts[F[ExitCode]] =
    Opts.subcommand("run", "Runs the postgres database projection") {
      locatorResource.map { _.use { locator => locator.get[PostgresProjection[F]].run.as(ExitCode.Success) } }
    }

}

object Postgres {

  final def apply[F[_]: TagK: ConcurrentEffect: Timer: Parallel: ContextShift](
      locatorOpt: Option[LocatorRef] = None
  ): Postgres[F] =
    new Postgres[F](locatorOpt)

} 
Example 42
Source File: PostgresModule.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.modules.postgres

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import ch.epfl.bluebrain.nexus.cli.config.AppConfig
import distage.{ModuleDef, TagK}
import doobie.util.transactor.Transactor
import izumi.distage.model.definition.StandardAxis.Repo
import izumi.distage.model.recursive.LocatorRef

final class PostgresModule[F[_]: Parallel: ContextShift: ConcurrentEffect: Timer: TagK] extends ModuleDef {
  make[Postgres[F]].tagged(Repo.Prod).from { locatorRef: LocatorRef => Postgres[F](Some(locatorRef)) }
  make[Transactor[F]].tagged(Repo.Prod).from { (cfg: AppConfig) =>
    Transactor.fromDriverManager[F](
      "org.postgresql.Driver",
      cfg.postgres.jdbcUrl,
      cfg.postgres.username,
      cfg.postgres.password
    )
  }
  make[PostgresProjection[F]].tagged(Repo.Prod)
}

object PostgresModule {
  final def apply[F[_]: Parallel: ContextShift: ConcurrentEffect: Timer: TagK]: PostgresModule[F] =
    new PostgresModule[F]
} 
Example 43
Source File: Config.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.modules.config

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, ExitCode, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.config.AppConfig
import ch.epfl.bluebrain.nexus.cli.{AbstractCommand, Console}
import com.monovore.decline.Opts
import com.typesafe.config.ConfigRenderOptions
import distage.TagK
import izumi.distage.model.recursive.LocatorRef
import pureconfig.ConfigWriter


final class Config[F[_]: Timer: Parallel: ContextShift: TagK](locatorOpt: Option[LocatorRef])(implicit
    F: ConcurrentEffect[F]
) extends AbstractCommand[F](locatorOpt) {

  def subcommand: Opts[F[ExitCode]] =
    Opts.subcommand("config", "Read or write the tool configuration.") {
      show
    }

  private def show: Opts[F[ExitCode]] =
    Opts.subcommand("show", "Print the current configuration") {
      locatorResource.map {
        _.use { locator =>
          val console = locator.get[Console[F]]
          val cfg     = locator.get[AppConfig]
          console.println(renderConfig(cfg)).as(ExitCode.Success)
        }
      }
    }

  private def renderConfig(cfg: AppConfig): String = {
    val opts = ConfigRenderOptions.concise().setComments(false).setJson(false).setFormatted(true)
    ConfigWriter[AppConfig].to(cfg).render(opts)
  }
}

object Config {
  final def apply[F[_]: TagK: ConcurrentEffect: Timer: Parallel: ContextShift](
      locatorOpt: Option[LocatorRef] = None
  ): Config[F] =
    new Config[F](locatorOpt)
} 
Example 44
Source File: CliModule.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli

import cats.effect.concurrent.Ref
import cats.effect.{ConcurrentEffect, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.clients._
import ch.epfl.bluebrain.nexus.cli.config.AppConfig
import ch.epfl.bluebrain.nexus.cli.sse.{OrgLabel, OrgUuid, ProjectLabel, ProjectUuid}
import distage.{ModuleDef, TagK}
import izumi.distage.model.definition.StandardAxis.Repo
import org.http4s.client.Client
import org.http4s.client.blaze.BlazeClientBuilder

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.Duration

final class CliModule[F[_]: ConcurrentEffect: Timer: TagK] extends ModuleDef {

  make[Console[F]].tagged(Repo.Prod).from(Console[F])

  make[Client[F]].tagged(Repo.Prod).fromResource {
    BlazeClientBuilder[F](ExecutionContext.global).withIdleTimeout(Duration.Inf).resource
  }

  make[ProjectClient[F]].tagged(Repo.Prod).fromEffect { (cfg: AppConfig, client: Client[F], console: Console[F]) =>
    Ref.of[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]](Map.empty).map { cache =>
      ProjectClient(client, cfg.env, cache, console)
    }
  }

  make[SparqlClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], console: Console[F]) =>
    SparqlClient(client, cfg.env, console)
  }

  make[EventStreamClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], pc: ProjectClient[F]) =>
    EventStreamClient(client, pc, cfg.env)
  }

  make[InfluxClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], console: Console[F]) =>
    InfluxClient(client, cfg, console)
  }
}

object CliModule {

  final def apply[F[_]: ConcurrentEffect: Timer: TagK]: CliModule[F] =
    new CliModule[F]

} 
Example 45
Source File: AbstractCommand.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, Resource, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.CliOpts._
import ch.epfl.bluebrain.nexus.cli.config.AppConfig
import ch.epfl.bluebrain.nexus.cli.modules.config.ConfigModule
import ch.epfl.bluebrain.nexus.cli.modules.influx.InfluxModule
import ch.epfl.bluebrain.nexus.cli.modules.postgres.PostgresModule
import com.monovore.decline.Opts
import distage.{Injector, TagK}
import izumi.distage.model.Locator
import izumi.distage.model.definition.StandardAxis.Repo
import izumi.distage.model.definition.{Activation, Module, ModuleDef}
import izumi.distage.model.plan.Roots
import izumi.distage.model.recursive.LocatorRef

abstract class AbstractCommand[F[_]: TagK: Timer: ContextShift: Parallel](locatorOpt: Option[LocatorRef])(implicit
    F: ConcurrentEffect[F]
) {

  protected def locatorResource: Opts[Resource[F, Locator]] =
    locatorOpt match {
      case Some(value) => Opts(Resource.make(F.delay(value.get))(_ => F.unit))
      case None        =>
        (envConfig.orNone, postgresConfig.orNone, influxConfig.orNone, token.orNone).mapN {
          case (e, p, i, t) =>
            val res: Resource[F, Module] = Resource.make({
              AppConfig.load[F](e, p, i, t).flatMap[Module] {
                case Left(err)    => F.raiseError(err)
                case Right(value) =>
                  val effects  = EffectModule[F]
                  val cli      = CliModule[F]
                  val config   = ConfigModule[F]
                  val postgres = PostgresModule[F]
                  val influx   = InfluxModule[F]
                  val modules  = effects ++ cli ++ config ++ postgres ++ influx ++ new ModuleDef {
                    make[AppConfig].from(value)
                  }
                  F.pure(modules)
              }
            })(_ => F.unit)

            res.flatMap { modules =>
              Injector(Activation(Repo -> Repo.Prod)).produceF[F](modules, Roots.Everything).toCats
            }
        }
    }
} 
Example 46
Source File: InfluxDocker.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.influx

import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import distage.TagK
import izumi.distage.docker.Docker.{ContainerConfig, DockerPort}
import izumi.distage.docker.modules.DockerSupportModule
import izumi.distage.docker.{ContainerDef, Docker}
import izumi.distage.model.definition.ModuleDef
import org.http4s.Uri

object InfluxDocker extends ContainerDef {

  val primaryPort: DockerPort = DockerPort.TCP(8086)

  override def config: InfluxDocker.Config =
    ContainerConfig(
      image = "library/influxdb:1.8.0",
      ports = Seq(primaryPort),
      env = Map("INFLUXDB_REPORTING_DISABLED" -> "true", "INFLUXDB_HTTP_FLUX_ENABLED" -> "true"),
      reuse = true
    )

  class Module[F[_]: ConcurrentEffect: ContextShift: Timer: TagK] extends ModuleDef {
    make[InfluxDocker.Container].fromResource {
      InfluxDocker.make[F]
    }

    make[InfluxHostConfig].from { docker: InfluxDocker.Container =>
      val knownAddress = docker.availablePorts.availablePorts(primaryPort).head
      InfluxHostConfig(knownAddress.hostV4, knownAddress.port)
    }

    // add docker dependencies and override default configuration
    include(new DockerSupportModule[F] overridenBy new ModuleDef {
      make[Docker.ClientConfig].from {
        Docker.ClientConfig(
          readTimeoutMs = 60000, // long timeout for gh actions
          connectTimeoutMs = 500,
          allowReuse = false,
          useRemote = false,
          useRegistry = true,
          remote = None,
          registry = None
        )
      }
    })
  }

  final case class InfluxHostConfig(host: String, port: Int) {
    def endpoint: Uri = Uri.unsafeFromString(s"http://$host:$port")
  }
} 
Example 47
Source File: PostgresDocker.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.postgres

import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import distage.TagK
import izumi.distage.docker.Docker.{ContainerConfig, DockerPort}
import izumi.distage.docker.modules.DockerSupportModule
import izumi.distage.docker.{ContainerDef, Docker}
import izumi.distage.model.definition.ModuleDef

object PostgresDocker extends ContainerDef {

  val primaryPort: DockerPort = DockerPort.TCP(5432)
  val password: String        = "postgres"

  override def config: PostgresDocker.Config =
    ContainerConfig(
      image = "library/postgres:12.2",
      ports = Seq(primaryPort),
      env = Map("POSTGRES_PASSWORD" -> password),
      reuse = true
    )

  class Module[F[_]: ConcurrentEffect: ContextShift: Timer: TagK] extends ModuleDef {
    make[PostgresDocker.Container].fromResource {
      PostgresDocker.make[F]
    }

    make[PostgresHostConfig].from { docker: PostgresDocker.Container =>
      val knownAddress = docker.availablePorts.availablePorts(primaryPort).head
      PostgresHostConfig(knownAddress.hostV4, knownAddress.port)
    }

    // add docker dependencies and override default configuration
    include(new DockerSupportModule[F] overridenBy new ModuleDef {
      make[Docker.ClientConfig].from {
        Docker.ClientConfig(
          readTimeoutMs = 60000, // long timeout for gh actions
          connectTimeoutMs = 500,
          allowReuse = false,
          useRemote = false,
          useRegistry = true,
          remote = None,
          registry = None
        )
      }
    })
  }

  final case class PostgresHostConfig(host: String, port: Int)
} 
Example 48
Source File: TestCliModule.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.dummies

import cats.Parallel
import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import ch.epfl.bluebrain.nexus.cli.clients.{EventStreamClient, ProjectClient, SparqlClient}
import ch.epfl.bluebrain.nexus.cli.sse.Event
import ch.epfl.bluebrain.nexus.cli.sse.OrgUuid.unsafe._
import ch.epfl.bluebrain.nexus.cli.sse.ProjectUuid.unsafe._
import ch.epfl.bluebrain.nexus.cli.{Cli, Console}
import distage.{ModuleDef, TagK}
import izumi.distage.model.definition.StandardAxis.Repo
import izumi.distage.model.recursive.LocatorRef

final class TestCliModule[F[_]: Parallel: ContextShift: Timer: ConcurrentEffect: TagK](events: List[Event])
    extends ModuleDef {
  make[TestConsole[F]].tagged(Repo.Dummy).fromEffect(TestConsole[F])
  make[Console[F]].tagged(Repo.Dummy).from { tc: TestConsole[F] => tc }

  make[ProjectClient[F]]
    .tagged(Repo.Dummy)
    .from(
      new TestProjectClient[F](
        // matches the uuids from the events.json file used for testing
        Map(
          (
            ("e6a84231-5df7-41cf-9d18-286892d119ec", "d576d282-1049-4a0c-9240-ff34b5e879f2"),
            ("tutorialnexus", "datamodels")
          ),
          (
            ("a605b71a-377d-4df3-95f8-923149d04106", "a7d69059-8d1d-4dac-800f-90b6b6ab94ee"),
            ("bbp", "atlas")
          )
        )
      )
    )

  make[SparqlClient[F]].tagged(Repo.Dummy).fromEffect { TestSparqlClient[F](events) }

  make[EventStreamClient[F]].tagged(Repo.Dummy).from { pc: ProjectClient[F] =>
    new TestEventStreamClient[F](events, pc)
  }

  make[Cli[F]].tagged(Repo.Dummy).from { locatorRef: LocatorRef => new Cli[F](Some(locatorRef)) }
}

object TestCliModule {

  final def apply[F[_]: Parallel: ContextShift: Timer: ConcurrentEffect: TagK](events: List[Event]): TestCliModule[F] =
    new TestCliModule[F](events)

} 
Example 49
Source File: ProcessWirings.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking

import aecor.data._
import aecor.distributedprocessing.DistributedProcessing
import aecor.journal.postgres.Offset
import akka.actor.ActorSystem
import cats.effect.{ Clock, ConcurrentEffect, Timer }
import cats.implicits._
import cats.temp.par._
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import ru.pavkin.booking.booking.entity.{ BookingEvent, EventMetadata, EventsourcedBooking }
import ru.pavkin.booking.booking.process.{ BookingPaymentProcess, _ }
import ru.pavkin.booking.booking.view.BookingViewProjectionWiring
import ru.pavkin.booking.common.models.BookingKey

import scala.concurrent.duration._

final class ProcessWirings[F[_]: Timer: ConcurrentEffect: Par](system: ActorSystem,
                                                               clock: Clock[F],
                                                               postgresWirings: PostgresWirings[F],
                                                               kafkaWirings: KafkaWirings[F],
                                                               serviceWirings: ServiceWirings[F],
                                                               entityWirings: EntityWirings[F]) {

  import serviceWirings._
  import postgresWirings._
  import kafkaWirings._
  import entityWirings._

  val distributedProcessing = DistributedProcessing(system)

  val bookingQueries =
    bookingsJournal.queries(journals.booking.pollingInterval).withOffsetStore(offsetStore)

  def bookingEvents(
    eventTag: EventTag,
    consumerId: ConsumerId
  ): fs2.Stream[F, Committable[F,
                               (Offset,
                                EntityEvent[BookingKey, Enriched[EventMetadata, BookingEvent]])]] =
    fs2.Stream.force(bookingQueries.eventsByTag(eventTag, consumerId))

  val bookingViewProjection = new BookingViewProjectionWiring(
    bookingViewRepo,
    bookingEvents(_, _).map(_.map(_._2)),
    EventsourcedBooking.tagging
  )

  val bookingConfirmationProcess =
    new BookingConfirmationProcess(
      bookings,
      confirmationService,
      Slf4jLogger.unsafeFromName("BookingConfirmationProcess")
    )

  val bookingConfirmationProcessWiring =
    new BookingConfirmationProcessWiring(
      bookingEvents(_, _).map(_.map(_._2.map(_.event))),
      EventsourcedBooking.tagging,
      bookingConfirmationProcess
    )

  val bookingExpirationProcess = new BookingExpirationProcess(bookings, bookingViewRepo)

  val bookingExpirationProcessWiring =
    new BookingExpirationProcessWiring(clock, frequency = 30.seconds, bookingExpirationProcess)

  val bookingPaymentProcess =
    new BookingPaymentProcess(bookings, Slf4jLogger.unsafeFromName("BookingPaymentProcess"))

  val bookingPaymentProcessWiring =
    new BookingPaymentProcessWiring(paymentReceivedEventStream, bookingPaymentProcess)

  // Launcher
  val launchProcesses: F[List[DistributedProcessing.KillSwitch[F]]] =
    List(
      "BookingViewProjectionProcessing" -> bookingViewProjection.processes,
      "BookingConfirmationProcessing" -> bookingConfirmationProcessWiring.processes,
      "BookingExpirationProcessing" -> bookingExpirationProcessWiring.processes,
      "BookingPaymentProcessing" -> bookingPaymentProcessWiring.processes
    ).parTraverse {
      case (name, processes) => distributedProcessing.start(name, processes)
    }

} 
Example 50
Source File: Fs2Process.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.common.streaming

import aecor.distributedprocessing.DistributedProcessing._
import cats.effect.ConcurrentEffect
import cats.implicits._
import fs2._
import fs2.concurrent.SignallingRef

object Fs2Process {
  def apply[F[_]](stream: Stream[F, Unit])(implicit F: ConcurrentEffect[F]): Process[F] =
    Process(for {
      signal <- SignallingRef(false)
      running <- F.start(
                  stream
                    .interruptWhen(signal)
                    .compile
                    .drain
                )
    } yield RunningProcess(running.join, signal.set(true)))
} 
Example 51
Source File: BookingViewProjectionWiring.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.booking.view

import aecor.data._
import aecor.distributedprocessing.DistributedProcessing
import cats.effect.ConcurrentEffect
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import ru.pavkin.booking.booking.entity.{ BookingEvent, EventMetadata }
import ru.pavkin.booking.booking.view.BookingViewProjectionWiring.EventSource
import ru.pavkin.booking.common.models.BookingKey
import ru.pavkin.booking.common.streaming.Fs2Process
import ru.pavkin.booking.common.view.ProjectionFlow

class BookingViewProjectionWiring[F[_]](
  repo: BookingViewRepository[F],
  eventSource: (EventTag, ConsumerId) => EventSource[F],
  tagging: Tagging[BookingKey]
)(implicit F: ConcurrentEffect[F]) {

  val consumerId = ConsumerId("BookingViewProjection")

  val sink =
    ProjectionFlow(Slf4jLogger.unsafeCreate[F], new BookingViewProjection[F](repo))

  def tagProcess(tag: EventTag): fs2.Stream[F, Unit] =
    eventSource(tag, consumerId).through(sink)

  def processes: List[DistributedProcessing.Process[F]] =
    tagging.tags.map(tag => Fs2Process(tagProcess(tag)))
}

object BookingViewProjectionWiring {
  type EventSource[F[_]] =
    fs2.Stream[F, Committable[F, EntityEvent[BookingKey, Enriched[EventMetadata, BookingEvent]]]]

} 
Example 52
Source File: BookingPaymentProcessWiring.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.booking.process

import aecor.data.{ Committable, ConsumerId }
import aecor.distributedprocessing.DistributedProcessing
import cats.effect.{ ConcurrentEffect, Timer }
import ru.pavkin.booking.common.streaming.Fs2Process
import ru.pavkin.payment.event.PaymentReceived
import cats.syntax.all._

class BookingPaymentProcessWiring[F[_]: ConcurrentEffect: Timer](
  source: ConsumerId => fs2.Stream[F, Committable[F, PaymentReceived]],
  process: PaymentReceived => F[Unit]
) {

  val consumerId = ConsumerId("BookingPaymentProcess")

  val processStream: fs2.Stream[F, Unit] =
    source(consumerId).evalMap(c => process(c.value) >> c.commit)

  // Topic has 4 partitions, so we can run up to 4 processes in our cluster
  def processes: List[DistributedProcessing.Process[F]] =
    List.fill(4)(Fs2Process(processStream))

} 
Example 53
Source File: Fs2OutputStream.scala    From fs2-blobstore   with Apache License 2.0 4 votes vote down vote up
package blobstore.gcs

import java.io.OutputStream

import cats.effect.{ConcurrentEffect, Effect}
import fs2.{Chunk, Stream}
import fs2.concurrent.Queue
import cats.syntax.functor._

import scala.annotation.tailrec

private[gcs] class Fs2OutputStream[F[_]](
  queue: Queue[F, Option[Chunk[Byte]]],
  chunkSize: Int
)(implicit eff: Effect[F])
  extends OutputStream {
  @SuppressWarnings(Array("scalafix:DisableSyntax.var"))
  private var bufferedChunk: Chunk[Byte] = Chunk.empty

  @tailrec
  private def addChunk(newChunk: Chunk[Byte]): Unit = {
    val newChunkSize         = newChunk.size
    val bufferedChunkSize    = bufferedChunk.size
    val spaceLeftInTheBuffer = chunkSize - bufferedChunkSize

    if (newChunkSize > spaceLeftInTheBuffer) {
      bufferedChunk = Chunk.concatBytes(Seq(bufferedChunk, newChunk.take(spaceLeftInTheBuffer)), chunkSize)
      flushBuffer()
      addChunk(newChunk.drop(spaceLeftInTheBuffer))
    } else {
      bufferedChunk =
        Chunk.concatBytes(Seq(bufferedChunk, newChunk), bufferedChunkSize + newChunkSize)
    }
  }

  private def flushBuffer(): Unit = {
    enqueueChunkSync(Some(bufferedChunk))
    bufferedChunk = Chunk.empty
  }

  private def enqueueChunkSync(c: Option[Chunk[Byte]]): Unit =
    eff.toIO(queue.enqueue1(c)).unsafeRunSync()

  val stream: Stream[F, Byte] = queue.dequeue.unNoneTerminate.flatMap(Stream.chunk)

  override def write(bytes: Array[Byte]): Unit =
    addChunk(Chunk.bytes(bytes))
  override def write(bytes: Array[Byte], off: Int, len: Int): Unit =
    addChunk(Chunk.bytes(bytes, off, len))
  override def write(b: Int): Unit =
    addChunk(Chunk.singleton(b.toByte))

  override def flush(): Unit = flushBuffer()

  override def close(): Unit = {
    flush()
    enqueueChunkSync(None)
  }
}

private[gcs] object Fs2OutputStream {
  def apply[F[_]: ConcurrentEffect](chunkSize: Int, queueSize: Option[Int]): F[Fs2OutputStream[F]] = {
    val fQueue = queueSize match {
      case None       => Queue.unbounded[F, Option[Chunk[Byte]]]
      case Some(size) => Queue.bounded[F, Option[Chunk[Byte]]](size)
    }
    fQueue.map { queue => new Fs2OutputStream[F](queue, chunkSize) }
  }
} 
Example 54
Source File: Algebras.scala    From hydra   with Apache License 2.0 4 votes vote down vote up
package hydra.ingest.modules

import cats.effect.{Async, ConcurrentEffect, ContextShift, Timer}
import cats.implicits._
import hydra.avro.registry.SchemaRegistry
import hydra.ingest.app.AppConfig.AppConfig
import hydra.kafka.algebras.{KafkaAdminAlgebra, KafkaClientAlgebra, MetadataAlgebra}
import io.chrisdavenport.log4cats.Logger

final class Algebras[F[_]] private (
    val schemaRegistry: SchemaRegistry[F],
    val kafkaAdmin: KafkaAdminAlgebra[F],
    val kafkaClient: KafkaClientAlgebra[F],
    val metadata: MetadataAlgebra[F]
)

object Algebras {

  def make[F[_]: Async: ConcurrentEffect: ContextShift: Timer: Logger](config: AppConfig): F[Algebras[F]] =
    for {
      schemaRegistry <- SchemaRegistry.live[F](
        config.createTopicConfig.schemaRegistryConfig.fullUrl,
        config.createTopicConfig.schemaRegistryConfig.maxCacheSize
      )
      kafkaAdmin <- KafkaAdminAlgebra.live[F](config.createTopicConfig.bootstrapServers)
      kafkaClient <- KafkaClientAlgebra.live[F](config.createTopicConfig.bootstrapServers, schemaRegistry, config.ingestConfig.recordSizeLimitBytes)
      metadata <- MetadataAlgebra.make[F](config.v2MetadataTopicConfig.topicName.value,
        config.v2MetadataTopicConfig.consumerGroup, kafkaClient, schemaRegistry, config.v2MetadataTopicConfig.createOnStartup)
    } yield new Algebras[F](schemaRegistry, kafkaAdmin, kafkaClient, metadata)
}