-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from fp-in-bo/producers
Add Producers
- Loading branch information
Showing
7 changed files
with
556 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package jms4s | ||
|
||
import cats.data.NonEmptyList | ||
import cats.effect.{ Concurrent, ContextShift, Resource, Sync } | ||
import fs2.concurrent.Queue | ||
import jms4s.config.DestinationName | ||
import jms4s.jms._ | ||
import jms4s.model.SessionType | ||
import cats.implicits._ | ||
import scala.concurrent.duration.FiniteDuration | ||
import scala.concurrent.duration._ | ||
|
||
trait JmsPooledProducer[F[_]] { | ||
|
||
def sendN( | ||
messageFactory: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F])]] | ||
): F[Unit] | ||
|
||
def sendNWithDelay( | ||
messageFactory: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], Option[FiniteDuration])]] | ||
): F[Unit] | ||
|
||
def sendWithDelay( | ||
messageFactory: MessageFactory[F] => F[(JmsMessage[F], Option[FiniteDuration])] | ||
): F[Unit] | ||
|
||
def send(messageFactory: MessageFactory[F] => F[JmsMessage[F]]): F[Unit] | ||
|
||
} | ||
|
||
object JmsPooledProducer { | ||
|
||
private[jms4s] def make[F[_]: ContextShift: Concurrent]( | ||
connection: JmsConnection[F], | ||
queue: DestinationName, | ||
concurrencyLevel: Int | ||
): Resource[F, JmsPooledProducer[F]] = | ||
for { | ||
pool <- Resource.liftF( | ||
Queue.bounded[F, JmsResource[F]](concurrencyLevel) | ||
) | ||
_ <- (0 until concurrencyLevel).toList.traverse_ { _ => | ||
for { | ||
session <- connection.createSession(SessionType.AutoAcknowledge) | ||
destination <- Resource.liftF(session.createDestination(queue)) | ||
producer <- session.createProducer(destination) | ||
_ <- Resource.liftF(pool.enqueue1(JmsResource(session, producer, new MessageFactory(session)))) | ||
} yield () | ||
} | ||
} yield new JmsPooledProducer[F] { | ||
override def sendN( | ||
f: MessageFactory[F] => F[NonEmptyList[JmsMessage[F]]] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messages <- f(resources.messageFactory) | ||
_ <- messages.traverse_( | ||
message => | ||
for { | ||
_ <- resources.producer | ||
.send(message) | ||
} yield () | ||
) | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
|
||
override def sendNWithDelay( | ||
f: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], Option[FiniteDuration])]] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messagesDelays <- f(resources.messageFactory) | ||
_ <- messagesDelays.traverse_( | ||
messageWithDelay => | ||
for { | ||
_ <- messageWithDelay._2 match { | ||
case Some(delay) => resources.producer.setDeliveryDelay(delay) | ||
case None => Sync[F].unit | ||
} | ||
_ <- resources.producer.send(messageWithDelay._1) | ||
_ <- resources.producer.setDeliveryDelay(0.millis) | ||
} yield () | ||
) | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
|
||
override def sendWithDelay( | ||
f: MessageFactory[F] => F[(JmsMessage[F], Option[FiniteDuration])] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messagesWithDelay <- f(resources.messageFactory) | ||
_ <- messagesWithDelay._2 match { | ||
case Some(delay) => resources.producer.setDeliveryDelay(delay) | ||
case None => Sync[F].unit | ||
} | ||
_ <- resources.producer.send(messagesWithDelay._1) | ||
_ <- resources.producer.setDeliveryDelay(0.millis) | ||
_ <- pool.enqueue1(resources) | ||
|
||
} yield () | ||
|
||
override def send(f: MessageFactory[F] => F[JmsMessage[F]]): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
message <- f(resources.messageFactory) | ||
_ <- for { | ||
_ <- resources.producer | ||
.send(message) | ||
} yield () | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
} | ||
|
||
case class JmsResource[F[_]] private[jms4s] ( | ||
session: JmsSession[F], | ||
producer: JmsMessageProducer[F], | ||
messageFactory: MessageFactory[F] | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package jms4s | ||
|
||
import cats.effect.{ ContextShift, Sync } | ||
import cats.implicits._ | ||
import jms4s.jms.{ JmsMessage, JmsMessageProducer } | ||
|
||
import scala.concurrent.duration.{ FiniteDuration, _ } | ||
|
||
class JmsProducer[F[_]: Sync: ContextShift] private[jms4s] (private[jms4s] val producer: JmsMessageProducer[F]) { | ||
|
||
def publish(message: JmsMessage[F]): F[Unit] = | ||
producer.send(message) | ||
|
||
def publish(message: JmsMessage[F], delay: FiniteDuration): F[Unit] = | ||
producer.setDeliveryDelay(delay) >> producer.send(message) >> producer.setDeliveryDelay(0.millis) | ||
} |
124 changes: 124 additions & 0 deletions
124
core/src/main/scala/jms4s/JmsUnidentifiedPooledProducer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package jms4s | ||
|
||
import cats.data.NonEmptyList | ||
import cats.effect.{ Concurrent, ContextShift, Resource, Sync } | ||
import cats.implicits._ | ||
import fs2.concurrent.Queue | ||
import jms4s.config.DestinationName | ||
import jms4s.jms._ | ||
import jms4s.model.SessionType | ||
|
||
import scala.concurrent.duration.FiniteDuration | ||
import scala.concurrent.duration._ | ||
|
||
trait JmsUnidentifiedPooledProducer[F[_]] { | ||
|
||
def sendN( | ||
messageFactory: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], DestinationName)]] | ||
): F[Unit] | ||
|
||
def sendNWithDelay( | ||
messageFactory: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], (DestinationName, Option[FiniteDuration]))]] | ||
): F[Unit] | ||
|
||
def sendWithDelay( | ||
messageFactory: MessageFactory[F] => F[(JmsMessage[F], (DestinationName, Option[FiniteDuration]))] | ||
): F[Unit] | ||
|
||
def send(messageFactory: MessageFactory[F] => F[(JmsMessage[F], DestinationName)]): F[Unit] | ||
|
||
} | ||
|
||
object JmsUnidentifiedPooledProducer { | ||
|
||
private[jms4s] def make[F[_]: ContextShift: Concurrent]( | ||
connection: JmsConnection[F], | ||
concurrencyLevel: Int | ||
): Resource[F, JmsUnidentifiedPooledProducer[F]] = | ||
for { | ||
pool <- Resource.liftF( | ||
Queue.bounded[F, JmsResource[F]](concurrencyLevel) | ||
) | ||
_ <- (0 until concurrencyLevel).toList.traverse_ { _ => | ||
for { | ||
session <- connection.createSession(SessionType.AutoAcknowledge) | ||
producer <- session.createUnidentifiedProducer | ||
_ <- Resource.liftF(pool.enqueue1(JmsResource(session, producer, new MessageFactory(session)))) | ||
} yield () | ||
} | ||
} yield new JmsUnidentifiedPooledProducer[F] { | ||
override def sendN( | ||
f: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], DestinationName)]] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messagesWithDestinations <- f(resources.messageFactory) | ||
_ <- messagesWithDestinations.traverse_( | ||
messageWithDestination => | ||
for { | ||
jmsDestination <- resources.session.createDestination(messageWithDestination._2) | ||
_ <- resources.producer | ||
.send(jmsDestination, messageWithDestination._1) | ||
} yield () | ||
) | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
|
||
override def sendNWithDelay( | ||
f: MessageFactory[F] => F[NonEmptyList[(JmsMessage[F], (DestinationName, Option[FiniteDuration]))]] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messagesWithDestinationsAndDelayes <- f(resources.messageFactory) | ||
_ <- messagesWithDestinationsAndDelayes.traverse_( | ||
messageWithDestinationAndDelay => | ||
for { | ||
jmsDestination <- resources.session.createDestination(messageWithDestinationAndDelay._2._1) | ||
_ <- messageWithDestinationAndDelay._2._2 match { | ||
case Some(delay) => resources.producer.setDeliveryDelay(delay) | ||
case None => Sync[F].unit | ||
} | ||
_ <- resources.producer.send(jmsDestination, messageWithDestinationAndDelay._1) | ||
_ <- resources.producer.setDeliveryDelay(0.millis) | ||
} yield () | ||
) | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
|
||
override def sendWithDelay( | ||
f: MessageFactory[F] => F[(JmsMessage[F], (DestinationName, Option[FiniteDuration]))] | ||
): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messagesWithDestinationAndDelay <- f(resources.messageFactory) | ||
jmsDestination <- resources.session.createDestination(messagesWithDestinationAndDelay._2._1) | ||
_ <- messagesWithDestinationAndDelay._2._2 match { | ||
case Some(a) => resources.producer.setDeliveryDelay(a) | ||
case None => Sync[F].unit | ||
} | ||
_ <- resources.producer.send(jmsDestination, messagesWithDestinationAndDelay._1) | ||
_ <- resources.producer.setDeliveryDelay(0.millis) | ||
_ <- pool.enqueue1(resources) | ||
|
||
} yield () | ||
|
||
override def send(f: MessageFactory[F] => F[(JmsMessage[F], DestinationName)]): F[Unit] = | ||
for { | ||
resources <- pool.dequeue1 | ||
messageWithDestination <- f(resources.messageFactory) | ||
_ <- for { | ||
jmsDestination <- resources.session.createDestination(messageWithDestination._2) | ||
_ <- resources.producer | ||
.send(jmsDestination, messageWithDestination._1) | ||
} yield () | ||
_ <- pool.enqueue1(resources) | ||
} yield () | ||
} | ||
|
||
case class JmsResource[F[_]] private[jms4s] ( | ||
session: JmsSession[F], | ||
producer: JmsUnidentifiedMessageProducer[F], | ||
messageFactory: MessageFactory[F] | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package jms4s | ||
|
||
import cats.effect.{ ContextShift, Sync } | ||
import jms4s.jms.{ JmsDestination, JmsMessage, JmsUnidentifiedMessageProducer } | ||
import cats.implicits._ | ||
import scala.concurrent.duration.FiniteDuration | ||
import scala.concurrent.duration._ | ||
|
||
class JmsUnidentifiedProducer[F[_]: Sync: ContextShift] private[jms4s] ( | ||
private[jms4s] val producer: JmsUnidentifiedMessageProducer[F] | ||
) { | ||
|
||
def publish(destination: JmsDestination, message: JmsMessage[F]): F[Unit] = | ||
producer.send(destination, message) | ||
|
||
def publish(destination: JmsDestination, message: JmsMessage[F], delay: FiniteDuration): F[Unit] = | ||
producer.setDeliveryDelay(delay) >> producer.send(destination, message) >> producer.setDeliveryDelay(0.millis) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.