This repository has been archived by the owner on Aug 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
vitaliihonta
committed
Feb 1, 2019
1 parent
3fb4dcf
commit 4b49cd6
Showing
6 changed files
with
169 additions
and
7 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
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
67 changes: 67 additions & 0 deletions
67
integrations/akka/streams/src/main/scala/trembita/akka_streams/JoinFlow.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,67 @@ | ||
package trembita.akka_streams | ||
|
||
import akka.NotUsed | ||
import akka.stream.{Attributes, FlowShape, Inlet, Outlet} | ||
import akka.stream.scaladsl._ | ||
import akka.stream.stage._ | ||
|
||
import scala.language.higherKinds | ||
|
||
class JoinFlow[A, B](right: Stream[B], on: (A, B) => Boolean) extends GraphStage[FlowShape[A, (A, B)]] { | ||
def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogicWithLogging(shape) { | ||
setHandlers( | ||
in, | ||
out, | ||
new InHandler with OutHandler { | ||
def onPush(): Unit = { | ||
val curr = grab(in) | ||
log.debug(s"grabed $curr\n\tright=$right") | ||
right.find(on(curr, _)) match { | ||
case None => | ||
log.debug(s"Haven't found pair for $curr") | ||
case Some(found) => | ||
push(out, (curr, found)) | ||
log.debug(s"Pushed pair: $curr -> $found") | ||
} | ||
} | ||
def onPull(): Unit = { | ||
log.debug("On pull...") | ||
pull(in) | ||
} | ||
} | ||
) | ||
} | ||
private val in = Inlet[A]("join.in") | ||
private val out = Outlet[(A, B)]("join.out") | ||
val shape: FlowShape[A, (A, B)] = FlowShape(in, out) | ||
} | ||
|
||
class JoinLeftFlow[A, B](right: Stream[B], on: (A, B) => Boolean) extends GraphStage[FlowShape[A, (A, Option[B])]] { | ||
def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogicWithLogging(shape) { | ||
setHandlers( | ||
in, | ||
out, | ||
new InHandler with OutHandler { | ||
def onPush(): Unit = { | ||
val curr = grab(in) | ||
log.debug(s"grabed $curr") | ||
right.find(on(curr, _)) match { | ||
case None => | ||
log.debug(s"Haven't found pair for $curr") | ||
push(out, (curr, None)) | ||
case res @ Some(found) => | ||
push(out, (curr, res)) | ||
log.debug(s"Pushed pair: $curr -> $found") | ||
} | ||
} | ||
def onPull(): Unit = { | ||
log.debug("Pulling...") | ||
pull(in) | ||
} | ||
} | ||
) | ||
} | ||
private val in = Inlet[A]("joinLeft.in") | ||
private val out = Outlet[(A, Option[B])]("joinLeft.out") | ||
val shape: FlowShape[A, (A, Option[B])] = FlowShape(in, out) | ||
} |
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
67 changes: 67 additions & 0 deletions
67
integrations/akka/streams/src/test/scala/trembita/akka_streams/JoinSpec.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,67 @@ | ||
package trembita.akka_streams | ||
|
||
import akka.actor.ActorSystem | ||
import akka.stream.scaladsl.Source | ||
import akka.stream.{ActorMaterializer, DelayOverflowStrategy} | ||
import akka.testkit.TestKit | ||
import cats.effect.{IO, Timer} | ||
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike} | ||
import trembita._ | ||
import scala.concurrent.ExecutionContext | ||
|
||
class JoinSpec extends TestKit(ActorSystem("trembita-akka-join")) with FlatSpecLike with BeforeAndAfterAll { | ||
implicit val _system: ActorSystem = system | ||
implicit val mat: ActorMaterializer = ActorMaterializer()(system) | ||
implicit val parallelism: Parallelism = Parallelism(4, ordered = false) | ||
implicit val ec: ExecutionContext = system.dispatcher | ||
implicit val delayOverflowStrategy: DelayOverflowStrategy = DelayOverflowStrategy.dropHead | ||
implicit val ioTimer: Timer[IO] = IO.timer(ec) | ||
|
||
override def afterAll(): Unit = { | ||
mat.shutdown() | ||
system.terminate() | ||
} | ||
|
||
"Akka pipelines" should "support join" in { | ||
val ppln1 = Input.fromSourceF[IO](Source(1 to 10)) | ||
val ppln2 = Input.fromSourceF[IO](Source(0 :: 1 :: Nil)) | ||
|
||
val result = ppln1.join(ppln2)(on = _ % 2 == _).into(Output.vector).run.unsafeRunSync().sortBy(_._1) | ||
|
||
assert(result == (1 to 10).toVector.map(x => x -> (x % 2))) | ||
} | ||
|
||
it should "support join left" in { | ||
val ppln1 = Input.fromSourceF[IO](Source(1 to 10)) | ||
val ppln2 = Input.fromSourceF[IO](Source(0 :: 1 :: Nil)) | ||
|
||
val result = ppln1.joinLeft(ppln2)(on = _ % 3 == _).into(Output.vector).run.unsafeRunSync().sortBy(_._1) | ||
|
||
assert(result == (1 to 10).toVector.map { x => | ||
x -> (x % 3 match { | ||
case 0 => Some(0) | ||
case 1 => Some(1) | ||
case _ => None | ||
}) | ||
}) | ||
} | ||
|
||
it should "support join right" in { | ||
val ppln1 = Input.fromSourceF[IO](Source(1 to 10)) | ||
val ppln2 = Input.fromSourceF[IO](Source(0 :: 1 :: Nil)) | ||
|
||
val result = ppln2.joinRight(ppln1)(on = _ == _ % 3).into(Output.vector).run.unsafeRunSync().sortBy(_._2) | ||
|
||
assert( | ||
result == (1 to 10).toVector | ||
.map { x => | ||
x -> (x % 3 match { | ||
case 0 => Some(0) | ||
case 1 => Some(1) | ||
case _ => None | ||
}) | ||
} | ||
.map(_.swap) | ||
) | ||
} | ||
} |