monix.eval.Task Scala Examples
The following examples show how to use monix.eval.Task.
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: NoOpHttpClient.scala From cornichon with Apache License 2.0 | 6 votes |
package com.github.agourlay.cornichon.http.client import cats.Show import cats.data.EitherT import cats.syntax.either._ import com.github.agourlay.cornichon.core.Done import com.github.agourlay.cornichon.http.{ CornichonHttpResponse, HttpRequest, HttpStreamedRequest } import monix.eval.Task import org.http4s.EntityEncoder import scala.concurrent.duration.FiniteDuration class NoOpHttpClient extends HttpClient { def runRequest[A: Show](cReq: HttpRequest[A], t: FiniteDuration)(implicit ee: EntityEncoder[Task, A]) = EitherT.apply(Task.now(CornichonHttpResponse(200, Nil, "NoOpBody").asRight)) def openStream(req: HttpStreamedRequest, t: FiniteDuration) = Task.now(CornichonHttpResponse(200, Nil, "NoOpBody").asRight) def shutdown() = Done.taskDone def paramsFromUrl(url: String) = Right(Nil) }
Example 2
Source File: MockHttpServer.scala From cornichon with Apache License 2.0 | 6 votes |
package com.github.agourlay.cornichon.http.server import java.net.NetworkInterface import com.github.agourlay.cornichon.core.CornichonError import monix.eval.Task import monix.execution.Scheduler import org.http4s.HttpRoutes import org.http4s.server.Router import org.http4s.server.blaze.BlazeServerBuilder import org.http4s.implicits._ import scala.jdk.CollectionConverters._ import scala.concurrent.duration._ import scala.util.Random class MockHttpServer[A](interface: Option[String], port: Option[Range], mockService: HttpRoutes[Task], maxRetries: Int = 5)(useFromAddress: String => Task[A])(implicit scheduler: Scheduler) { private val selectedInterface = interface.getOrElse(bestInterface()) private val randomPortOrder = port.fold(0 :: Nil)(r => Random.shuffle(r.toList)) private val mockRouter = Router("/" -> mockService).orNotFound def useServer(): Task[A] = if (randomPortOrder.isEmpty) Task.raiseError(MockHttpServerError.toException) else startServerTryPorts(randomPortOrder) private def startServerTryPorts(ports: List[Int], retry: Int = 0): Task[A] = startBlazeServer(ports.head).onErrorHandleWith { case _: java.net.BindException if ports.length > 1 => startServerTryPorts(ports.tail, retry) case _: java.net.BindException if retry < maxRetries => val sleepFor = retry + 1 println(s"Could not start server on any port. Retrying in $sleepFor seconds...") startServerTryPorts(randomPortOrder, retry = retry + 1).delayExecution(sleepFor.seconds) } private def startBlazeServer(port: Int): Task[A] = BlazeServerBuilder[Task](executionContext = scheduler) .bindHttp(port, selectedInterface) .withoutBanner .withHttpApp(mockRouter) .withNio2(true) .resource .use(server => useFromAddress(s"http://${server.address.getHostString}:${server.address.getPort}")) private def bestInterface(): String = NetworkInterface.getNetworkInterfaces.asScala .filter(_.isUp) .flatMap(_.getInetAddresses.asScala) .find(_.isSiteLocalAddress) .map(_.getHostAddress) .getOrElse("localhost") } case object MockHttpServerError extends CornichonError { val baseErrorMessage = "the range of ports provided for the HTTP mock is invalid" }
Example 3
Source File: TaskLimiter.scala From spark-tools with Apache License 2.0 | 5 votes |
package io.univalence.centrifuge.util //from https://gist.github.com/alexandru/623fe6c587d73e89a8f14de284ca1e2d import monix.eval.Task import java.util.concurrent.TimeUnit import scala.concurrent.duration._ final case class State(window: Long, period: TimeUnit, requested: Int, limit: Int) { private def periodMillis = TimeUnit.MILLISECONDS.convert(1, period) def request(now: Timestamp): (Option[FiniteDuration], State) = { val periodMillis = this.periodMillis val currentWindow = now / periodMillis if (currentWindow != window) (None, copy(window = currentWindow, requested = 1)) else if (requested < limit) (None, copy(requested = requested + 1)) else { val nextTS = (currentWindow + 1) * periodMillis val sleep = nextTS - now (Some(sleep.millis), this) } } } }
Example 4
Source File: TwitterSearcher.scala From gbf-raidfinder with MIT License | 5 votes |
package walfie.gbf.raidfinder import monix.eval.Task import monix.reactive._ import scala.collection.JavaConverters._ import scala.concurrent.duration._ import scala.concurrent.Future import twitter4j._ import walfie.gbf.raidfinder.TwitterSearcher.PaginationType import walfie.gbf.raidfinder.util.BlockingIO trait TwitterSearcher { import TwitterSearcher.TweetId def observable( searchTerm: String, initialTweet: Option[TweetId], maxCount: Int ): Observable[Seq[Status]] } object TwitterSearcher { sealed trait PaginationType case object Chronological extends PaginationType case object ReverseChronological extends PaginationType type TweetId = Long def observable(searchTerm: String, initialTweet: Option[TweetId], maxCount: Int): Observable[Seq[Status]] = { Observable.fromAsyncStateAction[Option[TweetId], Seq[Status]] { tweetId => val query = new Query(searchTerm).count(maxCount) Task.fromFuture(searchFunction(query, tweetId, maxCount)) .onErrorHandle { error: Throwable => System.err.println(error) // TODO: Better handling? Seq.empty[Status] -> tweetId } }(None) } private val searchFunction = paginationType match { case Chronological => searchChronological _ case ReverseChronological => searchReverseChronological _ } private def searchChronological( query: Query, initialTweet: Option[TweetId], maxCount: Int ): Future[(Seq[Status], Option[TweetId])] = { initialTweet.foreach(query.setSinceId) BlockingIO.future { val queryResult = twitter.search(query) val tweetsEarliestFirst = queryResult.getTweets.asScala.sortBy(_.getCreatedAt) // Earliest first tweetsEarliestFirst -> Option(queryResult.getMaxId) } } private def searchReverseChronological( query: Query, initialTweet: Option[TweetId], maxCount: Int ): Future[(Seq[Status], Option[TweetId])] = { initialTweet.foreach(query.setMaxId) BlockingIO.future { val queryResult = twitter.search(query) val tweetsLatestFirst = queryResult.getTweets.asScala.sortBy(-_.getCreatedAt.getTime) // Latest first tweetsLatestFirst -> tweetsLatestFirst.lastOption.map(_.getId) // queryResult.getSinceId returns 0 } } }
Example 5
Source File: RaidFinder.scala From gbf-raidfinder with MIT License | 5 votes |
package walfie.gbf.raidfinder import java.util.Date import monix.eval.Task import monix.execution.{Cancelable, Scheduler} import monix.reactive._ import scala.concurrent.duration._ import scala.concurrent.Future import twitter4j._ import walfie.gbf.raidfinder.domain._ import walfie.gbf.raidfinder.util.CachedObservablesPartitioner trait RaidFinder[T] { def getRaidTweets(bossName: BossName): Observable[T] def newBossObservable: Observable[RaidBoss] def getKnownBosses(): Map[BossName, RaidBoss] def purgeOldBosses( minDate: Date, levelThreshold: Option[Int] ): Future[Map[BossName, RaidBoss]] def shutdown(): Unit } object RaidFinder { val DefaultCacheSizePerBoss = 20 val DefaultBackfillSize = 200 protected def onShutdown(): Unit = () // TODO: Parsing happens twice somewhere -- should figure out where private val raidInfos = statusesObservable .collect(Function.unlift(StatusParser.parse)) .publish private val (partitioner, partitionerCancelable) = CachedObservablesPartitioner.fromUngroupedObservable( raidInfos.map(_.tweet), cachedTweetsPerBoss, (_: RaidTweet).bossName, fromRaidTweet.from // TODO ) private val (knownBosses, knownBossesCancelable) = KnownBossesObserver .fromRaidInfoObservable(raidInfos, initialBosses) val newBossObservable = knownBosses.newBossObservable private val raidInfosCancelable = raidInfos.connect() private val cancelable = Cancelable { () => List( raidInfosCancelable, partitionerCancelable, knownBossesCancelable ).foreach(_.cancel) onShutdown() } def shutdown(): Unit = cancelable.cancel() def getKnownBosses(): Map[BossName, RaidBoss] = knownBosses.get() def getRaidTweets(bossName: BossName): Observable[T] = partitioner.getObservable(bossName) def purgeOldBosses( minDate: Date, levelThreshold: Option[Int] ): Future[Map[BossName, RaidBoss]] = knownBosses.purgeOldBosses(minDate, levelThreshold) }
Example 6
Source File: ObservableSpec.scala From gbf-raidfinder with MIT License | 5 votes |
package walfie.gbf.raidfinder.util import monix.eval.Task import monix.execution.Ack import monix.execution.schedulers.TestScheduler import monix.reactive.{Observable, Observer} import org.scalatest._ import org.scalatest.concurrent.ScalaFutures import org.scalatest.Matchers._ import scala.concurrent.Future class ObservableSpec extends FreeSpec with ScalaFutures { case class Item(id: Int) object ItemRepository { def getItems(count: Int, pageNum: Int): Future[Seq[Item]] = Future.successful { (0 until count).map(i => Item(pageNum * count + i)) } } // This was added as [[ObservableUtil.fromAsyncStateAction]] before // [[Observable.fromAsyncStateAction]] existed in Monix. Keeping these // tests around because why not. "fromAsyncStateAction" - { implicit val scheduler = TestScheduler() "yield an observable" in { val itemsPerPage = 5 val observable = Observable.fromAsyncStateAction { pageNum: Int => val nextPage = pageNum + 1 val itemsF = ItemRepository.getItems(itemsPerPage, pageNum) Task.fromFuture(itemsF).map(_ -> nextPage) }(0) val resultF = observable.take(3).toListL.runAsync scheduler.tick() resultF.futureValue shouldBe Seq( (0 to 4).map(Item.apply), (5 to 9).map(Item.apply), (10 to 14).map(Item.apply) ) } "stop on error" in { implicit val scheduler = TestScheduler() // Create an observable counter that errors when it gets to 5 val error = new RuntimeException("Oh no!") val observable = Observable .fromAsyncStateAction[Int, Int] { counter: Int => Task.fromFuture { if (counter == 5) Future.failed(error) else Future.successful(counter -> (counter + 1)) } }(0) val observer = new TestObserver[Int] observable.take(10).subscribe(observer) scheduler.tick() observer.received shouldBe (0 to 4) } } }
Example 7
package com.wavesplatform.dex.time import java.net.{InetAddress, SocketTimeoutException} import java.util.concurrent.RejectedExecutionException import java.util.concurrent.atomic.AtomicBoolean import com.wavesplatform.dex.domain.utils.ScorexLogging import monix.eval.Task import monix.execution.schedulers.SchedulerService import monix.execution.{ExecutionModel, Scheduler} import org.apache.commons.net.ntp.NTPUDPClient import scala.concurrent.duration.DurationInt class NTP(ntpServer: String) extends Time with ScorexLogging with AutoCloseable { private val offsetPanicThreshold = 1000000L private val ExpirationTimeout = 60.seconds private val RetryDelay = 10.seconds private val ResponseTimeout = 10.seconds private val duringShutdown = new AtomicBoolean(false) private implicit val scheduler: SchedulerService = Scheduler.singleThread( name = "time-impl", daemonic = false, executionModel = ExecutionModel.AlwaysAsyncExecution, reporter = { case _: RejectedExecutionException if duringShutdown.get() => // ignore case e: Throwable => log.error("An uncaught error", e) } ) private val client = new NTPUDPClient() client.setDefaultTimeout(ResponseTimeout.toMillis.toInt) @volatile private var offset = 0L private val updateTask: Task[Unit] = { def newOffsetTask: Task[Option[(InetAddress, java.lang.Long)]] = Task { try { val info = client.getTime(InetAddress.getByName(ntpServer)) info.computeDetails() Option(info.getOffset).map { offset => val r = if (Math.abs(offset) > offsetPanicThreshold) throw new Exception("Offset is suspiciously large") else offset (info.getAddress, r) } } catch { case _: SocketTimeoutException => None case t: Throwable => log.warn("Problems with NTP: ", t) None } } newOffsetTask.flatMap { case None if !scheduler.isShutdown => updateTask.delayExecution(RetryDelay) case Some((server, newOffset)) if !scheduler.isShutdown => log.trace(s"Adjusting time with $newOffset milliseconds, source: ${server.getHostAddress}.") offset = newOffset updateTask.delayExecution(ExpirationTimeout) case _ => Task.unit } } def correctedTime(): Long = System.currentTimeMillis() + offset private var txTime: Long = 0 def getTimestamp(): Long = { txTime = Math.max(correctedTime(), txTime + 1) txTime } private val taskHandle = updateTask.runAsync { case Left(e) => log.error(s"Error executing task", e) case _ => } override def close(): Unit = if (duringShutdown.compareAndSet(false, true)) { log.info("Shutting down Time") taskHandle.cancel() if (client.isOpen) client.close() scheduler.shutdown() } }
Example 8
Source File: ScorexLogging.scala From matcher with MIT License | 5 votes |
package com.wavesplatform.dex.domain.utils import monix.eval.Task import monix.execution.{CancelableFuture, Scheduler} import org.slf4j.{Logger, LoggerFactory} case class LoggerFacade(logger: Logger) { def trace(message: => String): Unit = if (logger.isTraceEnabled) logger.trace(message) def debug(message: => String, arg: Any): Unit = if (logger.isDebugEnabled) logger.debug(message, arg) def debug(message: => String): Unit = if (logger.isDebugEnabled) logger.debug(message) def info(message: => String): Unit = if (logger.isInfoEnabled) logger.info(message) def info(message: => String, arg: Any): Unit = if (logger.isInfoEnabled) logger.info(message, arg) def info(message: => String, throwable: Throwable): Unit = if (logger.isInfoEnabled) logger.info(message, throwable) def warn(message: => String): Unit = if (logger.isWarnEnabled) logger.warn(message) def warn(message: => String, throwable: Throwable): Unit = if (logger.isWarnEnabled) logger.warn(message, throwable) def error(message: => String): Unit = if (logger.isErrorEnabled) logger.error(message) def error(message: => String, throwable: Throwable): Unit = if (logger.isErrorEnabled) logger.error(message, throwable) } trait ScorexLogging { protected lazy val log: LoggerFacade = LoggerFacade(LoggerFactory.getLogger(this.getClass)) implicit class TaskExt[A](t: Task[A]) { def runAsyncLogErr(implicit s: Scheduler): CancelableFuture[A] = logErr.runToFuture(s) def logErr: Task[A] = t.onErrorHandleWith { ex => log.error(s"Error executing task", ex) Task.raiseError[A](ex) } } }
Example 9
Source File: MonadlessTaskSpec.scala From monadless with Apache License 2.0 | 5 votes |
package io.monadless.monix import java.util.concurrent.TimeUnit import org.scalatest.MustMatchers import io.monadless.impl.TestSupport import monix.eval.Task import monix.execution.Cancelable import monix.execution.schedulers.ReferenceScheduler class MonadlessTaskSpec extends org.scalatest.FreeSpec with MustMatchers with MonadlessTask with TestSupport[Task] { implicit val s = new ReferenceScheduler { def scheduleOnce(initialDelay: Long, unit: TimeUnit, r: Runnable) = { r.run() Cancelable.empty } def execute(command: Runnable) = command.run() def executionModel = monix.execution.ExecutionModel.SynchronousExecution def reportFailure(t: Throwable): Unit = {} } def get[T](f: Task[T]) = f.runSyncMaybe.right.get def fail[T]: T = throw new Exception val one = Task(1) val two = Task(2) "apply" in runLiftTest(1) { 1 } "collect" in runLiftTest(3) { unlift(one) + unlift(two) } "map" in runLiftTest(2) { unlift(one) + 1 } "flatMap" in runLiftTest(3) { val a = unlift(one) a + unlift(two) } "rescue" - { "success" in runLiftTest(1) { try unlift(one) catch { case e: Throwable => unlift(two) } } "failure" in runLiftTest(1) { try fail[Int] catch { case e: Exception => unlift(one) } } } "ensure" - { "success" in runLiftTest(1) { var i = 0 def c() = i += 1 try unlift(one) finally { c() } i } "failure" in runLiftTest(1) { var i = 0 def c() = i += 1 try { try unlift(one) / fail[Int] finally { c() } } catch { case e: Exception => 1 } i } } }
Example 10
Source File: Cp.scala From benchmarks with Apache License 2.0 | 5 votes |
package com.rossabaker package benchmarks import org.openjdk.jmh.annotations._ @State(Scope.Thread) @Fork(2) @Measurement(iterations = 10) @Warmup(iterations = 10) @Threads(1) class Cp extends BenchmarkUtils { @Benchmark def fs2Sync(): Unit = { import _root_.fs2._, Stream._ import java.nio.file.Paths io.file.readAll[Task](Paths.get("testdata/lorem-ipsum.txt"), 4096) .to(io.file.writeAll[Task](Paths.get("out/lorem-ipsum.txt"))) .run .unsafeRun } @Benchmark def fs2Async(): Unit = { import _root_.fs2._, Stream._ import java.nio.file.Paths io.file.readAllAsync[Task](Paths.get("testdata/lorem-ipsum.txt"), 4096) .to(io.file.writeAllAsync[Task](Paths.get("out/lorem-ipsum.txt"))) .run .unsafeRun } @Benchmark def scalazStreamIo(): Unit = { import _root_.scalaz.stream._, Process._ constant(4096) .through(io.fileChunkR("testdata/lorem-ipsum.txt")) .to(io.fileChunkW("out/lorem-ipsum.txt")) .run .unsafePerformSync } @Benchmark def scalazStreamNio(): Unit = { import _root_.scalaz.stream._, Process._ constant(4096) .through(nio.file.chunkR("testdata/lorem-ipsum.txt")) .to(nio.file.chunkW("out/lorem-ipsum.txt")) .run .unsafePerformSync } } callback.onError(ex) } def onComplete(): Unit = { try { out.close() callback.onSuccess(()) } catch { case NonFatal(ex) => callback.onError(ex) } } } } Await.result( copyFile(new File("testdata/lorem-ipsum.txt"), new File("out/lorem-ipsum.txt"), 4096) .runAsync(monixScheduler), Duration.Inf ) } }
Example 11
Source File: Monix.scala From arrows with Apache License 2.0 | 5 votes |
package benchmarks import monix.eval.Task import monix.execution.Cancelable import org.openjdk.jmh.annotations.Benchmark import scala.util.Try import scala.util.Success trait MonixAsync { this: Benchmarks => private[this] final val gen = MonixGen(dist) @Benchmark def monixTask = { import scala.concurrent._ import scala.concurrent.duration._ import monix.execution.Scheduler.Implicits.global Try(Await.result(gen(1).runAsync, Duration.Inf)) } } trait MonixSync { this: Benchmarks => private[this] final val gen = MonixGen(dist) @Benchmark def monixTask = { import monix.execution.Scheduler.Implicits.global Success(gen(1).runSyncMaybe.right.get) } } object MonixGen extends Gen[Int => Task[Int]] { def sync = Task.now _ def async(schedule: Runnable => Unit) = { v => Task.async[Int] { case (s, cb) => schedule(() => cb.onSuccess(v)) Cancelable.empty } } def failure(ex: Throwable) = _ => Task.raiseError(ex) def map(t: Int => Task[Int], f: Int => Int) = t.andThen(_.map(f)) def flatMap(t: Int => Task[Int], f: Int => Task[Int]) = t.andThen(_.flatMap(f)) def handle(t: Int => Task[Int], i: Int) = t.andThen(_.onErrorHandle(_ => i)) }
Example 12
Source File: MonixRestImplicits.scala From udash-core with Apache License 2.0 | 5 votes |
package io.udash package rest.monix import com.avsystem.commons._ import com.avsystem.commons.meta.MacroInstances import com.avsystem.commons.misc.ImplicitNotFound import io.udash.rest.raw.HttpResponseType import io.udash.rest.raw.RawRest.{Async, AsyncEffect} import io.udash.rest.{GenCodecRestImplicits, OpenApiFullInstances, RestOpenApiCompanion} import monix.eval.Task import monix.execution.Scheduler import scala.annotation.implicitNotFound trait MonixRestImplicits extends GenCodecRestImplicits { implicit def scheduler: Scheduler = Scheduler.global implicit def taskToAsync: AsyncEffect[Task] = new AsyncEffect[Task] { def toAsync[A](task: Task[A]): Async[A] = callback => task.runAsync(res => callback(res.fold(Failure(_), Success(_)))) def fromAsync[A](async: Async[A]): Task[A] = Task.async(callback => async(res => callback(res.fold(Left(_), Right(_))))) } @implicitNotFound("${T} is not a valid HTTP method result type - it must be wrapped into a Task") implicit def httpResponseTypeNotFound[T]: ImplicitNotFound[HttpResponseType[T]] = ImplicitNotFound() } object MonixRestImplicits extends MonixRestImplicits abstract class MonixRestApiCompanion[Real]( implicit macroInstances: MacroInstances[MonixRestImplicits, OpenApiFullInstances[Real]] ) extends RestOpenApiCompanion[MonixRestImplicits, Real](MonixRestImplicits)
Example 13
Source File: ArrayFillBenchmark.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import scala.collection.immutable.Range import org.openjdk.jmh.annotations._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) class ArrayFillBenchmark { @Param(Array("10000")) var size: Int = _ def createTestArray: Array[Int] = Range.inclusive(1, size).toArray.reverse @Benchmark def zioArrayFill() = { import IOBenchmarks.unsafeRun def arrayFill(array: Array[Int])(i: Int): UIO[Unit] = if (i >= array.length) UIO.unit else UIO(array.update(i, i)).flatMap(_ => arrayFill(array)(i + 1)) unsafeRun( for { array <- IO.effectTotal[Array[Int]](createTestArray) _ <- arrayFill(array)(0) } yield () ) } @Benchmark def monoArrayFill() = { import reactor.core.publisher.Mono def arrayFill(array: Array[Int])(i: Int): Mono[Unit] = if (i >= array.length) Mono.fromSupplier(() => ()) else Mono .fromSupplier(() => array.update(i, i)) .flatMap(_ => arrayFill(array)(i + 1)) (for { array <- Mono.fromSupplier(() => createTestArray) _ <- arrayFill(array)(0) } yield ()) .block() } @Benchmark def catsArrayFill() = { import cats.effect.IO def arrayFill(array: Array[Int])(i: Int): IO[Unit] = if (i >= array.length) IO.unit else IO(array.update(i, i)).flatMap(_ => arrayFill(array)(i + 1)) (for { array <- IO(createTestArray) _ <- arrayFill(array)(0) } yield ()).unsafeRunSync() } @Benchmark def monixArrayFill() = { import IOBenchmarks.monixScheduler import monix.eval.Task def arrayFill(array: Array[Int])(i: Int): Task[Unit] = if (i >= array.length) Task.unit else Task.eval(array.update(i, i)).flatMap(_ => arrayFill(array)(i + 1)) (for { array <- Task.eval(createTestArray) _ <- arrayFill(array)(0) } yield ()).runSyncUnsafe(scala.concurrent.duration.Duration.Inf) } }
Example 14
Source File: ZIOArray.scala From zio with Apache License 2.0 | 5 votes |
package zio import scala.{ Array, Boolean, Int, Unit } object ZIOArray { def bubbleSort[A](lessThanEqual0: (A, A) => Boolean)(array: Array[A]): UIO[Unit] = { def outerLoop(i: Int): UIO[Unit] = if (i >= array.length - 1) UIO.unit else innerLoop(i, i + 1).flatMap(_ => outerLoop(i + 1)) def innerLoop(i: Int, j: Int): UIO[Unit] = if (j >= array.length) UIO.unit else UIO((array(i), array(j))).flatMap { case (ia, ja) => val maybeSwap = if (lessThanEqual0(ia, ja)) UIO.unit else swapIJ(i, ia, j, ja) maybeSwap.flatMap(_ => innerLoop(i, j + 1)) } def swapIJ(i: Int, ia: A, j: Int, ja: A): UIO[Unit] = UIO { array.update(i, ja); array.update(j, ia) } outerLoop(0) } } object CatsIOArray { import cats.effect.IO def bubbleSort[A](lessThanEqual0: (A, A) => Boolean)(array: Array[A]): IO[Unit] = { def outerLoop(i: Int): IO[Unit] = if (i >= array.length - 1) IO.unit else innerLoop(i, i + 1).flatMap(_ => outerLoop(i + 1)) def innerLoop(i: Int, j: Int): IO[Unit] = if (j >= array.length) IO.unit else IO((array(i), array(j))).flatMap { case (ia, ja) => val maybeSwap = if (lessThanEqual0(ia, ja)) IO.unit else swapIJ(i, ia, j, ja) maybeSwap.flatMap(_ => innerLoop(i, j + 1)) } def swapIJ(i: Int, ia: A, j: Int, ja: A): IO[Unit] = IO { array.update(i, ja); array.update(j, ia) } outerLoop(0) } } object MonixIOArray { import monix.eval.Task def bubbleSort[A](lessThanEqual0: (A, A) => Boolean)(array: Array[A]): Task[Unit] = { def outerLoop(i: Int): Task[Unit] = if (i >= array.length - 1) Task.unit else innerLoop(i, i + 1).flatMap(_ => outerLoop(i + 1)) def innerLoop(i: Int, j: Int): Task[Unit] = if (j >= array.length) Task.unit else Task.eval((array(i), array(j))).flatMap { case (ia, ja) => val maybeSwap = if (lessThanEqual0(ia, ja)) Task.unit else swapIJ(i, ia, j, ja) maybeSwap.flatMap(_ => innerLoop(i, j + 1)) } def swapIJ(i: Int, ia: A, j: Int, ja: A): Task[Unit] = Task.eval { array.update(i, ja); array.update(j, ia) } outerLoop(0) } }
Example 15
Source File: IOEmptyRaceBenchmark.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import org.openjdk.jmh.annotations._ import zio.IOBenchmarks._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @Warmup(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Fork(1) @Threads(1) class IOEmptyRaceBenchmark { @Param(Array("1000")) var size: Int = _ @Benchmark def monixEmptyRace(): Int = { import monix.eval.Task def loop(i: Int): monix.eval.Task[Int] = if (i < size) Task.race(Task.never, Task.eval(i + 1)).flatMap(_ => loop(i + 1)) else Task.pure(i) loop(0).runSyncUnsafe() } @Benchmark def catsEmptyRace(): Int = { import cats.effect.IO def loop(i: Int): IO[Int] = if (i < size) IO.race(IO.never, IO.delay(i + 1)).flatMap(_ => loop(i + 1)) else IO.pure(i) loop(0).unsafeRunSync() } @Benchmark def zioEmptyRace(): Int = zioEmptyRace(IOBenchmarks) @Benchmark def zioTracedEmptyRace(): Int = zioEmptyRace(TracedRuntime) private[this] def zioEmptyRace(runtime: Runtime[Any]): Int = { def loop(i: Int): UIO[Int] = if (i < size) IO.never.raceFirst(IO.effectTotal(i + 1)).flatMap(loop) else IO.succeedNow(i) runtime.unsafeRun(loop(0)) } }
Example 16
Source File: BubbleSortBenchmarks.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import scala.collection.immutable.Range import IOBenchmarks.unsafeRun import org.openjdk.jmh.annotations._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) class BubbleSortBenchmarks { @Param(Array("1000")) var size: Int = _ def createTestArray: Array[Int] = Range.inclusive(1, size).toArray.reverse def assertSorted(array: Array[Int]): Unit = if (!array.sorted.sameElements(array)) { throw new Exception("Array not correctly sorted") } @Benchmark def zioBubbleSort() = { import ZIOArray._ unsafeRun( for { array <- IO.effectTotal[Array[Int]](createTestArray) _ <- bubbleSort[Int](_ <= _)(array) _ <- IO.effectTotal[Unit](assertSorted(array)) } yield () ) } @Benchmark def catsBubbleSort() = { import CatsIOArray._ import cats.effect.IO (for { array <- IO(createTestArray) _ <- bubbleSort[Int](_ <= _)(array) _ <- IO(assertSorted(array)) } yield ()).unsafeRunSync() } @Benchmark def monixBubbleSort() = { import IOBenchmarks.monixScheduler import MonixIOArray._ import monix.eval.Task (for { array <- Task.eval(createTestArray) _ <- bubbleSort[Int](_ <= _)(array) _ <- Task.eval(assertSorted(array)) } yield ()).runSyncUnsafe(scala.concurrent.duration.Duration.Inf) } }
Example 17
Source File: IODeepLeftBindBenchmark.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import org.openjdk.jmh.annotations._ import zio.IOBenchmarks._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) class IODeepLeftBindBenchmark { @Param(Array("10000")) var depth: Int = _ @Benchmark def monixDeepLeftBindBenchmark(): Int = { import monix.eval.Task var i = 0 var io = Task.eval(i) while (i < depth) { io = io.flatMap(i => Task.eval(i)) i += 1 } io.runSyncStep.right.get } @Benchmark def zioDeepLeftBindBenchmark(): Int = zioDeepLeftBindBenchmark(IOBenchmarks) @Benchmark def zioTracedDeepLeftBindBenchmark(): Int = zioDeepLeftBindBenchmark(TracedRuntime) def zioDeepLeftBindBenchmark(runtime: Runtime[Any]): Int = { var i = 0 var io = IO.effectTotal(i) while (i < depth) { io = io.flatMap(i => IO.effectTotal(i)) i += 1 } runtime.unsafeRun(io) } @Benchmark def catsDeepLeftBindBenchmark(): Int = { import cats.effect.IO var i = 0 var io = IO(i) while (i < depth) { io = io.flatMap(i => IO(i)) i += 1 } io.unsafeRunSync } }
Example 18
Source File: IOForkInterruptBenchmark.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import cats.effect.concurrent.Deferred import org.openjdk.jmh.annotations._ import zio.IOBenchmarks._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @Warmup(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Fork(1) @Threads(1) class IOForkInterruptBenchmark { @Param(Array("100")) var size: Int = _ @Benchmark def monixForkInterrupt(): Unit = { import monix.eval.Task def loop(i: Int): monix.eval.Task[Unit] = if (i < size) Deferred[Task, Unit].flatMap { p1 => Deferred[Task, Unit].flatMap { p2 => p1.complete(()) .flatMap(_ => Task.never) .guarantee(p2.complete(())) .start .flatMap(f => p1.get.flatMap(_ => f.cancel.flatMap(_ => p2.get.flatMap(_ => loop(i + 1))))) } } else Task.unit loop(0).runSyncUnsafe() } @Benchmark def catsForkInterrupt(): Unit = { import cats.effect.IO def loop(i: Int): IO[Unit] = if (i < size) Deferred[IO, Unit].flatMap { p1 => Deferred[IO, Unit].flatMap { p2 => p1.complete(()) .flatMap(_ => IO.never) .guarantee(p2.complete(())) .start .flatMap(f => p1.get.flatMap(_ => f.cancel.flatMap(_ => p2.get.flatMap(_ => loop(i + 1))))) } } else IO.unit loop(0).unsafeRunSync() } @Benchmark def zioForkInterrupt(): Unit = zioForkInterrupt(IOBenchmarks) @Benchmark def zioTracedForkInterrupt(): Unit = zioForkInterrupt(TracedRuntime) private[this] def zioForkInterrupt(runtime: Runtime[Any]): Unit = { def loop(i: Int): UIO[Unit] = if (i < size) IO.never.fork.flatMap(_.interrupt *> loop(i + 1)) else IO.unit runtime.unsafeRun(loop(0)) } }
Example 19
Source File: Endpoint.scala From lsp4s with Apache License 2.0 | 5 votes |
package scala.meta.jsonrpc import io.circe.Decoder import io.circe.Encoder import monix.eval.Task import monix.execution.Ack import scala.concurrent.Future class Endpoint[A: Decoder: Encoder, B: Decoder: Encoder](val method: String) { def encoderA: Encoder[A] = implicitly def decoderA: Decoder[A] = implicitly def encoderB: Encoder[B] = implicitly def decoderB: Decoder[B] = implicitly def request(request: A)( implicit client: JsonRpcClient ): Task[Either[Response.Error, B]] = client.request[A, B](method, request) def notify( notification: A )(implicit client: JsonRpcClient): Future[Ack] = client.notify[A](method, notification) } object Endpoint { def request[A: Decoder: Encoder, B: Decoder: Encoder]( method: String ): Endpoint[A, B] = new Endpoint(method) def notification[A: Decoder: Encoder](method: String): Endpoint[A, Unit] = new Endpoint(method) }
Example 20
Source File: JsonRpcClient.scala From lsp4s with Apache License 2.0 | 5 votes |
package scala.meta.jsonrpc import scala.concurrent.Future import io.circe.Decoder import io.circe.Encoder import monix.eval.Task import monix.execution.Ack trait JsonRpcClient { final def notify[A]( endpoint: Endpoint[A, Unit], notification: A ): Future[Ack] = notify[A](endpoint.method, notification)(endpoint.encoderA) def notify[A: Encoder](method: String, notification: A): Future[Ack] def serverRespond(response: Response): Future[Ack] def clientRespond(response: Response): Unit final def request[A, B]( endpoint: Endpoint[A, B], req: A ): Task[Either[Response.Error, B]] = request[A, B](endpoint.method, req)(endpoint.encoderA, endpoint.decoderB) def request[A: Encoder, B: Decoder]( method: String, request: A ): Task[Either[Response.Error, B]] } object JsonRpcClient { val empty: JsonRpcClient = new JsonRpcClient { override def notify[A: Encoder]( method: String, notification: A ): Future[Ack] = Ack.Continue override def serverRespond(response: Response): Future[Ack] = Ack.Continue override def clientRespond(response: Response): Unit = () override def request[A: Encoder, B: Decoder]( method: String, request: A ): Task[Either[Response.Error, B]] = Task.never } }
Example 21
Source File: LanguageClient.scala From lsp4s with Apache License 2.0 | 5 votes |
package scala.meta.jsonrpc import cats.syntax.either._ import io.circe.Decoder import io.circe.Encoder import io.circe.syntax._ import java.io.OutputStream import java.nio.ByteBuffer import monix.eval.Callback import monix.eval.Task import monix.execution.Ack import monix.execution.Cancelable import monix.execution.atomic.Atomic import monix.execution.atomic.AtomicInt import monix.reactive.Observer import scala.collection.concurrent.TrieMap import scala.concurrent.Future import scala.concurrent.duration.Duration import MonixEnrichments._ import scribe.LoggerSupport class LanguageClient(out: Observer[ByteBuffer], logger: LoggerSupport) extends JsonRpcClient { def this(out: OutputStream, logger: LoggerSupport) = this(Observer.fromOutputStream(out, logger), logger) private val writer = new MessageWriter(out, logger) private val counter: AtomicInt = Atomic(1) private val activeServerRequests = TrieMap.empty[RequestId, Callback[Response]] def notify[A: Encoder](method: String, notification: A): Future[Ack] = writer.write(Notification(method, Some(notification.asJson))) def serverRespond(response: Response): Future[Ack] = response match { case Response.Empty => Ack.Continue case x: Response.Success => writer.write(x) case x: Response.Error => logger.error(s"Response error: $x") writer.write(x) } def clientRespond(response: Response): Unit = for { id <- response match { case Response.Empty => None case Response.Success(_, requestId) => Some(requestId) case Response.Error(_, requestId) => Some(requestId) } callback <- activeServerRequests.get(id).orElse { logger.error(s"Response to unknown request: $response") None } } { activeServerRequests.remove(id) callback.onSuccess(response) } def request[A: Encoder, B: Decoder]( method: String, request: A ): Task[Either[Response.Error, B]] = { val nextId = RequestId(counter.incrementAndGet()) val response = Task.create[Response] { (out, cb) => val scheduled = out.scheduleOnce(Duration(0, "s")) { val json = Request(method, Some(request.asJson), nextId) activeServerRequests.put(nextId, cb) writer.write(json) } Cancelable { () => scheduled.cancel() this.notify("$/cancelRequest", CancelParams(nextId.value)) } } response.map { case Response.Empty => Left( Response.invalidParams( s"Got empty response for request $request", nextId ) ) case err: Response.Error => Left(err) case Response.Success(result, _) => result.as[B].leftMap { err => Response.invalidParams(err.toString, nextId) } } } } object LanguageClient { def fromOutputStream(out: OutputStream, logger: LoggerSupport) = new LanguageClient(Observer.fromOutputStream(out, logger), logger) }
Example 22
Source File: Message.scala From lsp4s with Apache License 2.0 | 5 votes |
package scala.meta.jsonrpc import monix.eval.Task import io.circe.Json import io.circe.Decoder import io.circe.Encoder import io.circe.JsonObject import io.circe.derivation.annotations.JsonCodec import io.circe.syntax._ import cats.syntax.either._ sealed trait Message object Message { implicit val encoder: Encoder[Message] = new Encoder[Message] { override def apply(a: Message): Json = { val json = a match { case r: Request => r.asJson case r: Notification => r.asJson case r: Response => r.asJson } json.mapObject(_.add("jsonrpc", "2.0".asJson)) } } implicit val decoder: Decoder[Message] = Decoder.decodeJsonObject.emap { obj => val json = Json.fromJsonObject(obj) val result = if (obj.contains("id")) if (obj.contains("error")) json.as[Response.Error] else if (obj.contains("result")) json.as[Response.Success] else json.as[Request] else json.as[Notification] result.leftMap(_.toString) } } @JsonCodec case class Request( method: String, params: Option[Json], id: RequestId ) extends Message { def toError(code: ErrorCode, message: String): Response = Response.error(ErrorObject(code, message, None), id) } @JsonCodec case class Notification(method: String, params: Option[Json]) extends Message sealed trait Response extends Message { def isSuccess: Boolean = this.isInstanceOf[Response.Success] } object Response { implicit val encoderResponse: Encoder[Response] = new Encoder[Response] { override def apply(a: Response): Json = a match { case r: Response.Success => r.asJson case r: Response.Error => r.asJson case Response.Empty => JsonObject.empty.asJson } } @JsonCodec case class Success(result: Json, id: RequestId) extends Response @JsonCodec case class Error(error: ErrorObject, id: RequestId) extends Response case object Empty extends Response def empty: Response = Empty def ok(result: Json, id: RequestId): Response = success(result, id) def okAsync[T](value: T): Task[Either[Response.Error, T]] = Task(Right(value)) def success(result: Json, id: RequestId): Response = Success(result, id) def error(error: ErrorObject, id: RequestId): Response.Error = Error(error, id) def internalError(message: String): Response.Error = internalError(message, RequestId.Null) def internalError(message: String, id: RequestId): Response.Error = Error(ErrorObject(ErrorCode.InternalError, message, None), id) def invalidParams(message: String): Response.Error = invalidParams(message, RequestId.Null) def invalidParams(message: String, id: RequestId): Response.Error = Error(ErrorObject(ErrorCode.InvalidParams, message, None), id) def invalidRequest(message: String): Response.Error = Error( ErrorObject(ErrorCode.InvalidRequest, message, None), RequestId.Null ) def cancelled(id: Json): Response.Error = Error( ErrorObject(ErrorCode.RequestCancelled, "", None), id.as[RequestId].getOrElse(RequestId.Null) ) def parseError(message: String): Response.Error = Error(ErrorObject(ErrorCode.ParseError, message, None), RequestId.Null) def methodNotFound(message: String, id: RequestId): Response.Error = Error(ErrorObject(ErrorCode.MethodNotFound, message, None), id) }
Example 23
Source File: MonixParallelTests.scala From freestyle with Apache License 2.0 | 5 votes |
package freestyle.free.tests import freestyle.free.implicits._ import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.{Matchers, WordSpec} import scala.concurrent.Await import scala.concurrent.duration.Duration class MonixParallelTests extends WordSpec with Matchers { "Applicative Parallel Support" should { "allow non deterministic execution when interpreting to monix.eval.Task" ignore { val test = new freestyle.NonDeterminismTestShared import test._ implicit val interpreter = new freestyle.MixedFreeS.Handler[Task] { override def x: Task[Int] = Task(blocker(1, 1000L)) override def y: Task[Int] = Task(blocker(2, 0L)) override def z: Task[Int] = Task(blocker(3, 2000L)) } Await.result(program.interpret[Task].runAsync, Duration.Inf) shouldBe List(3, 1, 2, 3) buf.toArray shouldBe Array(3, 2, 1, 3) } } }
Example 24
Source File: WatchServiceObservable.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio import java.nio.file.WatchEvent import monix.eval.Task import monix.execution.Ack.{ Continue, Stop } import monix.execution.atomic.Atomic import monix.execution.cancelables.SingleAssignCancelable import monix.execution.exceptions.APIContractViolationException import monix.execution.{ Callback, Cancelable, Scheduler } import monix.reactive.Observable import monix.reactive.observers.Subscriber import scala.concurrent.Future import scala.util.control.NonFatal abstract class WatchServiceObservable extends Observable[Array[WatchEvent[_]]] { def watchService: Option[WatchService] private[this] val wasSubscribed = Atomic(false) override def unsafeSubscribeFn(subscriber: Subscriber[Array[WatchEvent[_]]]): Cancelable = { if (wasSubscribed.getAndSet(true)) { subscriber.onError(APIContractViolationException(this.getClass.getName)) Cancelable.empty } else try startPolling(subscriber) catch { case NonFatal(e) => subscriber.onError(e) Cancelable.empty } } def init(subscriber: Subscriber[Array[WatchEvent[_]]]): Future[Unit] = Future.successful(()) private def startPolling(subscriber: Subscriber[Array[WatchEvent[_]]]): Cancelable = { import subscriber.scheduler val taskCallback = new Callback[Throwable, Array[WatchEvent[_]]]() { override def onSuccess(value: Array[WatchEvent[_]]): Unit = {} override def onError(ex: Throwable): Unit = { subscriber.onError(ex) } } val cancelable = Task .fromFuture(init(subscriber)) .flatMap { _ => loop(subscriber) } .executeWithOptions(_.enableAutoCancelableRunLoops) .runAsync(taskCallback) val extraCancelable = Cancelable(() => { cancelable.cancel() }) SingleAssignCancelable.plusOne(extraCancelable) } private def loop(subscriber: Subscriber[Array[WatchEvent[_]]])(implicit scheduler: Scheduler): Task[Array[WatchEvent[_]]] = { import collection.JavaConverters._ watchService.map { ws => ws.take() .doOnCancel(Task.defer(ws.close())) .flatMap { key => val events = key.pollEvents().asScala.toArray key.reset() Task.fromFuture(subscriber.onNext(events)).flatMap { case Continue => loop(subscriber) case Stop => emptyTask } } } }.getOrElse(emptyTask) private val emptyTask = Task.create[Array[WatchEvent[_]]]((_, _) => Cancelable.empty) }
Example 25
Source File: AsyncSocketChannelClient.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.tcp import monix.eval.Task import monix.execution.Scheduler def close(): Task[Unit] = taskSocketChannel.fold(Task.pure(()))(_.close()) } object AsyncSocketChannelClient { def apply( host: String, port: Int, bufferSize: Int)(implicit scheduler: Scheduler): AsyncSocketChannelClient = { val client = new AsyncSocketChannelClient(host, port, bufferSize) client.init() client } def apply( taskSocketChannel: TaskSocketChannel, bufferSize: Int)(implicit scheduler: Scheduler): AsyncSocketChannelClient = { val client = new AsyncSocketChannelClient(taskSocketChannel, bufferSize) client.init() client } }
Example 26
Source File: AsyncChannelObservable.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio import java.nio.ByteBuffer import monix.eval.Task import monix.execution.Ack.{ Continue, Stop } import monix.execution.{ Callback, Cancelable, Scheduler } import monix.execution.atomic.Atomic import monix.execution.cancelables.SingleAssignCancelable import monix.execution.exceptions.APIContractViolationException import monix.nio.internal.{ Bytes, EmptyBytes, NonEmptyBytes } import monix.reactive.Observable import monix.reactive.observers.Subscriber import scala.concurrent.Future import scala.util.control.NonFatal private[nio] abstract class AsyncChannelObservable extends Observable[Array[Byte]] { def bufferSize: Int def channel: Option[AsyncChannel] def init(subscriber: Subscriber[Array[Byte]]): Future[Unit] = Future.successful(()) private[this] val wasSubscribed = Atomic(false) override def unsafeSubscribeFn(subscriber: Subscriber[Array[Byte]]): Cancelable = { import subscriber.scheduler if (wasSubscribed.getAndSet(true)) { subscriber.onError(APIContractViolationException(this.getClass.getName)) Cancelable.empty } else try startReading(subscriber) catch { case NonFatal(e) => subscriber.onError(e) closeChannel() Cancelable.empty } } private def startReading(subscriber: Subscriber[Array[Byte]]): Cancelable = { import subscriber.scheduler val taskCallback = new Callback[Throwable, Array[Byte]]() { override def onSuccess(value: Array[Byte]): Unit = { channel.collect { case sc if sc.closeOnComplete => closeChannel() } } override def onError(ex: Throwable): Unit = { closeChannel() subscriber.onError(ex) } } val cancelable = Task .fromFuture(init(subscriber)) .flatMap { _ => loop(subscriber, 0) } .executeWithOptions(_.enableAutoCancelableRunLoops) .runAsync(taskCallback) val extraCancelable = Cancelable(() => { cancelable.cancel() closeChannel() }) SingleAssignCancelable.plusOne(extraCancelable) } private[this] val buffer = ByteBuffer.allocate(bufferSize) private def loop(subscriber: Subscriber[Array[Byte]], position: Long)(implicit scheduler: Scheduler): Task[Array[Byte]] = { buffer.clear() channel.map { ch => ch .read(buffer, position) .doOnCancel(Task.defer(ch.close())) .flatMap { result => val bytes = Bytes(buffer, result) bytes match { case EmptyBytes => subscriber.onComplete() Task.now(Bytes.emptyBytes) case NonEmptyBytes(arr) => Task.fromFuture(subscriber.onNext(arr)).flatMap { case Continue => loop(subscriber, position + result) case Stop => Task.now(Bytes.emptyBytes) } } } }.getOrElse(Task.now(Bytes.emptyBytes)) } private[nio] final def closeChannel()(implicit scheduler: Scheduler) = channel.foreach(_.close().runToFuture) }
Example 27
Source File: AsyncWatchServiceObservable.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.file import java.nio.file.WatchKey import monix.eval.Task import monix.nio.WatchServiceObservable import scala.concurrent.duration.TimeUnit final class AsyncWatchServiceObservable(taskWatchService: TaskWatchService) extends WatchServiceObservable { override def watchService = Option { asyncWatchServiceWrapper(taskWatchService) } private[file] def asyncWatchServiceWrapper(taskWatchService: TaskWatchService) = new monix.nio.WatchService { override def poll(timeout: Long, timeUnit: TimeUnit): Task[Option[WatchKey]] = taskWatchService.poll(timeout, timeUnit) override def poll(): Task[Option[WatchKey]] = taskWatchService.poll() override def take(): Task[WatchKey] = taskWatchService.take() override def close(): Task[Unit] = taskWatchService.close() } }
Example 28
Source File: TaskWatchService.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.file import java.nio.file.WatchEvent.Kind import java.nio.file.{ Path, WatchKey } import monix.eval.Task import monix.execution.{ Callback, Scheduler } import scala.concurrent.duration.TimeUnit abstract class TaskWatchService { protected val watchService: WatchService def poll(timeout: Long, timeUnit: TimeUnit): Task[Option[WatchKey]] = Task.create { (scheduler, cb) => watchService.poll(timeout, timeUnit, Callback.forked(cb)(scheduler)) } def poll(): Task[Option[WatchKey]] = Task.create { (scheduler, cb) => watchService.poll(Callback.forked(cb)(scheduler)) } def take(): Task[WatchKey] = Task.create { (scheduler, cb) => watchService.take(Callback.forked(cb)(scheduler)) } def close(): Task[Unit] = Task.now(watchService.close()) } object TaskWatchService { def apply(path: Path, events: Kind[_]*)(implicit s: Scheduler): TaskWatchService = { new TaskWatchService { override val watchService: WatchService = WatchService.apply(path, events: _*) } } }
Example 29
Source File: UdpIntegrationSpec.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.udp import java.net.InetSocketAddress import minitest.SimpleTestSuite import monix.eval.Task import monix.execution.Ack import monix.execution.Ack.{ Continue, Stop } import monix.reactive.Observable import scala.concurrent.duration._ import scala.concurrent.{ Await, Promise } object UdpIntegrationSpec extends SimpleTestSuite { implicit val ctx = monix.execution.Scheduler.Implicits.global test("send and receive UDP packets successfully") { val data = Array.fill(8)("monix") val writes = (ch: TaskDatagramChannel, to: InetSocketAddress) => Observable .fromIterable(data) .mapEval(data => ch.send(Packet(data.getBytes, to))) val readsPromise = Promise[String]() val recv = new StringBuilder("") val reads = (ch: TaskDatagramChannel, maxSize: Int) => Observable .repeatEval(ch.receive(maxSize, 2.seconds)) .mapEval(t => t) .map { packet => packet.foreach(p => recv.append(new String(p.data))) packet } .guaranteeCase(_ => Task(readsPromise.success(recv.mkString))) .subscribe(_.fold[Ack](Stop)(_ => Continue)) val program = for { ch <- bind("localhost", 2115).map { ch => reads(ch, 64) ch } sent <- writes(ch, new InetSocketAddress("localhost", 2115)).sumL received <- Task.fromFuture(readsPromise.future) _ <- ch.close() } yield sent == 40 & received == data.mkString("") val result = Await.result(program.runToFuture, 10.seconds) assert(result) } }
Example 30
Source File: WatchServiceTest.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.file import java.io.File import java.nio.file.{ Paths, WatchEvent } import minitest.SimpleTestSuite import monix.eval.Task import monix.execution.Ack.{ Continue, Stop } import scala.concurrent.duration._ import scala.concurrent.{ Await, Promise } object WatchServiceTest extends SimpleTestSuite { implicit val ctx = monix.execution.Scheduler.Implicits.global test("file event captured") { val path = Paths.get(System.getProperty("java.io.tmpdir")) val watchP = Promise[Boolean]() val watchT = Task.evalAsync { watchAsync(path).timeoutOnSlowUpstream(10.seconds).subscribe( (events: Array[WatchEvent[_]]) => { val captured = events.find(e => s"${e.kind().name()} - ${e.context().toString}".contains("monix")) if (captured.isDefined) { watchP.success(true) Stop } else { Continue } }, err => watchP.failure(err), () => watchP.success(true)) } val fileT = Task.evalAsync { val temp = File.createTempFile("monix", ".tmp", path.toFile) Thread.sleep(2000) temp.delete() } watchT.runToFuture fileT.runToFuture val result = Await.result(watchP.future, 20.seconds) assert(result) } }
Example 31
Source File: FileChannelForTesting.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.file import java.nio.ByteBuffer import monix.eval.Task import monix.execution.{ Callback, Scheduler } import monix.execution.atomic.Atomic import monix.nio.AsyncChannel class FileChannelForTesting( readingSeq: Vector[Array[Byte]], writeSeq: Atomic[Vector[Array[Byte]]])(implicit s: Scheduler) extends TaskFileChannel with AsyncChannel { private val asyncFileChannelForTesting = new AsyncFileChannelForTesting(readingSeq, writeSeq) override val closeOnComplete: Boolean = true override val asyncFileChannel: AsyncFileChannel = asyncFileChannelForTesting def isClosed = asyncFileChannelForTesting.isClosed def getBytesReadPosition = asyncFileChannelForTesting.getBytesReadPosition def getBytesWritePosition = asyncFileChannelForTesting.getBytesWritePosition def createReadException() = asyncFileChannelForTesting.createReadException() def createWriteException() = asyncFileChannelForTesting.createWriteException() private final class AsyncFileChannelForTesting( readingSeq: Vector[Array[Byte]], writeSeq: Atomic[Vector[Array[Byte]]])(implicit s: Scheduler) extends AsyncFileChannel { private val readChannelPosition = Atomic(0) private val writeChannelPosition = Atomic(0) private val channelClosed = Atomic(false) private val readException = Atomic(false) private val writeException = Atomic(false) def isClosed = channelClosed.get def getBytesReadPosition = readChannelPosition.get def getBytesWritePosition = writeChannelPosition.get def createReadException() = readException.set(true) def createWriteException() = writeException.set(true) def taskCallback(handler: Callback[Throwable, Int]) = new Callback[Throwable, Array[Byte]]() { override def onSuccess(value: Array[Byte]): Unit = handler.onSuccess(value.length) override def onError(ex: Throwable): Unit = handler.onError(ex) } override def isOpen: Boolean = !isClosed override def flush(writeMetaData: Boolean, cb: Callback[Throwable, Unit]): Unit = ??? override def size(cb: Callback[Throwable, Long]): Unit = () //not really used override def read(dst: ByteBuffer, position: Long, handler: Callback[Throwable, Int]) = { if (readException.get) handler.onError(new Exception("Test Exception")) else if (readChannelPosition.get < readingSeq.size) { val pos = readChannelPosition.getAndIncrement() val r = Task { val elem = readingSeq(pos) dst.put(elem) elem } r.runAsync(taskCallback(handler)) } else { handler.onSuccess(-1) } } override def write(b: ByteBuffer, position: Long, handler: Callback[Throwable, Int]) = { if (writeException.get) handler.onError(new Exception("Test Exception")) else { val pos = writeChannelPosition.getAndIncrement() val r = Task { val bytes = b.array() writeSeq.transform { v => if (v.size > pos) v.updated(pos, bytes) else v :+ bytes } bytes } r.runAsync(taskCallback(handler)) } } override def close() = { channelClosed.set(true) } } }
Example 32
Source File: CodecTest.scala From monix-nio with Apache License 2.0 | 5 votes |
package monix.nio.file import java.nio.file.{ Files, Paths } import java.util import minitest.SimpleTestSuite import monix.eval.Task import monix.execution.Callback import monix.execution.Scheduler.Implicits.{ global => ctx } import monix.nio.file import monix.nio.text.UTF8Codec.{ utf8Decode, utf8Encode } import monix.reactive.Observable import scala.concurrent.duration._ import scala.concurrent.{ Await, Promise } object CodecTest extends SimpleTestSuite { test("decode file utf8") { val from = Paths.get(this.getClass.getResource("/testFiles/specialChars.txt").toURI) val p = Promise[Seq[Byte]]() val callback = new Callback[Throwable, List[Array[Byte]]] { override def onSuccess(value: List[Array[Byte]]): Unit = p.success(value.flatten) override def onError(ex: Throwable): Unit = p.failure(ex) } readAsync(from, 3) .pipeThrough(utf8Decode) .pipeThrough(utf8Encode) .toListL .runAsync(callback) val result = Await.result(p.future, 3.second) val f1 = Files.readAllBytes(from) val f2 = result assert(util.Arrays.equals(f1, f2.toArray)) } test("decode special chars") { val strSeq = Seq("A", "\u0024", "\u00A2", "\u20AC", new String(Array(0xF0, 0x90, 0x8D, 0x88).map(_.toByte)), "B") for (grouping <- 1 to 12) { val obsSeq = Observable .fromIterator(Task(strSeq.flatMap(_.getBytes).grouped(grouping).map(_.toArray))) .pipeThrough(utf8Decode) val p = Promise[Boolean]() val callback = new Callback[Throwable, List[String]] { override def onSuccess(value: List[String]): Unit = { p.success(if (value.mkString == strSeq.mkString) true else false) } override def onError(ex: Throwable): Unit = p.failure(ex) } obsSeq.toListL.runAsync(callback) val result = Await.result(p.future, 3.second) assert(result) } } test("copy file utf8") { val from = Paths.get(this.getClass.getResource("/testFiles/specialChars.txt").toURI) val to = Paths.get("src/test/resources/res.txt") val consumer = file.writeAsync(to) val p = Promise[Long]() val callback = new Callback[Throwable, Long] { override def onSuccess(value: Long): Unit = p.success(value) override def onError(ex: Throwable): Unit = p.failure(ex) } readAsync(from, 3) .pipeThrough(utf8Decode) .map { str => //Console.println(str) str } .pipeThrough(utf8Encode) .consumeWith(consumer) .runAsync(callback) val result = Await.result(p.future, 3.second) val f1 = Files.readAllBytes(from) val f2 = result Files.delete(to) assertEquals(f1.size, f2) } }
Example 33
Source File: implicits.scala From frees-rpc-workshop with Apache License 2.0 | 5 votes |
package scalaexchange package serverapp import cats.{~>, Applicative} import freestyle.rpc.server.handlers.GrpcServerHandler import freestyle.rpc.server._ import freestyle.rpc.server.implicits._ import monix.eval.Task import scalaexchange.services.protocol.RFMAnalysisService import scalaexchange.services.runtime.RFMAnalysisServiceHandler trait Implicits extends scalaexchange.CommonImplicits { implicit def rfmAnalisysServiceHandler[F[_]: Applicative]( implicit T2F: Task ~> F): RFMAnalysisServiceHandler[F] = new RFMAnalysisServiceHandler[F] val grpcConfigs: List[GrpcConfig] = List( AddService( RFMAnalysisService.bindService[ConcurrentMonad] ) ) implicit def grpcServerHandler: GrpcServer.Op ~> ConcurrentMonad = new GrpcServerHandler[ConcurrentMonad] andThen new GrpcKInterpreter[ConcurrentMonad](ServerW(port, grpcConfigs).server) }
Example 34
Source File: MonixAutoAckConsumer.scala From fs2-rabbit with Apache License 2.0 | 5 votes |
package dev.profunktor.fs2rabbit.examples import cats.data.NonEmptyList import cats.effect._ import cats.syntax.functor._ import dev.profunktor.fs2rabbit.config.{Fs2RabbitConfig, Fs2RabbitNodeConfig} import dev.profunktor.fs2rabbit.interpreter.RabbitClient import dev.profunktor.fs2rabbit.resiliency.ResilientStream import monix.eval.{Task, TaskApp} import java.util.concurrent.Executors object MonixAutoAckConsumer extends TaskApp { private val config: Fs2RabbitConfig = Fs2RabbitConfig( virtualHost = "/", nodes = NonEmptyList.one( Fs2RabbitNodeConfig( host = "127.0.0.1", port = 5672 ) ), username = Some("guest"), password = Some("guest"), ssl = false, connectionTimeout = 3, requeueOnNack = false, requeueOnReject = false, internalQueueSize = Some(500), automaticRecovery = true ) val blockerResource = Resource .make(Task(Executors.newCachedThreadPool()))(es => Task(es.shutdown())) .map(Blocker.liftExecutorService) override def run(args: List[String]): Task[ExitCode] = blockerResource.use { blocker => RabbitClient[Task](config, blocker).flatMap { client => ResilientStream .runF(new AutoAckConsumerDemo[Task](client).program) .as(ExitCode.Success) } } }
Example 35
Source File: AdminRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.admin.routes import akka.actor.ActorSystem import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.index.{OrganizationCache, ProjectCache} import ch.epfl.bluebrain.nexus.admin.organizations.Organizations import ch.epfl.bluebrain.nexus.admin.projects.Projects import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.routes.EventRoutes import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.{HttpConfig, PaginationConfig, PersistenceConfig} import monix.eval.Task import monix.execution.Scheduler.Implicits.global object AdminRoutes { final def apply( orgs: Organizations[Task], projects: Projects[Task], orgCache: OrganizationCache[Task], projCache: ProjectCache[Task], acls: Acls[Task], realms: Realms[Task] )(implicit as: ActorSystem, cfg: ServiceConfig ): Route = { implicit val hc: HttpConfig = cfg.http implicit val pc: PersistenceConfig = cfg.persistence implicit val pgc: PaginationConfig = cfg.pagination val eventsRoutes = new EventRoutes(acls, realms).routes val orgRoutes = new OrganizationRoutes(orgs, orgCache, acls, realms).routes val projectRoutes = new ProjectRoutes(projects, orgCache, projCache, acls, realms).routes pathPrefix(cfg.http.prefix) { eventsRoutes ~ orgRoutes ~ projectRoutes } } }
Example 36
Source File: PathDirectives.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.admin.directives import java.util.UUID import akka.http.scaladsl.server.Directive1 import akka.http.scaladsl.server.Directives._ import ch.epfl.bluebrain.nexus.admin.index.{OrganizationCache, ProjectCache} import monix.eval.Task import monix.execution.Scheduler import scala.util.Try object PathDirectives { def project(implicit cache: ProjectCache[Task], s: Scheduler): Directive1[(String, String)] = pathPrefix(Segment / Segment).tflatMap { case (orgSegment, projSegment) => Try((UUID.fromString(orgSegment), UUID.fromString(projSegment))) .map { case (orgUuid, projUuid) => onSuccess(cache.get(orgUuid, projUuid).runToFuture).flatMap { case Some(resource) => provide((resource.value.organizationLabel, resource.value.label)) case None => provide((orgSegment, projSegment)) } } .getOrElse(provide((orgSegment, projSegment))) } }
Example 37
Source File: RepairFromMessages.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.admin import java.util.UUID import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.PersistenceQuery import ch.epfl.bluebrain.nexus.admin.organizations.Organizations import ch.epfl.bluebrain.nexus.admin.projects.Projects import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.Future import scala.util.Try object RepairFromMessages { private val log = Logger[RepairFromMessages.type] def repair( o: Organizations[Task], p: Projects[Task] )(implicit as: ActorSystem, sc: Scheduler): Future[Unit] = { val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) pq.currentPersistenceIds() .mapAsync(1) { case OrgId(uuid) => (o.fetch(uuid) >> Task.unit).runToFuture case ProjId(uuid) => (p.fetch(uuid) >> Task.unit).runToFuture case other => log.warn(s"Unknown persistence id '$other'") Future.successful(()) } .runFold(0) { case (acc, _) => if (acc % 100 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .map(_ => ()) } sealed abstract class PersistenceId(prefix: String) { private val len = prefix.length def unapply(arg: String): Option[UUID] = if (arg.startsWith(prefix)) Try(UUID.fromString(arg.drop(len))).toOption else None } object OrgId extends PersistenceId("organizations-") object ProjId extends PersistenceId("projects-") }
Example 38
Source File: EventRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.actor.ActorSystem import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.client.types.{Organization, Project} import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._ import ch.epfl.bluebrain.nexus.rdf.Iri.Path._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class EventRoutes(acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit override val as: ActorSystem, override val config: ServiceConfig ) extends AuthDirectives(acls, realms) with EventCommonRoutes { private val read: Permission = Permission.unsafe("resources/read") def routes(project: Project): Route = { lastEventId { offset => operationName(s"/${config.http.prefix}/resources/{org}/{project}/events") { authorizeFor(project.organizationLabel / project.label, read)(caller) { complete(source(s"project=${project.uuid}", offset)) } } } } def routes(org: Organization): Route = lastEventId { offset => operationName(s"/${config.http.prefix}/resources/{org}/events") { authorizeFor(/ + org.label, read)(caller) { complete(source(s"org=${org.uuid}", offset)) } } } }
Example 39
Source File: TagRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.http.scaladsl.model.StatusCodes.{Created, OK} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.kg.config.Contexts.tagCtxUri import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._ import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources._ import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import ch.epfl.bluebrain.nexus.rdf.Iri.Path._ import ch.epfl.bluebrain.nexus.rdf.implicits._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import io.circe.syntax._ import io.circe.{Encoder, Json} import kamon.Kamon import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class TagRoutes private[routes] ( resourceType: String, tags: Tags[Task], acls: Acls[Task], realms: Realms[Task], schema: Ref, write: Permission )(implicit caller: Caller, project: Project, config: ServiceConfig ) extends AuthDirectives(acls, realms) { private val projectPath = project.organizationLabel / project.label implicit private val subject: Subject = caller.subject def routes(id: AbsoluteIri): Route = // Consume the tag segment pathPrefix("tags") { concat( // Create tag (post & parameter("rev".as[Long]) & pathEndOrSingleSlash) { rev => operationName(opName) { (authorizeFor(projectPath, write) & projectNotDeprecated) { entity(as[Json]) { source => Kamon.currentSpan().tag("resource.operation", "create") complete(tags.create(Id(project.ref, id), rev, source, schema).value.runWithStatus(Created)) } } } }, // Fetch a tag (get & projectNotDeprecated & pathEndOrSingleSlash) { operationName(opName) { authorizeFor(projectPath, read)(caller) { parameter("rev".as[Long].?) { case Some(rev) => complete(tags.fetch(Id(project.ref, id), rev, schema).value.runWithStatus(OK)) case _ => complete(tags.fetch(Id(project.ref, id), schema).value.runWithStatus(OK)) } } } } ) } implicit private def tagsEncoder: Encoder[TagSet] = Encoder.instance(tags => Json.obj("tags" -> Json.arr(tags.map(_.asJson).toSeq: _*)).addContext(tagCtxUri)) private def opName: String = resourceType match { case "resources" => s"/${config.http.prefix}/resources/{org}/{project}/{schemaId}/{id}/tags" case _ => s"/${config.http.prefix}/$resourceType/{org}/{project}/{id}/tags" } }
Example 40
Source File: Clients.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import ch.epfl.bluebrain.nexus.admin.client.AdminClient import ch.epfl.bluebrain.nexus.commons.es.client.ElasticSearchClient import ch.epfl.bluebrain.nexus.commons.http.HttpClient import ch.epfl.bluebrain.nexus.commons.http.HttpClient.UntypedHttpClient import ch.epfl.bluebrain.nexus.commons.search.QueryResults import ch.epfl.bluebrain.nexus.commons.sparql.client.BlazegraphClient import ch.epfl.bluebrain.nexus.storage.client.StorageClient import io.circe.Json import monix.eval.Task final case class Clients[F[_]]()(implicit val sparql: BlazegraphClient[F], val elasticSearch: ElasticSearchClient[F], val admin: AdminClient[F], val defaultRemoteStorage: StorageClient[F], val rsSearch: HttpClient[F, QueryResults[Json]], val http: UntypedHttpClient[Task], val uclJson: HttpClient[Task, Json] ) object Clients { implicit def esClient[F[_]](implicit clients: Clients[F]): ElasticSearchClient[F] = clients.elasticSearch implicit def sparqlClient[F[_]](implicit clients: Clients[F]): BlazegraphClient[F] = clients.sparql }
Example 41
Source File: ArchiveRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.http.scaladsl.model.StatusCodes.{Created, OK} import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.model.{HttpEntity, MediaTypes} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Caller import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject import ch.epfl.bluebrain.nexus.kg.KgError.{InvalidOutputFormat, UnacceptedResponseContentType} import ch.epfl.bluebrain.nexus.kg.archives.Archive._ import ch.epfl.bluebrain.nexus.kg.directives.PathDirectives._ import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._ import ch.epfl.bluebrain.nexus.kg.directives.QueryDirectives.outputFormat import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources._ import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.Tar import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import ch.epfl.bluebrain.nexus.rdf.Iri.Path._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import io.circe.Json import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class ArchiveRoutes private[routes] (archives: Archives[Task], acls: Acls[Task], realms: Realms[Task])(implicit project: Project, caller: Caller, config: ServiceConfig ) extends AuthDirectives(acls, realms) { private val responseType = MediaTypes.`application/x-tar` private val projectPath = project.organizationLabel / project.label implicit private val subject: Subject = caller.subject def routes(id: AbsoluteIri): Route = { val resId = Id(project.ref, id) concat( // Create archive (put & pathEndOrSingleSlash) { operationName(s"/${config.http.prefix}/archives/{org}/{project}/{id}") { (authorizeFor(projectPath, write) & projectNotDeprecated) { entity(as[Json]) { source => complete(archives.create(resId, source).value.runWithStatus(Created)) } } } }, // Fetch archive (get & outputFormat(strict = true, Tar) & pathEndOrSingleSlash) { case Tar => getArchive(resId) case format: NonBinaryOutputFormat => getResource(resId)(format) case other => failWith(InvalidOutputFormat(other.toString)) } ) } private def getResource(resId: ResId)(implicit format: NonBinaryOutputFormat): Route = completeWithFormat(archives.fetch(resId).value.runWithStatus(OK)) private def getArchive(resId: ResId): Route = { (parameter("ignoreNotFound".as[Boolean] ? false) & extractCallerAcls(anyProject)) { (ignoreNotFound, acls) => onSuccess(archives.fetchArchive(resId, ignoreNotFound)(acls, caller).value.runToFuture) { case Right(source) => headerValueByType[Accept](()) { accept => if (accept.mediaRanges.exists(_.matches(responseType))) complete(HttpEntity(responseType, source)) else failWith( UnacceptedResponseContentType( s"File Media Type '$responseType' does not match the Accept header value '${accept.mediaRanges.mkString(", ")}'" ) ) } case Left(err) => complete(err) } } } }
Example 42
Source File: GlobalEventRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.actor.ActorSystem import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._ import akka.http.scaladsl.server.Directives.complete import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.kg.persistence.TaggingAdapter import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class GlobalEventRoutes(acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit override val as: ActorSystem, override val config: ServiceConfig ) extends AuthDirectives(acls, realms) with EventCommonRoutes { private val read: Permission = Permission.unsafe("events/read") def routes: Route = lastEventId { offset => operationName(s"/${config.http.prefix}/events") { authorizeFor(permission = read)(caller) { complete(source(TaggingAdapter.EventTag, offset)) } } } }
Example 43
Source File: Status.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.cluster.{Cluster, MemberStatus} import monix.eval.Task sealed trait Status { def check: Task[Boolean] } object Status { class ClusterStatus(cluster: Cluster) extends Status { override def check: Task[Boolean] = Task.pure( !cluster.isTerminated && cluster.state.leader.isDefined && cluster.state.members.nonEmpty && !cluster.state.members.exists(_.status != MemberStatus.Up) && cluster.state.unreachable.isEmpty ) } }
Example 44
Source File: ProjectDirectives.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.directives import java.util.UUID import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{Directive0, Directive1} import cats.implicits._ import ch.epfl.bluebrain.nexus.admin.client.AdminClient import ch.epfl.bluebrain.nexus.admin.client.types.{Organization, Project} import ch.epfl.bluebrain.nexus.iam.client.types.AuthToken import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject import ch.epfl.bluebrain.nexus.kg.KgError.{OrganizationNotFound, ProjectIsDeprecated, ProjectNotFound} import ch.epfl.bluebrain.nexus.kg.cache.ProjectCache import ch.epfl.bluebrain.nexus.kg.config.Schemas import ch.epfl.bluebrain.nexus.kg.resources.{OrganizationRef, ProjectInitializer} import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier._ import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv import monix.eval.Task import monix.execution.Scheduler import scala.util.{Success, Try} object ProjectDirectives { // TODO: Remove when migrating ADMIN client implicit private val fakeToken: Option[AuthToken] = None val defaultPrefixMapping: Map[String, AbsoluteIri] = Map( "resource" -> Schemas.unconstrainedSchemaUri, "schema" -> Schemas.shaclSchemaUri, "view" -> Schemas.viewSchemaUri, "resolver" -> Schemas.resolverSchemaUri, "file" -> Schemas.fileSchemaUri, "storage" -> Schemas.storageSchemaUri, "nxv" -> nxv.base, "documents" -> nxv.defaultElasticSearchIndex.value, "graph" -> nxv.defaultSparqlIndex.value, "defaultResolver" -> nxv.defaultResolver.value, "defaultStorage" -> nxv.defaultStorage.value ) def projectNotDeprecated(implicit proj: Project): Directive0 = if (proj.deprecated) failWith(ProjectIsDeprecated(proj.projectLabel)) else pass }
Example 45
Source File: ProjectAttributesCoordinator.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.async import akka.actor.{ActorRef, ActorSystem} import cats.effect.Async import cats.implicits._ import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.kg.async.ProjectAttributesCoordinatorActor.Msg._ import ch.epfl.bluebrain.nexus.kg.cache.ProjectCache import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.kg.resources.{Files, OrganizationRef} import ch.epfl.bluebrain.nexus.kg.storage.Storage.StorageOperations.FetchAttributes import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.sourcing.projections.Projections import monix.eval.Task def stop(projectRef: ProjectRef): F[Unit] = { ref ! Stop(projectRef.id) F.unit } } object ProjectAttributesCoordinator { def apply(files: Files[Task], projectCache: ProjectCache[Task])(implicit config: ServiceConfig, fetchAttributes: FetchAttributes[Task], as: ActorSystem, P: Projections[Task, String] ): ProjectAttributesCoordinator[Task] = { val coordinatorRef = ProjectAttributesCoordinatorActor.start(files, None, config.cluster.shards) new ProjectAttributesCoordinator[Task](projectCache, coordinatorRef) } }
Example 46
Source File: RepairFromMessages.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg import java.net.URLDecoder import java.util.UUID import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.PersistenceQuery import ch.epfl.bluebrain.nexus.kg.resources.{Id, Repo, ResId} import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef import ch.epfl.bluebrain.nexus.rdf.Iri import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import scala.concurrent.Future import scala.util.Try object RepairFromMessages { // $COVERAGE-OFF$ private val log = Logger[RepairFromMessages.type] def repair(repo: Repo[Task])(implicit as: ActorSystem, sc: Scheduler, pm: CanBlock): Unit = { log.info("Repairing dependent tables from messages.") val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) Task .fromFuture { pq.currentPersistenceIds() .mapAsync(1) { case ResourceId(id) => (repo.get(id, None).value >> Task.unit).runToFuture case other => log.warn(s"Unknown persistence id '$other'") Future.successful(()) } .runFold(0) { case (acc, _) => if (acc % 1000 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .map(_ => ()) } .runSyncUnsafe() log.info("Finished repairing dependent tables from messages.") } object ResourceId { private val regex = "^resources\\-([0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12})\\-(.+)$".r def unapply(arg: String): Option[ResId] = arg match { case regex(stringUuid, stringId) => for { uuid <- Try(UUID.fromString(stringUuid)).toOption iri <- Iri.absolute(URLDecoder.decode(stringId, "UTF-8")).toOption } yield Id(ProjectRef(uuid), iri) case _ => None } } // $COVERAGE-ON$ }
Example 47
Source File: IamRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.actor.ActorSystem import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.permissions.Permissions import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.{HttpConfig, PersistenceConfig} import monix.eval.Task object IamRoutes { final def apply( acls: Acls[Task], realms: Realms[Task], perms: Permissions[Task] )(implicit as: ActorSystem, cfg: ServiceConfig): Route = { implicit val hc: HttpConfig = cfg.http implicit val pc: PersistenceConfig = cfg.persistence val eventsRoutes = new EventRoutes(acls, realms).routes val idsRoutes = new IdentitiesRoutes(acls, realms).routes val permsRoutes = new PermissionsRoutes(perms, acls, realms).routes val realmsRoutes = new RealmsRoutes(acls, realms).routes val aclsRoutes = new AclsRoutes(acls, realms).routes pathPrefix(cfg.http.prefix) { eventsRoutes ~ aclsRoutes ~ permsRoutes ~ realmsRoutes ~ idsRoutes } } }
Example 48
Source File: PermissionsRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.javadsl.server.Rejections._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.permissions.Permissions import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract} import ch.epfl.bluebrain.nexus.iam.types.Permission import ch.epfl.bluebrain.nexus.iam.types.ResourceF._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import ch.epfl.bluebrain.nexus.service.marshallers.instances._ import io.circe.{Decoder, DecodingFailure} import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class PermissionsRoutes(permissions: Permissions[Task], acls: Acls[Task], realms: Realms[Task])(implicit http: HttpConfig ) extends AuthDirectives(acls, realms) { def routes: Route = (pathPrefix("permissions") & pathEndOrSingleSlash) { operationName(s"/${http.prefix}/permissions") { extractCaller { implicit caller => concat( get { parameter("rev".as[Long].?) { case Some(rev) => complete(permissions.fetchAt(rev).runNotFound) case None => complete(permissions.fetch.runToFuture) } }, (put & parameter("rev" ? 0L)) { rev => entity(as[PatchPermissions]) { case Replace(set) => complete(permissions.replace(set, rev).runToFuture) case _ => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'.")) } }, delete { parameter("rev".as[Long]) { rev => complete(permissions.delete(rev).runToFuture) } }, (patch & parameter("rev" ? 0L)) { rev => entity(as[PatchPermissions]) { case Append(set) => complete(permissions.append(set, rev).runToFuture) case Subtract(set) => complete(permissions.subtract(set, rev).runToFuture) case _ => reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'.")) } } ) } } } } object PermissionsRoutes { sealed private[routes] trait PatchPermissions extends Product with Serializable private[routes] object PatchPermissions { final case class Append(permissions: Set[Permission]) extends PatchPermissions final case class Subtract(permissions: Set[Permission]) extends PatchPermissions final case class Replace(permissions: Set[Permission]) extends PatchPermissions implicit val patchPermissionsDecoder: Decoder[PatchPermissions] = Decoder.instance { hc => for { permissions <- hc.get[Set[Permission]]("permissions") tpe = hc.get[String]("@type").getOrElse("Replace") patch <- tpe match { case "Replace" => Right(Replace(permissions)) case "Append" => Right(Append(permissions)) case "Subtract" => Right(Subtract(permissions)) case _ => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history)) } } yield patch } } }
Example 49
Source File: IdentitiesRoutes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Caller.JsonLd._ import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig import ch.epfl.bluebrain.nexus.service.marshallers.instances._ import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class IdentitiesRoutes(acls: Acls[Task], realms: Realms[Task])(implicit http: HttpConfig) extends AuthDirectives(acls, realms) { def routes: Route = { (pathPrefix("identities") & pathEndOrSingleSlash) { operationName(s"/${http.prefix}/identities") { (extractCaller & get) { caller => complete(caller) } } } } }
Example 50
Source File: RepairFromMessages.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam import java.net.URLDecoder import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.PersistenceQuery import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.permissions.Permissions import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Label import ch.epfl.bluebrain.nexus.rdf.Iri.Path import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import scala.concurrent.Future object RepairFromMessages { // $COVERAGE-OFF$ private val log = Logger[RepairFromMessages.type] def repair( p: Permissions[Task], r: Realms[Task], a: Acls[Task] )(implicit as: ActorSystem, sc: Scheduler, pm: CanBlock): Unit = { val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) pq.currentPersistenceIds() .mapAsync(1) { case PermissionsId() => p.agg.currentState(p.persistenceId).runToFuture case RealmId(label) => r.agg.currentState(label.value).runToFuture case AclId(path) => a.agg.currentState(path.asString).runToFuture case other => log.warn(s"Unknown persistence id '$other'") Future.successful(()) } .runFold(0) { case (acc, _) => if (acc % 100 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .runSyncDiscard() log.info("Repair from messages table completed.") } sealed abstract class PersistenceId(prefix: String) { private val len = prefix.length protected def dropPrefix(arg: String): Option[String] = if (arg.startsWith(prefix)) Some(arg.drop(len)) else None } object RealmId extends PersistenceId("realms-") { def unapply(arg: String): Option[Label] = dropPrefix(arg).map(Label.unsafe) } object AclId extends PersistenceId("acls-") { def unapply(arg: String): Option[Path] = dropPrefix(arg).flatMap(str => Path(URLDecoder.decode(str, "UTF-8")).toOption) } object PermissionsId { def unapply(arg: String): Boolean = arg == "permissions-permissions" } implicit class RichFuture[A](val future: Future[A]) extends AnyVal { def runSyncDiscard()(implicit s: Scheduler, permit: CanBlock): Unit = Task.fromFuture(future).map(_ => ()).runSyncUnsafe() } // $COVERAGE-ON$ }
Example 51
Source File: AuthDirectives.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.service.directives import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.directives.Credentials import akka.http.scaladsl.server.directives.FutureDirectives.onComplete import akka.http.scaladsl.server.{Directive0, Directive1} import cats.implicits._ import ch.epfl.bluebrain.nexus.admin.exceptions.AdminError.AuthorizationFailed import ch.epfl.bluebrain.nexus.iam.acls.{AccessControlLists, Acls} import ch.epfl.bluebrain.nexus.iam.auth.AccessToken import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.IamError.InvalidAccessToken import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.kg.KgError.AuthenticationFailed import ch.epfl.bluebrain.nexus.rdf.Iri.{AbsoluteIri, Path} import ch.epfl.bluebrain.nexus.rdf.Iri.Path._ import ch.epfl.bluebrain.nexus.rdf.implicits._ import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig import ch.epfl.bluebrain.nexus.service.exceptions.ServiceError.InternalError import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.Future import scala.util.{Failure, Success} def extractCallerAcls(path: Path)(implicit c: Caller): Directive1[AccessControlLists] = onComplete(acls.list(path, ancestors = true, self = true).runToFuture).flatMap { case Success(AccessControlLists.empty) => failWith(AuthorizationFailed) case Success(result) => provide(result) case Failure(err) => val message = "Error when trying to check for permissions" logger.error(message, err) failWith(InternalError(message)) } }
Example 52
Source File: instances.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.service.marshallers import akka.http.scaladsl.marshalling.GenericMarshallers.eitherMarshaller import akka.http.scaladsl.marshalling._ import akka.http.scaladsl.model.MediaTypes.`application/json` import akka.http.scaladsl.model._ import ch.epfl.bluebrain.nexus.admin.exceptions.AdminError import ch.epfl.bluebrain.nexus.admin.organizations.OrganizationRejection import ch.epfl.bluebrain.nexus.admin.projects.ProjectRejection import ch.epfl.bluebrain.nexus.commons.circe.syntax._ import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport.OrderedKeys import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes._ import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom import ch.epfl.bluebrain.nexus.iam.acls.AclRejection import ch.epfl.bluebrain.nexus.iam.permissions.PermissionsRejection import ch.epfl.bluebrain.nexus.iam.realms.RealmRejection import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.orderedKeys import ch.epfl.bluebrain.nexus.service.exceptions.ServiceError import ch.epfl.bluebrain.nexus.service.exceptions.ServiceError.InternalError import ch.epfl.bluebrain.nexus.service.routes.ResourceRejection import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport import io.circe._ import io.circe.syntax._ import monix.eval.Task import monix.execution.Scheduler import scala.collection.immutable.Seq import scala.concurrent.Future import scala.concurrent.duration.FiniteDuration object instances extends FailFastCirceSupport { implicit val finiteDurationEncoder: Encoder[FiniteDuration] = Encoder.encodeString.contramap(fd => s"${fd.toMillis} ms") implicit val resourceRejectionEncoder: Encoder[ResourceRejection] = Encoder.instance { case r: ProjectRejection => Encoder[ProjectRejection].apply(r) case r: OrganizationRejection => Encoder[OrganizationRejection].apply(r) case r: AclRejection => Encoder[AclRejection].apply(r) case r: RealmRejection => Encoder[RealmRejection].apply(r) case r: PermissionsRejection => Encoder[PermissionsRejection].apply(r) case _ => Encoder[ServiceError].apply(InternalError("unspecified")) } implicit val resourceRejectionStatusFrom: StatusFrom[ResourceRejection] = StatusFrom { case r: OrganizationRejection => OrganizationRejection.organizationStatusFrom(r) case r: ProjectRejection => ProjectRejection.projectStatusFrom(r) case r: AclRejection => AclRejection.aclRejectionStatusFrom(r) case r: RealmRejection => RealmRejection.realmRejectionStatusFrom(r) case r: PermissionsRejection => PermissionsRejection.permissionsRejectionStatusFrom(r) } override def unmarshallerContentTypes: Seq[ContentTypeRange] = List(`application/json`, `application/ld+json`, `application/sparql-results+json`) implicit final def rejection[A <: ResourceRejection: Encoder](implicit statusFrom: StatusFrom[A], printer: Printer = Printer.noSpaces.copy(dropNullValues = true), ordered: OrderedKeys = orderedKeys ): ToResponseMarshaller[A] = { val marshallers = Seq(`application/ld+json`, `application/json`).map { contentType => Marshaller.withFixedContentType[A, HttpResponse](contentType) { rejection => HttpResponse( status = statusFrom(rejection), entity = HttpEntity(contentType, printer.print(rejection.asJson.sortKeys)) ) } } Marshaller.oneOf(marshallers: _*) } implicit class EitherTask[R <: ResourceRejection, A](task: Task[Either[R, A]])(implicit s: Scheduler) { def runWithStatus(code: StatusCode): Future[Either[R, (StatusCode, A)]] = task.map(_.map(code -> _)).runToFuture } implicit class OptionTask[A](task: Task[Option[A]])(implicit s: Scheduler) { def runNotFound: Future[A] = task.flatMap { case Some(a) => Task.pure(a) case None => Task.raiseError(AdminError.NotFound) }.runToFuture } }
Example 53
Source File: EventRoutesSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.NotUsed import akka.actor.ActorSystem import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.`Last-Event-ID` import akka.http.scaladsl.model.sse.ServerSentEvent import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence} import akka.stream.scaladsl.Source import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.kg.resources.Event import ch.epfl.bluebrain.nexus.kg.routes.EventRoutesSpec.TestableEventRoutes import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import ch.epfl.bluebrain.nexus.rdf.Iri.Path._ import io.circe.Encoder import monix.eval.Task class EventRoutesSpec extends EventsSpecBase { private val aclsApi = mock[Acls[Task]] private val realms = mock[Realms[Task]] val eventRoutes = new TestableEventRoutes(events, aclsApi, realms, caller) "EventRoutes" should { val read = Permission.unsafe("resources/read") aclsApi.hasPermission("org" / "project", read)(caller) shouldReturn Task.pure(true) aclsApi.hasPermission(/ + "org", read)(caller) shouldReturn Task.pure(true) "return all events for a project" in { Get("/") ~> eventRoutes.routes(project) ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected) } } "return all events for a project from the last seen" in { Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(project) ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected, 1) } } "return all events for an organization" in { Get("/") ~> eventRoutes.routes(organization) ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected) } } "return all events for an organization from the last seen" in { Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(organization) ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected, 1) } } } } object EventRoutesSpec { class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit as: ActorSystem, config: ServiceConfig ) extends EventRoutes(acls, realms, caller) { private val envelopes = events.zipWithIndex.map { case (ev, idx) => EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L) } override protected def source( tag: String, offset: Offset )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = { val toDrop = offset match { case NoOffset => 0 case Sequence(v) => v + 1 } Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList)) } } }
Example 54
Source File: GlobalEventRoutesSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.NotUsed import akka.actor.ActorSystem import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.`Last-Event-ID` import akka.http.scaladsl.model.sse.ServerSentEvent import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence} import akka.stream.scaladsl.Source import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Caller import ch.epfl.bluebrain.nexus.kg.resources.Event import ch.epfl.bluebrain.nexus.kg.routes.GlobalEventRoutesSpec.TestableEventRoutes import ch.epfl.bluebrain.nexus.rdf.Iri.Path import ch.epfl.bluebrain.nexus.service.config.ServiceConfig import io.circe.Encoder import monix.eval.Task class GlobalEventRoutesSpec extends EventsSpecBase { private val aclsApi = mock[Acls[Task]] private val realms = mock[Realms[Task]] val routes = new TestableEventRoutes(events, aclsApi, realms, caller).routes aclsApi.hasPermission(Path./, read)(caller) shouldReturn Task.pure(true) "GlobalEventRoutes" should { "return all events for a project" in { Get("/") ~> routes ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected) } } "return all events for a project from the last seen" in { Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> routes ~> check { val expected = jsonContentOf("/events/events.json").asArray.value status shouldEqual StatusCodes.OK responseAs[String] shouldEqual eventStreamFor(expected, 1) } } } } object GlobalEventRoutesSpec { class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit as: ActorSystem, config: ServiceConfig ) extends GlobalEventRoutes(acls, realms, caller) { private val envelopes = events.zipWithIndex.map { case (ev, idx) => EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L) } override protected def source( tag: String, offset: Offset )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = { val toDrop = offset match { case NoOffset => 0 case Sequence(v) => v + 1 } Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList)) } } }
Example 55
Source File: ResolverCacheSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.cache import akka.actor.ExtendedActorSystem import akka.serialization.Serialization import akka.testkit._ import ch.epfl.bluebrain.nexus.commons.test.ActorSystemFixture import ch.epfl.bluebrain.nexus.iam.types.Identity.Anonymous import ch.epfl.bluebrain.nexus.kg.TestHelper import ch.epfl.bluebrain.nexus.kg.config.KgConfig._ import ch.epfl.bluebrain.nexus.kg.resolve.Resolver._ import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.{ProjectLabel, ProjectRef} import ch.epfl.bluebrain.nexus.service.config.{ServiceConfig, Settings} import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.{Inspectors, TryValues} import scala.concurrent.duration._ //noinspection NameBooleanParameters class ResolverCacheSpec extends ActorSystemFixture("ResolverCacheSpec", true) with Matchers with Inspectors with ScalaFutures with TryValues with TestHelper { implicit override def patienceConfig: PatienceConfig = PatienceConfig(3.seconds.dilated, 5.milliseconds) implicit private val appConfig: ServiceConfig = Settings(system).serviceConfig implicit private val keyValueStoreCfg = appConfig.kg.keyValueStore.keyValueStoreConfig val ref1 = ProjectRef(genUUID) val ref2 = ProjectRef(genUUID) val label1 = ProjectLabel(genString(), genString()) val label2 = ProjectLabel(genString(), genString()) val resolver: InProjectResolver = InProjectResolver(ref1, genIri, 1L, false, 10) val crossRefs: CrossProjectResolver = CrossProjectResolver(Set(genIri), List(ref1, ref2), Set(Anonymous), ref1, genIri, 0L, false, 1) val crossLabels: CrossProjectResolver = CrossProjectResolver(Set(genIri), List(label1, label2), Set(Anonymous), ref1, genIri, 0L, false, 1) val resolverProj1: Set[InProjectResolver] = List.fill(5)(resolver.copy(id = genIri)).toSet val resolverProj2: Set[InProjectResolver] = List.fill(5)(resolver.copy(id = genIri, ref = ref2)).toSet private val cache = ResolverCache[Task] "ResolverCache" should { "index resolvers" in { val list = (resolverProj1 ++ resolverProj2).toList forAll(list) { resolver => cache.put(resolver).runToFuture.futureValue cache.get(resolver.ref, resolver.id).runToFuture.futureValue shouldEqual Some(resolver) } } "list resolvers" in { cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs resolverProj1 cache.get(ref2).runToFuture.futureValue should contain theSameElementsAs resolverProj2 } "deprecate resolver" in { val resolver = resolverProj1.head cache.put(resolver.copy(deprecated = true, rev = 2L)).runToFuture.futureValue cache.get(resolver.ref, resolver.id).runToFuture.futureValue shouldEqual None cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs resolverProj1.filterNot(_ == resolver) } "serialize cross project resolver" when { val serialization = new Serialization(system.asInstanceOf[ExtendedActorSystem]) "parameterized with ProjectRef" in { val bytes = serialization.serialize(crossRefs).success.value val out = serialization.deserialize(bytes, classOf[CrossProjectResolver]).success.value out shouldEqual crossRefs } "parameterized with ProjectLabel" in { val bytes = serialization.serialize(crossLabels).success.value val out = serialization.deserialize(bytes, classOf[CrossProjectResolver]).success.value out shouldEqual crossLabels } } } }
Example 56
Source File: StorageCacheSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.cache import java.nio.file.Paths import java.time.Clock import akka.testkit._ import ch.epfl.bluebrain.nexus.commons.test.ActorSystemFixture import ch.epfl.bluebrain.nexus.kg.TestHelper import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef import ch.epfl.bluebrain.nexus.kg.storage.Storage.DiskStorage import ch.epfl.bluebrain.nexus.rdf.implicits._ import ch.epfl.bluebrain.nexus.service.config.{ServiceConfig, Settings} import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.{Inspectors, TryValues} import scala.concurrent.duration._ //noinspection NameBooleanParameters class StorageCacheSpec extends ActorSystemFixture("StorageCacheSpec", true) with Matchers with Inspectors with ScalaFutures with TryValues with TestHelper { implicit override def patienceConfig: PatienceConfig = PatienceConfig(3.seconds.dilated, 5.milliseconds) implicit private val clock: Clock = Clock.systemUTC implicit private val appConfig: ServiceConfig = Settings(system).serviceConfig implicit private val keyValueStoreCfg = appConfig.kg.keyValueStore.keyValueStoreConfig val ref1 = ProjectRef(genUUID) val ref2 = ProjectRef(genUUID) val time = clock.instant() val lastId = url"http://example.com/lastA" // initialInstant.minusSeconds(1L + genInt().toLong) val tempStorage = DiskStorage(ref1, genIri, 1L, false, true, "alg", Paths.get("/tmp"), read, write, 1024L) val lastStorageProj1 = tempStorage.copy(id = lastId) val lastStorageProj2 = tempStorage.copy(ref = ref2, id = lastId) val storagesProj1: List[DiskStorage] = List.fill(5)(tempStorage.copy(id = genIri)) :+ lastStorageProj1 val storagesProj2: List[DiskStorage] = List.fill(5)(tempStorage.copy(ref = ref2, id = genIri)) :+ lastStorageProj2 private val cache = StorageCache[Task] "StorageCache" should { "index storages" in { forAll((storagesProj1 ++ storagesProj2).zipWithIndex) { case (storage, index) => implicit val instant = time.plusSeconds(index.toLong) cache.put(storage).runToFuture.futureValue cache.get(storage.ref, storage.id).runToFuture.futureValue shouldEqual Some(storage) } } "get latest default storage" in { cache.getDefault(ref1).runToFuture.futureValue shouldEqual Some(lastStorageProj1) cache.getDefault(ref2).runToFuture.futureValue shouldEqual Some(lastStorageProj2) cache.getDefault(ProjectRef(genUUID)).runToFuture.futureValue shouldEqual None } "list storages" in { cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs storagesProj1 cache.get(ref2).runToFuture.futureValue should contain theSameElementsAs storagesProj2 } "deprecate storage" in { val storage = storagesProj1.head implicit val instant = time.plusSeconds(30L) cache.put(storage.copy(deprecated = true, rev = 2L)).runToFuture.futureValue cache.get(storage.ref, storage.id).runToFuture.futureValue shouldEqual None cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs storagesProj1.filterNot(_ == storage) } } }
Example 57
Source File: IdentitiesRoutesSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.testkit.ScalatestRouteTest import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.auth.{AccessToken, TokenRejection} import ch.epfl.bluebrain.nexus.iam.realms._ import ch.epfl.bluebrain.nexus.iam.testsyntax._ import ch.epfl.bluebrain.nexus.iam.types.Caller import ch.epfl.bluebrain.nexus.iam.types.IamError.InvalidAccessToken import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Authenticated, User} import ch.epfl.bluebrain.nexus.service.config.Settings import ch.epfl.bluebrain.nexus.service.marshallers.instances._ import ch.epfl.bluebrain.nexus.service.routes.Routes import ch.epfl.bluebrain.nexus.util.Resources import com.typesafe.config.{Config, ConfigFactory} import io.circe.Json import monix.eval.Task import org.mockito.matchers.MacroBasedMatchers import org.mockito.{IdiomaticMockito, Mockito} import org.scalatest.BeforeAndAfter import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike import scala.concurrent.duration._ //noinspection TypeAnnotation class IdentitiesRoutesSpec extends AnyWordSpecLike with Matchers with ScalatestRouteTest with BeforeAndAfter with MacroBasedMatchers with Resources with ScalaFutures with IdiomaticMockito { implicit override def patienceConfig: PatienceConfig = PatienceConfig(3.seconds, 100.milliseconds) override def testConfig: Config = ConfigFactory.load("test.conf") private val config = Settings(system).serviceConfig implicit private val http = config.http private val realms: Realms[Task] = mock[Realms[Task]] private val acls: Acls[Task] = mock[Acls[Task]] before { Mockito.reset(realms, acls) } "The IdentitiesRoutes" should { val routes = Routes.wrap(new IdentitiesRoutes(acls, realms).routes) "return forbidden" in { val err = InvalidAccessToken(TokenRejection.InvalidAccessToken) realms.caller(any[AccessToken]) shouldReturn Task.raiseError(err) Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check { status shouldEqual StatusCodes.Unauthorized } } "return anonymous" in { realms.caller(any[AccessToken]) shouldReturn Task.pure(Caller.anonymous) Get("/identities") ~> routes ~> check { status shouldEqual StatusCodes.OK responseAs[Json].sort shouldEqual jsonContentOf("/identities/anonymous.json") } } "return all identities" in { val user = User("theuser", "therealm") val auth = Authenticated("therealm") val caller = Caller(user, Set(user, Anonymous, auth)) realms.caller(any[AccessToken]) shouldReturn Task.pure(caller) Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check { status shouldEqual StatusCodes.OK responseAs[Json].sort shouldEqual jsonContentOf("/identities/identities.json") } } } }
Example 58
Source File: Main.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli import cats.Parallel import cats.effect.{ContextShift, ExitCode, Timer} import cats.syntax.all._ import monix.catnap.SchedulerEffect import monix.eval.{Task, TaskApp} // $COVERAGE-OFF$ object Main extends TaskApp { override def run(args: List[String]): Task[ExitCode] = { implicit val cs: ContextShift[Task] = SchedulerEffect.contextShift[Task](scheduler) implicit val tm: Timer[Task] = SchedulerEffect.timer[Task](scheduler) implicit val pl: Parallel[Task] = Task.catsParallel Cli(args, sys.env).recoverWith { case err: CliError => Task.delay(println(err.show)).as(ExitCode.Error) } } }
Example 59
Source File: instances.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.storage.routes import akka.http.scaladsl.marshalling.GenericMarshallers.eitherMarshaller import akka.http.scaladsl.marshalling._ import akka.http.scaladsl.model.MediaTypes._ import akka.http.scaladsl.model._ import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes._ import ch.epfl.bluebrain.nexus.storage.JsonLdCirceSupport.sortKeys import ch.epfl.bluebrain.nexus.storage.JsonLdCirceSupport.OrderedKeys import ch.epfl.bluebrain.nexus.storage.Rejection import ch.epfl.bluebrain.nexus.storage.config.AppConfig._ import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport import io.circe._ import io.circe.syntax._ import monix.eval.Task import monix.execution.Scheduler import scala.collection.immutable.Seq import scala.concurrent.Future object instances extends LowPriority { implicit final def valueWithStatusCodeMarshaller[A: Encoder](implicit printer: Printer = defaultPrinter, keys: OrderedKeys = orderedKeys ): ToResponseMarshaller[(StatusCode, A)] = jsonLdWithStatusCodeMarshaller.compose { case (status, value) => status -> value.asJson } private[routes] def onOf[A, Response]( fMarshaller: MediaType.WithFixedCharset => Marshaller[A, Response] ): Marshaller[A, Response] = { val marshallers = Seq(`application/ld+json`, `application/json`).map(fMarshaller) Marshaller.oneOf(marshallers: _*) } }
Example 60
Source File: AuthDirectives.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.storage.routes import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.server.Directive1 import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.directives.FutureDirectives.onComplete import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.{AccessToken, Caller} import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClientError.IdentitiesClientStatusError import ch.epfl.bluebrain.nexus.storage.StorageError._ import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler.Implicits.global import scala.util.{Failure, Success} object AuthDirectives { private val logger = Logger[this.type] def extractCaller(implicit identities: IamIdentitiesClient[Task], token: Option[AccessToken]): Directive1[Caller] = onComplete(identities().runToFuture).flatMap { case Success(caller) => provide(caller) case Failure(IdentitiesClientStatusError(StatusCodes.Unauthorized, _)) => failWith(AuthenticationFailed) case Failure(IdentitiesClientStatusError(StatusCodes.Forbidden, _)) => failWith(AuthorizationFailed) case Failure(err) => val message = "Error when trying to extract the subject" logger.error(message, err) failWith(InternalError(message)) } }
Example 61
Source File: Routes.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.storage.routes import akka.http.scaladsl.model.headers.{`WWW-Authenticate`, HttpChallenges} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route} import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.Caller import ch.epfl.bluebrain.nexus.storage.StorageError._ import ch.epfl.bluebrain.nexus.storage.config.AppConfig import ch.epfl.bluebrain.nexus.storage.config.AppConfig._ import ch.epfl.bluebrain.nexus.storage.routes.AuthDirectives._ import ch.epfl.bluebrain.nexus.storage.routes.PrefixDirectives._ import ch.epfl.bluebrain.nexus.storage.routes.instances._ import ch.epfl.bluebrain.nexus.storage.{AkkaSource, IamIdentitiesClient, Rejection, StorageError, Storages} import com.typesafe.scalalogging.Logger import monix.eval.Task import scala.util.control.NonFatal object Routes { private[this] val logger = Logger[this.type] def apply( storages: Storages[Task, AkkaSource] )(implicit config: AppConfig, identities: IamIdentitiesClient[Task]): Route = //TODO: Fetch Bearer token and verify identity wrap { concat( AppInfoRoutes(config.description).routes, (pathPrefix(config.http.prefix) & extractToken) { implicit token => extractCaller.apply { case Caller(config.subject.subjectValue, _) => StorageRoutes(storages).routes case _ => failWith(AuthenticationFailed) } } ) } }
Example 62
Source File: Main.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.storage import java.nio.file.Paths import java.time.Clock import akka.actor.ActorSystem import akka.event.{Logging, LoggingAdapter} import akka.http.scaladsl.Http import akka.http.scaladsl.server.Route import akka.util.Timeout import cats.effect.Effect import ch.epfl.bluebrain.nexus.storage.Storages.DiskStorage import ch.epfl.bluebrain.nexus.storage.attributes.AttributesCache import ch.epfl.bluebrain.nexus.storage.config.{AppConfig, Settings} import ch.epfl.bluebrain.nexus.storage.config.AppConfig._ import ch.epfl.bluebrain.nexus.storage.routes.Routes import com.typesafe.config.{Config, ConfigFactory} import kamon.Kamon import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.duration._ import scala.concurrent.{Await, ExecutionContext, Future} import scala.util.{Failure, Success} //noinspection TypeAnnotation // $COVERAGE-OFF$ object Main { def loadConfig(): Config = { val cfg = sys.env.get("STORAGE_CONFIG_FILE") orElse sys.props.get("storage.config.file") map { str => val file = Paths.get(str).toAbsolutePath.toFile ConfigFactory.parseFile(file) } getOrElse ConfigFactory.empty() (cfg withFallback ConfigFactory.load()).resolve() } def setupMonitoring(config: Config): Unit = { if (sys.env.getOrElse("KAMON_ENABLED", "false").toBoolean) { Kamon.reconfigure(config) Kamon.loadModules() } } def shutdownMonitoring(): Unit = { if (sys.env.getOrElse("KAMON_ENABLED", "false").toBoolean) { Await.result(Kamon.stopModules(), 10.seconds) } } @SuppressWarnings(Array("UnusedMethodParameter")) def main(args: Array[String]): Unit = { val config = loadConfig() setupMonitoring(config) implicit val appConfig: AppConfig = Settings(config).appConfig implicit val as: ActorSystem = ActorSystem(appConfig.description.fullName, config) implicit val ec: ExecutionContext = as.dispatcher implicit val eff: Effect[Task] = Task.catsEffect(Scheduler.global) implicit val iamIdentities: IamIdentitiesClient[Task] = new IamIdentitiesClient[Task](appConfig.iam) implicit val timeout = Timeout(1.minute) implicit val clock = Clock.systemUTC val storages: Storages[Task, AkkaSource] = new DiskStorage(appConfig.storage, appConfig.digest, AttributesCache[Task, AkkaSource]) val logger: LoggingAdapter = Logging(as, getClass) logger.info("==== Cluster is Live ====") val routes: Route = Routes(storages) val httpBinding: Future[Http.ServerBinding] = { Http().bindAndHandle(routes, appConfig.http.interface, appConfig.http.port) } httpBinding onComplete { case Success(binding) => logger.info(s"Bound to ${binding.localAddress.getHostString}: ${binding.localAddress.getPort}") case Failure(th) => logger.error(th, "Failed to perform an http binding on {}:{}", appConfig.http.interface, appConfig.http.port) Await.result(as.terminate(), 10.seconds) } as.registerOnTermination { shutdownMonitoring() } // attempt to leave the cluster before shutting down val _ = sys.addShutdownHook { Await.result(as.terminate().map(_ => ()), 10.seconds) } } } // $COVERAGE-ON$
Example 63
Source File: AppInfoRoutesSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.storage.routes import java.util.regex.Pattern.quote import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.server.Route import akka.http.scaladsl.testkit.ScalatestRouteTest import ch.epfl.bluebrain.nexus.storage.config.{AppConfig, Settings} import ch.epfl.bluebrain.nexus.storage.routes.instances._ import ch.epfl.bluebrain.nexus.storage.utils.Resources import ch.epfl.bluebrain.nexus.storage.{AkkaSource, IamIdentitiesClient, Storages} import io.circe.Json import monix.eval.Task import org.mockito.IdiomaticMockito import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike class AppInfoRoutesSpec extends AnyWordSpecLike with Matchers with ScalatestRouteTest with IdiomaticMockito with Resources { "the app info routes" should { implicit val config: AppConfig = Settings(system).appConfig implicit val iamIdentities: IamIdentitiesClient[Task] = mock[IamIdentitiesClient[Task]] val route: Route = Routes(mock[Storages[Task, AkkaSource]]) "return application information" in { Get("/") ~> route ~> check { status shouldEqual OK responseAs[Json] shouldEqual jsonContentOf("/app-info.json", Map(quote("{version}") -> config.description.version)) } } } }
Example 64
Source File: UserAccountRepositoryOnMemory.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.memory import com.github.j5ik2o.dddbase.example.dao.memory.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ OnMemory, UserAccountRepository } import com.github.j5ik2o.dddbase.memory._ import com.google.common.base.Ticker import monix.eval.Task import scala.concurrent.duration.Duration class UserAccountRepositoryOnMemory( concurrencyLevel: Option[Int] = None, expireAfterAccess: Option[Duration] = None, expireAfterWrite: Option[Duration] = None, initialCapacity: Option[Int] = None, maximumSize: Option[Int] = None, maximumWeight: Option[Int] = None, recordStats: Option[Boolean] = None, refreshAfterWrite: Option[Duration] = None, softValues: Option[Boolean] = None, ticker: Option[Ticker] = None, weakKeys: Option[Boolean] = None, weakValues: Option[Boolean] = None ) extends UserAccountRepository[OnMemory] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiWriteFeature with AggregateMultiReadFeature with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature with UserAccountComponent { override type RecordType = UserAccountRecord override type DaoType = UserAccountDao override protected val dao: UserAccountDao = new UserAccountDao( concurrencyLevel = concurrencyLevel, expireAfterAccess = expireAfterAccess, expireAfterWrite = expireAfterWrite, initialCapacity = initialCapacity, maximumSize = maximumSize, maximumWeight = maximumWeight, recordStats = recordStats, refreshAfterWrite = refreshAfterWrite, softValues = softValues, ticker = ticker, weakKeys = weakKeys, weakValues = weakValues ) override protected def convertToAggregate: UserAccountRecord => Task[UserAccount] = { record => Task.pure { UserAccount( id = UserAccountId(record.id.toLong), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } override protected def convertToRecord: UserAccount => Task[UserAccountRecord] = { aggregate => Task.pure { UserAccountRecord( id = aggregate.id.value.toString, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } }
Example 65
Source File: AbstractUserMessageRepositoryBySlick.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.slick import com.github.j5ik2o.dddbase.example.dao.slick.UserMessageComponent import com.github.j5ik2o.dddbase.example.model.{ Status, UserMessage, UserMessageId } import com.github.j5ik2o.dddbase.example.repository.{ BySlick, UserMessageRepository } import com.github.j5ik2o.dddbase.slick._ import monix.eval.Task import slick.jdbc.JdbcProfile import slick.lifted.Rep abstract class AbstractUserMessageRepositoryBySlick(val profile: JdbcProfile, val db: JdbcProfile#Backend#Database) extends UserMessageRepository[BySlick] with AggregateSingleReadFeature with AggregateMultiReadFeature with AggregateSingleWriteFeature with AggregateMultiWriteFeature with UserMessageComponent { override type RecordType = UserMessageRecord override type TableType = UserMessages override protected val dao = UserMessageDao override protected def byCondition(id: IdType): TableType => Rep[Boolean] = { v => import profile.api._ v.userId === id.userId && v.messageId === id.messageId } override protected def byConditions(ids: Seq[IdType]): TableType => Rep[Boolean] = { v => import profile.api._ ids .map { id => v.userId === id.userId && v.messageId === id.messageId } .reduceLeft(_ || _) } override protected def convertToAggregate: UserMessageRecord => Task[UserMessage] = { record => Task.pure { UserMessage( id = UserMessageId(record.userId, record.messageId), status = Status.withName(record.status), message = record.message, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } override protected def convertToRecord: UserMessage => Task[UserMessageRecord] = { aggregate => Task.pure { UserMessageRecord( messageId = aggregate.id.messageId, userId = aggregate.id.userId, status = aggregate.status.entryName, message = aggregate.message, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } }
Example 66
Source File: AbstractUserAccountRepositoryBySlick.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.slick import com.github.j5ik2o.dddbase.example.dao.slick.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ BySlick, UserAccountRepository } import com.github.j5ik2o.dddbase.slick.{ AggregateMultiReadFeature, AggregateMultiWriteFeature, AggregateSingleReadFeature, AggregateSingleWriteFeature } import monix.eval.Task import slick.jdbc.JdbcProfile import slick.lifted.Rep abstract class AbstractUserAccountRepositoryBySlick(val profile: JdbcProfile, val db: JdbcProfile#Backend#Database) extends UserAccountRepository[BySlick] with AggregateSingleReadFeature with AggregateMultiReadFeature with AggregateSingleWriteFeature with AggregateMultiWriteFeature with UserAccountComponent { override type RecordType = UserAccountRecord override type TableType = UserAccounts override protected val dao = UserAccountDao override protected def byCondition(id: IdType): TableType => Rep[Boolean] = { import profile.api._ _.id === id.value } override protected def byConditions(ids: Seq[IdType]): TableType => Rep[Boolean] = { import profile.api._ _.id.inSet(ids.map(_.value)) } override protected def convertToAggregate: UserAccountRecord => Task[UserAccount] = { record => Task.pure { UserAccount( id = UserAccountId(record.id), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } override protected def convertToRecord: UserAccount => Task[UserAccountRecord] = { aggregate => Task.pure { UserAccountRecord( id = aggregate.id.value, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } }
Example 67
Source File: UserAccountRepositoryOnMemcached.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.memcached import akka.actor.ActorSystem import cats.data.ReaderT import com.github.j5ik2o.dddbase.example.dao.memcached.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ OnMemcached, UserAccountRepository } import com.github.j5ik2o.dddbase.memcached._ import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task import scala.concurrent.duration._ class UserAccountRepositoryOnMemcached(val expireDuration: Duration)(implicit system: ActorSystem) extends UserAccountRepository[OnMemcached] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature with UserAccountComponent { require(expireDuration.gteq(1 seconds)) override type RecordType = UserAccountRecord override type DaoType = UserAccountDao override protected val dao: UserAccountDao = UserAccountDao() override protected def convertToAggregate: UserAccountRecord => ReaderT[Task, MemcachedConnection, UserAccount] = { record => ReaderT { _ => Task.pure { UserAccount( id = UserAccountId(record.id.toLong), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } } override protected def convertToRecord: UserAccount => ReaderT[Task, MemcachedConnection, UserAccountRecord] = { aggregate => ReaderT { _ => Task.pure { UserAccountRecord( id = aggregate.id.value.toString, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } } }
Example 68
Source File: UserAccountRepositoryOnRedis.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.redis import akka.actor.ActorSystem import cats.data.ReaderT import com.github.j5ik2o.dddbase.example.dao.redis.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ OnRedis, UserAccountRepository } import com.github.j5ik2o.dddbase.redis._ import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task import scala.concurrent.duration.Duration class UserAccountRepositoryOnRedis(val expireDuration: Duration)(implicit system: ActorSystem) extends UserAccountRepository[OnRedis] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature with UserAccountComponent { override type RecordType = UserAccountRecord override type DaoType = UserAccountDao override protected val dao = UserAccountDao() override protected def convertToAggregate: UserAccountRecord => ReaderT[Task, RedisConnection, UserAccount] = { record => ReaderT { _ => Task.pure { UserAccount( id = UserAccountId(record.id.toLong), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } } override protected def convertToRecord: UserAccount => ReaderT[Task, RedisConnection, UserAccountRecord] = { aggregate => ReaderT { _ => Task.pure { UserAccountRecord( id = aggregate.id.value.toString, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } } }
Example 69
Source File: UserAccountRepositoryBySkinny.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.example.dao.skinny.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ BySkinny, UserAccountRepository } import com.github.j5ik2o.dddbase.skinny._ import monix.eval.Task import scalikejdbc._ trait UserAccountRepositoryBySkinny extends UserAccountRepository[BySkinny] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with UserAccountComponent { override type RecordIdType = Long override type RecordType = UserAccountRecord override type DaoType = UserAccountDao.type override protected val dao: UserAccountDao.type = UserAccountDao override protected def toRecordId(id: UserAccountId): Long = id.value override protected def byCondition(id: IdType): SQLSyntax = sqls.eq(dao.defaultAlias.id, id.value) override protected def byConditions(ids: Seq[IdType]): SQLSyntax = sqls.in(dao.defaultAlias.id, ids.map(_.value)) override protected def convertToAggregate: UserAccountRecord => ReaderT[Task, DBSession, UserAccount] = { record => ReaderT { _ => Task.pure { UserAccount( id = UserAccountId(record.id), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } } override protected def convertToRecord: UserAccount => ReaderT[Task, DBSession, UserAccountRecord] = { aggregate => ReaderT { _ => Task.pure { UserAccountRecord( id = aggregate.id.value, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } } } class UserAccountRepositoryBySkinnyImpl extends UserAccountRepositoryBySkinny with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature
Example 70
Source File: UserMessageRepositoryBySkinny.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.example.dao.skinny.UserMessageComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ BySkinny, UserMessageRepository } import com.github.j5ik2o.dddbase.skinny._ import monix.eval.Task import scalikejdbc.{ sqls, DBSession, SQLSyntax } trait UserMessageRepositoryBySkinny extends UserMessageRepository[BySkinny] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with UserMessageComponent { override type RecordIdType = UserMessageRecordId override type RecordType = UserMessageRecord override type DaoType = UserMessageDao.type override protected val dao: UserMessageDao.type = UserMessageDao override protected def toRecordId(id: UserMessageId): UserMessageRecordId = UserMessageRecordId(id.messageId, id.userId) override protected def byCondition(id: IdType): SQLSyntax = sqls.eq(dao.column.messageId, id.messageId).and.eq(dao.column.userId, id.userId) override protected def byConditions(ids: Seq[IdType]): SQLSyntax = sqls.in((dao.column.messageId, dao.column.userId), ids.map(v => (v.messageId, v.userId))) override protected def convertToAggregate: UserMessageRecord => ReaderT[Task, DBSession, UserMessage] = { record => ReaderT { _ => Task.pure { UserMessage( id = UserMessageId(record.userId, record.messageId), status = Status.withName(record.status), message = record.message, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } } override protected def convertToRecord: UserMessage => ReaderT[Task, DBSession, UserMessageRecord] = { aggregate => ReaderT { _ => Task.pure { UserMessageRecord( messageId = aggregate.id.messageId, userId = aggregate.id.userId, status = aggregate.status.entryName, message = aggregate.message, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } } } class UserMessageRepositoryBySkinnyImpl extends UserMessageRepositoryBySkinny with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature
Example 71
Source File: UserAccountRepositoryOnDynamoDB.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.dynamodb import com.github.j5ik2o.dddbase.dynamodb._ import com.github.j5ik2o.dddbase.example.dao.dynamodb.UserAccountComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ OnDynamoDB, UserAccountRepository } import com.github.j5ik2o.reactive.aws.dynamodb.monix.DynamoDbMonixClient import monix.eval.Task class UserAccountRepositoryOnDynamoDB(client: DynamoDbMonixClient) extends UserAccountRepository[OnDynamoDB] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature with UserAccountComponent { override type RecordIdType = String override type RecordType = UserAccountRecord override type DaoType = UserAccountDao override protected val dao = UserAccountDao(client) override protected def toRecordId(id: UserAccountId): String = id.value.toString override protected def convertToAggregate: UserAccountRecord => Task[UserAccount] = { record => Task.pure { UserAccount( id = UserAccountId(record.id.toLong), status = Status.withName(record.status), emailAddress = EmailAddress(record.email), password = HashedPassword(record.password), firstName = record.firstName, lastName = record.lastName, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } override protected def convertToRecord: UserAccount => Task[UserAccountRecord] = { aggregate => Task.pure { UserAccountRecord( id = aggregate.id.value.toString, status = aggregate.status.entryName, email = aggregate.emailAddress.value, password = aggregate.password.value, firstName = aggregate.firstName, lastName = aggregate.lastName, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } }
Example 72
Source File: UserMessageRepositoryOnDynamoDB.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.dynamodb import com.github.j5ik2o.dddbase.dynamodb._ import com.github.j5ik2o.dddbase.example.dao.dynamodb.UserMessageComponent import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ OnDynamoDB, UserMessageRepository } import com.github.j5ik2o.reactive.aws.dynamodb.monix.DynamoDbMonixClient import monix.eval.Task class UserMessageRepositoryOnDynamoDB(client: DynamoDbMonixClient) extends UserMessageRepository[OnDynamoDB] with AggregateSingleReadFeature with AggregateSingleWriteFeature with AggregateMultiReadFeature with AggregateMultiWriteFeature with AggregateSingleSoftDeleteFeature with AggregateMultiSoftDeleteFeature with UserMessageComponent { override type RecordIdType = UserMessageRecordId override type RecordType = UserMessageRecord override type DaoType = UserMessageDao override protected val dao = UserMessageDao(client) override protected def toRecordId( id: UserMessageId ): UserMessageRecordId = UserMessageRecordId(id.userId, id.messageId) override protected def convertToAggregate: UserMessageRecord => Task[UserMessage] = { record => Task.pure { UserMessage( id = UserMessageId(record.id.userId, record.id.messageId), status = Status.withName(record.status), message = record.message, createdAt = record.createdAt, updatedAt = record.updatedAt ) } } override protected def convertToRecord: UserMessage => Task[UserMessageRecord] = { aggregate => Task.pure { UserMessageRecord( id = UserMessageRecordId(aggregate.id.userId, aggregate.id.messageId), status = aggregate.status.entryName, message = aggregate.message, createdAt = aggregate.createdAt, updatedAt = aggregate.updatedAt ) } } }
Example 73
Source File: UserAccountRepositoryOnMemorySpec.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.example.repository.memory import java.time.ZonedDateTime import com.github.j5ik2o.dddbase.AggregateNotFoundException import com.github.j5ik2o.dddbase.example.model._ import com.github.j5ik2o.dddbase.example.repository.{ IdGenerator, SpecSupport, UserAccountRepository } import com.github.j5ik2o.dddbase.example.repository.util.ScalaFuturesSupportSpec import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.concurrent.ScalaFutures import org.scalatest.{ FreeSpec, Matchers } import scala.concurrent.duration._ import scala.concurrent.{ Await, Future } class UserAccountRepositoryOnMemorySpec extends FreeSpec with ScalaFutures with ScalaFuturesSupportSpec with Matchers with SpecSupport { val userAccount = UserAccount( id = UserAccountId(IdGenerator.generateIdValue), status = Status.Active, emailAddress = EmailAddress("[email protected]"), password = HashedPassword("aaa"), firstName = "Junichi", lastName = "Kato", createdAt = ZonedDateTime.now, updatedAt = None ) val userAccounts = for (idx <- 1L to 10L) yield UserAccount( id = UserAccountId(IdGenerator.generateIdValue), status = Status.Active, emailAddress = EmailAddress(s"user${idx}@gmail.com"), password = HashedPassword("aaa"), firstName = "Junichi", lastName = "Kato", createdAt = ZonedDateTime.now, updatedAt = None ) "UserAccountRepositoryOnMemory" - { "store" in { val repository = UserAccountRepository.onMemory() val result: UserAccount = (for { _ <- repository.store(userAccount) r <- repository.resolveById(userAccount.id) } yield r).runToFuture.futureValue result shouldBe userAccount } "storeMulti" in { val repository = UserAccountRepository.onMemory() val result: Seq[UserAccount] = (for { _ <- repository.storeMulti(userAccounts) r <- repository.resolveMulti(userAccounts.map(_.id)) } yield r).runToFuture.futureValue sameAs(result, userAccounts) shouldBe true } "store then expired" in { val repository = UserAccountRepository.onMemory(expireAfterWrite = Some(1 seconds)) val resultFuture: Future[UserAccount] = (for { _ <- repository.store(userAccount) _ <- Task.pure(Thread.sleep(1000)) r <- repository.resolveById(userAccount.id) } yield r).runToFuture an[AggregateNotFoundException] should be thrownBy { Await.result(resultFuture, Duration.Inf) } } } }
Example 74
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memory import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import monix.eval.Task trait AggregateSingleReadFeature extends AggregateSingleReader[Task] with AggregateBaseReadFeature { override def resolveById(id: IdType): Task[AggregateType] = for { record <- dao.get(id.value.toString).flatMap { case Some(v) => Task.pure(v) case None => Task.raiseError(AggregateNotFoundException(id)) } aggregate <- convertToAggregate(record) } yield aggregate }
Example 75
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memcached import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task trait AggregateSingleReadFeature extends AggregateSingleReader[ReaderT[Task, MemcachedConnection, ?]] with AggregateBaseReadFeature { override def resolveById(id: IdType): ReaderT[Task, MemcachedConnection, AggregateType] = for { record <- ReaderT[Task, MemcachedConnection, RecordType] { con => dao.get(id.value.toString).run(con).flatMap { case Some(v) => Task.pure(v) case None => Task.raiseError(AggregateNotFoundException(id)) } } aggregate <- convertToAggregate(record) } yield aggregate }
Example 76
Source File: AggregateSingleSoftDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memcached import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleSoftDeletable import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task trait AggregateSingleSoftDeleteFeature extends AggregateSingleSoftDeletable[ReaderT[Task, MemcachedConnection, ?]] with AggregateBaseReadFeature { override type RecordType <: MemcachedDaoSupport#SoftDeletableRecord override type DaoType <: MemcachedDaoSupport#Dao[ReaderT[Task, MemcachedConnection, ?], RecordType] with MemcachedDaoSupport#DaoSoftDeletable[ ReaderT[Task, MemcachedConnection, ?], RecordType ] override def softDelete(id: IdType): ReaderT[Task, MemcachedConnection, Long] = ReaderT { con => dao.softDelete(id.value.toString).run(con) } }
Example 77
Source File: AggregateSingleWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memcached import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleWriter import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task trait AggregateSingleWriteFeature extends AggregateSingleWriter[ReaderT[Task, MemcachedConnection, ?]] with AggregateBaseWriteFeature { override def store(aggregate: AggregateType): ReaderT[Task, MemcachedConnection, Long] = { for { record <- convertToRecord(aggregate) result <- dao.set(record, expireDuration) } yield result } }
Example 78
Source File: AggregateMultiReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memcached import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiReader import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task trait AggregateMultiReadFeature extends AggregateMultiReader[ReaderT[Task, MemcachedConnection, ?]] with AggregateBaseReadFeature { override def resolveMulti(ids: Seq[IdType]): ReaderT[Task, MemcachedConnection, Seq[AggregateType]] = ReaderT[Task, MemcachedConnection, Seq[AggregateType]] { con => for { results <- dao.getMulti(ids.map(_.value.toString)).run(con) aggregates <- Task.gather(results.map(v => convertToAggregate(v)(con))) } yield aggregates } }
Example 79
Source File: AggregateMultiWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.memcached import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiWriter import com.github.j5ik2o.reactive.memcached.MemcachedConnection import monix.eval.Task trait AggregateMultiWriteFeature extends AggregateMultiWriter[ReaderT[Task, MemcachedConnection, ?]] with AggregateBaseWriteFeature { override def storeMulti(aggregates: Seq[AggregateType]): ReaderT[Task, MemcachedConnection, Long] = ReaderT[Task, MemcachedConnection, Long] { con => for { records <- Task.traverse(aggregates) { aggregate => convertToRecord(aggregate)(con) } result <- dao.setMulti(records, expireDuration).run(con) } yield result } }
Example 80
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.redis import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task trait AggregateSingleReadFeature extends AggregateSingleReader[ReaderT[Task, RedisConnection, ?]] with AggregateBaseReadFeature { override def resolveById(id: IdType): ReaderT[Task, RedisConnection, AggregateType] = for { record <- ReaderT[Task, RedisConnection, RecordType] { con => dao.get(id.value.toString).run(con).flatMap { case Some(v) => Task.pure(v) case None => Task.raiseError(AggregateNotFoundException(id)) } } aggregate <- convertToAggregate(record) } yield aggregate }
Example 81
Source File: AggregateSingleSoftDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.redis import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleSoftDeletable import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task trait AggregateSingleSoftDeleteFeature extends AggregateSingleSoftDeletable[ReaderT[Task, RedisConnection, ?]] with AggregateBaseReadFeature { override type RecordType <: RedisDaoSupport#SoftDeletableRecord override type DaoType <: RedisDaoSupport#Dao[ReaderT[Task, RedisConnection, ?], RecordType] with RedisDaoSupport#DaoSoftDeletable[ ReaderT[Task, RedisConnection, ?], RecordType ] override def softDelete(id: IdType): ReaderT[Task, RedisConnection, Long] = ReaderT { con => dao.softDelete(id.value.toString).run(con) } }
Example 82
Source File: AggregateSingleWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.redis import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleWriter import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task trait AggregateSingleWriteFeature extends AggregateSingleWriter[ReaderT[Task, RedisConnection, ?]] with AggregateBaseWriteFeature { override def store(aggregate: AggregateType): ReaderT[Task, RedisConnection, Long] = { for { record <- convertToRecord(aggregate) result <- dao.set(record, expireDuration) } yield result } }
Example 83
Source File: AggregateMultiReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.redis import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiReader import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task trait AggregateMultiReadFeature extends AggregateMultiReader[ReaderT[Task, RedisConnection, ?]] with AggregateBaseReadFeature { override def resolveMulti(ids: Seq[IdType]): ReaderT[Task, RedisConnection, Seq[AggregateType]] = ReaderT[Task, RedisConnection, Seq[AggregateType]] { con => for { results <- dao.getMulti(ids.map(_.value.toString)).run(con) aggregates <- Task.gather(results.map(convertToAggregate(_)(con))) } yield aggregates } }
Example 84
Source File: AggregateMultiWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.redis import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiWriter import com.github.j5ik2o.reactive.redis.RedisConnection import monix.eval.Task trait AggregateMultiWriteFeature extends AggregateMultiWriter[ReaderT[Task, RedisConnection, ?]] with AggregateBaseWriteFeature { override def storeMulti(aggregates: Seq[AggregateType]): ReaderT[Task, RedisConnection, Long] = ReaderT[Task, RedisConnection, Long] { con => for { records <- Task.traverse(aggregates) { aggregate => convertToRecord(aggregate)(con) } result <- dao.setMulti(records, expireDuration).run(con) } yield result } }
Example 85
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.dynamodb import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import monix.eval.Task trait AggregateSingleReadFeature extends AggregateSingleReader[Task] with AggregateBaseReadFeature { override def resolveById(id: IdType): Task[AggregateType] = { for { record <- dao.get(toRecordId(id)).flatMap { case Some(v) => Task.pure(v) case None => Task.raiseError(AggregateNotFoundException(id)) } aggregate <- convertToAggregate(record) } yield aggregate } }
Example 86
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.slick import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import monix.eval.Task trait AggregateSingleReadFeature extends AggregateSingleReader[Task] with AggregateBaseReadFeature { override def resolveById(id: IdType): Task[AggregateType] = for { record <- Task .deferFutureAction { implicit ec => import profile.api._ db.run(dao.filter(byCondition(id)).take(1).result) .map(_.headOption) .map(_.getOrElse(throw AggregateNotFoundException(id))) } aggregate <- convertToAggregate(record) } yield aggregate }
Example 87
Source File: AggregateSingleSoftDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.slick import com.github.j5ik2o.dddbase.AggregateSingleSoftDeletable import monix.eval.Task import slick.lifted.{ Rep, TableQuery } trait AggregateSingleSoftDeleteFeature extends AggregateSingleSoftDeletable[Task] with AggregateBaseReadFeature { override type RecordType <: SlickDaoSupport#SoftDeletableRecord override type TableType <: SlickDaoSupport#TableBase[RecordType] with SlickDaoSupport#SoftDeletableTableSupport[ RecordType ] protected final val DELETE = "deleted" override protected val dao: TableQuery[TableType] override def softDelete(id: IdType): Task[Long] = Task.deferFutureAction { implicit ec => import profile.api._ db.run(dao.filter(byCondition(id)).map(_.status).update(DELETE)).map(_.toLong) }.asyncBoundary abstract override protected def byCondition(id: IdType): TableType => Rep[Boolean] = { e => import profile.api._ super.byCondition(id)(e) && e.status =!= DELETE } abstract override protected def byConditions(ids: Seq[IdType]): TableType => Rep[Boolean] = { e => import profile.api._ super.byConditions(ids)(e) && e.status =!= DELETE } }
Example 88
Source File: AggregateChunkReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.slick import com.github.j5ik2o.dddbase.{ AggregateChunkReader, AggregatesChunk } import monix.eval.Task trait AggregateChunkReadFeature extends AggregateChunkReader[Task] with AggregateBaseReadFeature { import profile.api._ override def resolveMultiWithOffsetLimit(offset: Option[Long], limit: Long): Task[AggregatesChunk[AggregateType]] = { val index = offset.map(_.toInt).getOrElse(0) for { results <- Task.deferFuture { db.run(dao.drop(index).take(limit).result) } aggregates <- Task.traverse(results)(convertToAggregate(_)) } yield AggregatesChunk(index, aggregates) } }
Example 89
Source File: AggregateMultiWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.slick import com.github.j5ik2o.dddbase.AggregateMultiWriter import monix.eval.Task trait AggregateMultiWriteFeature extends AggregateMultiWriter[Task] with AggregateBaseWriteFeature { override def storeMulti(aggregates: Seq[AggregateType]): Task[Long] = for { records <- Task.traverse(aggregates) { aggregate => convertToRecord(aggregate) } result <- Task.deferFutureAction { implicit ec => import profile.api._ db.run(DBIO.sequence(records.foldLeft(Seq.empty[DBIO[Long]]) { case (result, record) => result :+ dao.insertOrUpdate(record).map(_.toLong) })) .map(_.sum) } } yield result }
Example 90
Source File: AggregateSingleReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateNotFoundException, AggregateSingleReader } import monix.eval.Task import scalikejdbc.DBSession trait AggregateSingleReadFeature extends AggregateSingleReader[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { override def resolveById(id: IdType): ReaderT[Task, DBSession, AggregateType] = for { record <- ReaderT[Task, DBSession, RecordType] { implicit dbSession: DBSession => Task { dao.findBy(byCondition(id)).getOrElse(throw AggregateNotFoundException(id)) } } aggregate <- convertToAggregate(record) } yield aggregate }
Example 91
Source File: AggregateSingleSoftDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleSoftDeletable import monix.eval.Task import scalikejdbc._ trait AggregateSingleSoftDeleteFeature extends AggregateSingleSoftDeletable[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { protected final val DELETE = "deleted" override def softDelete(id: IdType): ReaderT[Task, DBSession, Long] = ReaderT { implicit dbSession => Task { dao.updateById(toRecordId(id)).withAttributes('status -> DELETE).toLong } } abstract override protected def byCondition(id: IdType): SQLSyntax = super.byCondition(id).and.ne(dao.defaultAlias.status, DELETE) abstract override protected def byConditions(ids: Seq[IdType]): SQLSyntax = super.byConditions(ids).and.ne(dao.defaultAlias.status, DELETE) }
Example 92
Source File: AggregateMultiSoftDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateMultiSoftDeletable, AggregateMultiWriter } import monix.eval.Task import scalikejdbc.DBSession trait AggregateMultiSoftDeleteFeature extends AggregateMultiSoftDeletable[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { this: AggregateMultiWriter[ReaderT[Task, DBSession, ?]] with AggregateSingleSoftDeleteFeature => override def softDeleteMulti(ids: Seq[IdType]): ReaderT[Task, DBSession, Long] = ReaderT { implicit dbDesion => Task { dao.updateBy(byConditions(ids)).withAttributes('status -> DELETE).toLong } } }
Example 93
Source File: AggregateSingleWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateSingleWriter import monix.eval.Task import scalikejdbc.DBSession trait AggregateSingleWriteFeature extends AggregateSingleWriter[ReaderT[Task, DBSession, ?]] with AggregateBaseWriteFeature { override def store(aggregate: AggregateType): ReaderT[Task, DBSession, Long] = { for { record <- convertToRecord(aggregate) result <- ReaderT[Task, DBSession, Long] { implicit dbSession => Task { dao.createOrUpdate(record) } } } yield result } }
Example 94
Source File: AggregateMultiHardDeleteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateMultiHardDeletable, AggregateMultiWriter } import monix.eval.Task import scalikejdbc.DBSession trait AggregateMultiHardDeleteFeature extends AggregateMultiHardDeletable[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { this: AggregateMultiWriter[ReaderT[Task, DBSession, ?]] with AggregateSingleHardDeleteFeature => override def hardDeleteMulti(ids: Seq[IdType]): ReaderT[Task, DBSession, Long] = ReaderT { implicit dbSession => Task { dao.deleteBy(byConditions(ids)).toLong } } }
Example 95
Source File: AggregateChunkReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.{ AggregateChunkReader, AggregatesChunk } import monix.eval.Task import scalikejdbc.DBSession trait AggregateChunkReadFeature extends AggregateChunkReader[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { override def resolveMultiWithOffsetLimit( offset: Option[Long], limit: Long ): ReaderT[Task, DBSession, AggregatesChunk[AggregateType]] = ReaderT[Task, DBSession, AggregatesChunk[AggregateType]] { implicit dbSession: DBSession => val index = offset.map(_.toInt).getOrElse(0) for { results <- Task { dao.findAllWithLimitOffset(limit.toInt, index) } aggregates <- Task.gather(results.map(convertToAggregate(_)(dbSession))) } yield AggregatesChunk(index, aggregates) } }
Example 96
Source File: AggregateMultiReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiReader import monix.eval.Task import scalikejdbc.DBSession trait AggregateMultiReadFeature extends AggregateMultiReader[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { override def resolveMulti(ids: Seq[IdType]): ReaderT[Task, DBSession, Seq[AggregateType]] = ReaderT[Task, DBSession, Seq[AggregateType]] { implicit dbSession: DBSession => for { results <- Task { dao.findAllBy(byConditions(ids)) } aggregates <- Task.gather(results.map(convertToAggregate(_)(dbSession))) } yield aggregates } }
Example 97
Source File: AggregateMultiWriteFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateMultiWriter import monix.eval.Task import scalikejdbc.DBSession trait AggregateMultiWriteFeature extends AggregateMultiWriter[ReaderT[Task, DBSession, ?]] with AggregateBaseWriteFeature { override def storeMulti(aggregates: Seq[AggregateType]): ReaderT[Task, DBSession, Long] = ReaderT[Task, DBSession, Long] { dbSession => for { records <- Task.traverse(aggregates) { aggregate => convertToRecord(aggregate)(dbSession) } result <- Task .traverse(records) { record => Task { dao.createOrUpdate(record) } } .map(_.count(_ > 0)) } yield result } }
Example 98
Source File: AggregateAllReadFeature.scala From scala-ddd-base with MIT License | 5 votes |
package com.github.j5ik2o.dddbase.skinny import cats.data.ReaderT import com.github.j5ik2o.dddbase.AggregateAllReader import monix.eval.Task import scalikejdbc.DBSession trait AggregateAllReadFeature extends AggregateAllReader[ReaderT[Task, DBSession, ?]] with AggregateBaseReadFeature { override def resolveAll: ReaderT[Task, DBSession, Seq[AggregateType]] = ReaderT[Task, DBSession, Seq[AggregateType]] { implicit dbSession: DBSession => for { results <- Task { dao.findAll() } aggregates <- Task.gather(results.map(convertToAggregate(_)(dbSession))) } yield aggregates } }
Example 99
Source File: ConditionalLoggerSpec.scala From odin with Apache License 2.0 | 5 votes |
package io.odin.extras.loggers import cats.data.Kleisli import cats.effect.Sync import cats.effect.concurrent.Ref import cats.mtl.instances.all._ import cats.syntax.applicativeError._ import cats.syntax.flatMap._ import cats.syntax.order._ import io.odin.loggers.{DefaultLogger, HasContext} import io.odin.syntax._ import io.odin.extras.syntax._ import io.odin.{Level, LoggerMessage, OdinSpec} import monix.eval.Task import monix.execution.schedulers.TestScheduler class ConditionalLoggerSpec extends OdinSpec { implicit private val scheduler: TestScheduler = TestScheduler() type F[A] = Kleisli[Task, Map[String, String], A] case class RefLogger(ref: Ref[F, List[LoggerMessage]]) extends DefaultLogger[F] { def log(msg: LoggerMessage): F[Unit] = ref.update(_ :+ msg) } implicit private val hasContext: HasContext[Map[String, String]] = (env: Map[String, String]) => env it should "use log level of the inner logger in case of success" in { forAll { (messages: List[LoggerMessage], ctx: Map[String, String]) => val fa = for { ref <- Ref.of[F, List[LoggerMessage]](List.empty) _ <- RefLogger(ref) .withMinimalLevel(Level.Info) .withContext .withErrorLevel(Level.Debug)(logger => logger.log(messages)) written <- ref.get } yield written val written = fa.run(ctx).runSyncUnsafe() val expected = messages.filter(_.level >= Level.Info).map(m => m.copy(context = m.context ++ ctx)) written shouldBe expected } } it should "use log level of the conditional logger in case of error" in { forAll { (messages: List[LoggerMessage], ctx: Map[String, String]) => val error = new RuntimeException("Boom") val fa = for { ref <- Ref.of[F, List[LoggerMessage]](List.empty) attempt <- RefLogger(ref) .withMinimalLevel(Level.Info) .withContext .withErrorLevel(Level.Debug)(logger => logger.log(messages) >> Sync[F].raiseError[Unit](error)) .attempt written <- ref.get } yield (attempt, written) val (attempt, written) = fa.run(ctx).runSyncUnsafe() val expected = messages.filter(_.level >= Level.Debug).map(m => m.copy(context = m.context ++ ctx)) attempt shouldBe Left(error) written shouldBe expected } } }
Example 100
Source File: AsyncLoggerSpec.scala From odin with Apache License 2.0 | 5 votes |
package io.odin.loggers import cats.effect.Resource import cats.effect.concurrent.Ref import cats.instances.list._ import cats.syntax.all._ import io.odin.{Level, Logger, LoggerMessage, OdinSpec} import monix.catnap.ConcurrentQueue import monix.eval.Task import monix.execution.schedulers.TestScheduler import io.odin.syntax._ import scala.concurrent.duration._ class AsyncLoggerSpec extends OdinSpec { implicit private val scheduler: TestScheduler = TestScheduler() case class RefLogger(ref: Ref[Task, List[LoggerMessage]]) extends DefaultLogger[Task] { def log(msg: LoggerMessage): Task[Unit] = Task.raiseError(new IllegalStateException("Async should always batch")) override def log(msgs: List[LoggerMessage]): Task[Unit] = { ref.update(_ ::: msgs) } } it should "push logs down the chain" in { forAll { msgs: List[LoggerMessage] => (for { ref <- Resource.liftF(Ref.of[Task, List[LoggerMessage]](List.empty)) logger <- RefLogger(ref).withMinimalLevel(Level.Trace).withAsync() _ <- Resource.liftF(msgs.traverse(logger.log)) _ = scheduler.tick(10.millis) reported <- Resource.liftF(ref.get) } yield { reported shouldBe msgs }).use(Task(_)).runSyncUnsafe() } } it should "push logs to the queue" in { forAll { msgs: List[LoggerMessage] => (for { queue <- ConcurrentQueue.unbounded[Task, LoggerMessage]() logger = AsyncLogger(queue, 1.millis, Logger.noop[Task]) _ <- msgs.traverse(logger.log) reported <- queue.drain(0, Int.MaxValue) } yield { reported shouldBe msgs }).runSyncUnsafe() } } it should "ignore errors in underlying logger" in { val errorLogger = new DefaultLogger[Task] { def log(msg: LoggerMessage): Task[Unit] = Task.raiseError(new Error) } forAll { msgs: List[LoggerMessage] => (for { queue <- ConcurrentQueue.unbounded[Task, LoggerMessage]() logger = AsyncLogger(queue, 1.millis, errorLogger) _ <- logger.log(msgs) result <- logger.drain } yield { result shouldBe (()) }).runSyncUnsafe() } } }
Example 101
Source File: FileLoggerSpec.scala From odin with Apache License 2.0 | 5 votes |
package io.odin.loggers import java.nio.file.{Files, Path, Paths} import java.util.UUID import cats.effect.Resource import io.odin._ import io.odin.formatter.Formatter import io.odin.{LoggerMessage, OdinSpec} import scala.concurrent.duration._ import monix.eval.Task import monix.execution.schedulers.TestScheduler class FileLoggerSpec extends OdinSpec { implicit private val scheduler: TestScheduler = TestScheduler() private val fileResource = Resource.make[Task, Path] { Task.delay(Files.createTempFile(UUID.randomUUID().toString, "")) } { file => Task.delay(Files.delete(file)) } it should "write formatted message into file" in { forAll { (loggerMessage: LoggerMessage, formatter: Formatter) => (for { path <- fileResource fileName = path.toString logger <- FileLogger[Task](fileName, formatter, Level.Trace) _ <- Resource.liftF(logger.log(loggerMessage)) } yield { new String(Files.readAllBytes(Paths.get(fileName))) shouldBe formatter.format(loggerMessage) + lineSeparator }).use(Task(_)) .runSyncUnsafe() } } it should "write formatted messages into file" in { forAll { (loggerMessage: List[LoggerMessage], formatter: Formatter) => (for { path <- fileResource fileName = path.toString logger <- FileLogger[Task](fileName, formatter, Level.Trace) _ <- Resource.liftF(logger.log(loggerMessage)) } yield { new String(Files.readAllBytes(Paths.get(fileName))) shouldBe loggerMessage .map(formatter.format) .mkString(lineSeparator) + (if (loggerMessage.isEmpty) "" else lineSeparator) }).use(Task(_)) .runSyncUnsafe() } } it should "write in async mode" in { forAll { (loggerMessage: List[LoggerMessage], formatter: Formatter) => (for { path <- fileResource fileName = path.toString logger <- asyncFileLogger[Task](fileName, formatter) _ <- Resource.liftF(logger.withMinimalLevel(Level.Trace).log(loggerMessage)) _ <- Resource.liftF(Task(scheduler.tick(2.seconds))) } yield { new String(Files.readAllBytes(Paths.get(fileName))) shouldBe loggerMessage .map(formatter.format) .mkString(lineSeparator) + (if (loggerMessage.isEmpty) "" else lineSeparator) }).use(Task(_)) .runSyncUnsafe() } } }
Example 102
Source File: S3MonixClientSupport.scala From reactive-aws-clients with MIT License | 5 votes |
package com.github.j5ik2o.reactive.aws.s3.monix import java.io.File import java.nio.file.Path import monix.eval.Task import software.amazon.awssdk.core.ResponseBytes import software.amazon.awssdk.core.async.{ AsyncRequestBody, AsyncResponseTransformer } import software.amazon.awssdk.services.s3.model._ trait S3MonixClientSupport { this: S3MonixClient => override type RT[A, B] = AsyncResponseTransformer[A, B] override type RB = AsyncRequestBody override def listBuckets(): Task[ListBucketsResponse] = Task.deferFuture { underlying.listBuckets() } override def getObjectAsBytes(getObjectRequest: GetObjectRequest): Task[ResponseBytes[GetObjectResponse]] = Task.deferFuture { underlying.getObjectAsBytes(getObjectRequest) } override def getObjectToFile(getObjectRequest: GetObjectRequest, file: File): Task[GetObjectResponse] = Task.deferFuture { underlying.getObjectToFile(getObjectRequest, file) } override def getObjectToPath(getObjectRequest: GetObjectRequest, destinationPath: Path): Task[GetObjectResponse] = Task.deferFuture { underlying.getObjectToPath(getObjectRequest, destinationPath) } override def getObject[A]( getObjectRequest: GetObjectRequest, responseTransformer: AsyncResponseTransformer[GetObjectResponse, A] ): Task[A] = Task.deferFuture { underlying.getObject(getObjectRequest, responseTransformer) } override def getObjectTorrentAsBytes( getObjectRequest: GetObjectTorrentRequest ): Task[ResponseBytes[GetObjectTorrentResponse]] = Task.deferFuture { underlying.getObjectTorrentAsBytes(getObjectRequest) } override def getObjectTorrentToFile( getObjectRequest: GetObjectTorrentRequest, file: File ): Task[GetObjectTorrentResponse] = Task.deferFuture { underlying.getObjectTorrentToFile(getObjectRequest, file) } override def getObjectTorrentToPath( getObjectTorrentRequest: GetObjectTorrentRequest, destinationPath: Path ): Task[GetObjectTorrentResponse] = Task.deferFuture { underlying.getObjectTorrentToPath(getObjectTorrentRequest, destinationPath) } override def getObjectTorrent[A]( getObjectTorrentRequest: GetObjectTorrentRequest, responseTransformer: AsyncResponseTransformer[GetObjectTorrentResponse, A] ): Task[A] = Task.deferFuture { underlying.getObjectTorrent(getObjectTorrentRequest, responseTransformer) } override def putObject(putObjectRequest: PutObjectRequest, requestBody: AsyncRequestBody): Task[PutObjectResponse] = Task.deferFuture { underlying.putObject(putObjectRequest, requestBody) } override def putObjectFromPath(putObjectRequest: PutObjectRequest, sourcePath: Path): Task[PutObjectResponse] = Task.deferFuture { underlying.putObjectFromPath(putObjectRequest, sourcePath) } override def putObjectFromFile(putObjectRequest: PutObjectRequest, sourceFile: File): Task[PutObjectResponse] = Task.deferFuture { underlying.putObjectFromFile(putObjectRequest, sourceFile) } override def uploadPart( uploadPartRequest: UploadPartRequest, requestBody: AsyncRequestBody ): Task[UploadPartResponse] = Task.deferFuture { underlying.uploadPart(uploadPartRequest, requestBody) } override def uploadPartFromPath(uploadPartRequest: UploadPartRequest, sourcePath: Path): Task[UploadPartResponse] = Task.deferFuture { underlying.uploadPartFromPath(uploadPartRequest, sourcePath) } override def uploadPartFromFile(uploadPartRequest: UploadPartRequest, sourceFile: File): Task[UploadPartResponse] = Task.deferFuture { underlying.uploadPartFromFile(uploadPartRequest, sourceFile) } }
Example 103
Source File: DynamoDbStreamsMonixClient.scala From reactive-aws-clients with MIT License | 5 votes |
// Auto-Generated package com.github.j5ik2o.reactive.aws.dynamodb.streams.monix import com.github.j5ik2o.reactive.aws.dynamodb.streams.{ DynamoDbStreamsAsyncClient, DynamoDbStreamsClient } import monix.eval.Task import monix.reactive.Observable import software.amazon.awssdk.services.dynamodb.model._ object DynamoDbStreamsMonixClient { def apply(underlying: DynamoDbStreamsAsyncClient): DynamoDbStreamsMonixClient = new DynamoDbStreamsMonixClientImpl(underlying) } trait DynamoDbStreamsMonixClient extends DynamoDbStreamsClient[Task] { val underlying: DynamoDbStreamsAsyncClient override def describeStream(describeStreamRequest: DescribeStreamRequest): Task[DescribeStreamResponse] = Task.deferFuture { underlying.describeStream(describeStreamRequest) } def describeStreamPaginator(describeStreamRequest: DescribeStreamRequest): Observable[DescribeStreamResponse] = Observable.fromReactivePublisher(underlying.describeStreamPaginator(describeStreamRequest)) override def getRecords(getRecordsRequest: GetRecordsRequest): Task[GetRecordsResponse] = Task.deferFuture { underlying.getRecords(getRecordsRequest) } override def getShardIterator(getShardIteratorRequest: GetShardIteratorRequest): Task[GetShardIteratorResponse] = Task.deferFuture { underlying.getShardIterator(getShardIteratorRequest) } override def listStreams(listStreamsRequest: ListStreamsRequest): Task[ListStreamsResponse] = Task.deferFuture { underlying.listStreams(listStreamsRequest) } override def listStreams(): Task[ListStreamsResponse] = Task.deferFuture { underlying.listStreams() } def listStreamsPaginator(): Observable[ListStreamsResponse] = Observable.fromReactivePublisher(underlying.listStreamsPaginator()) def listStreamsPaginator(listStreamsRequest: ListStreamsRequest): Observable[ListStreamsResponse] = Observable.fromReactivePublisher(underlying.listStreamsPaginator(listStreamsRequest)) }
Example 104
Source File: Runner.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.context.monix import io.getquill.context.ContextEffect import monix.eval.Task import monix.execution.Scheduler import monix.reactive.Observable object Runner { def default = new Runner {} def using(scheduler: Scheduler) = new Runner { override def schedule[T](t: Task[T]): Task[T] = t.executeOn(scheduler, true) override def boundary[T](t: Task[T]): Task[T] = t.executeOn(scheduler, true) override def scheduleObservable[T](o: Observable[T]): Observable[T] = o.executeOn(scheduler, true) } } trait Runner extends ContextEffect[Task] { override def wrap[T](t: => T): Task[T] = Task(t) override def push[A, B](result: Task[A])(f: A => B): Task[B] = result.map(f) override def seq[A, B](list: List[Task[A]]): Task[List[A]] = Task.sequence(list) def schedule[T](t: Task[T]): Task[T] = t def scheduleObservable[T](o: Observable[T]): Observable[T] = o def boundary[T](t: Task[T]): Task[T] = t.asyncBoundary def wrapClose(t: => Unit): Task[Unit] = Task(t) }
Example 105
Source File: MonixContext.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.context.monix import io.getquill.NamingStrategy import io.getquill.context.{ Context, StreamingContext } import monix.eval.Task import monix.reactive.Observable trait MonixContext[Idiom <: io.getquill.idiom.Idiom, Naming <: NamingStrategy] extends Context[Idiom, Naming] with StreamingContext[Idiom, Naming] { override type StreamResult[T] = Observable[T] override type Result[T] = Task[T] override type RunQueryResult[T] = List[T] override type RunQuerySingleResult[T] = T // Need explicit return-type annotations due to scala/bug#8356. Otherwise macro system will not understand Result[Long]=Task[Long] etc... def executeQuery[T](sql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Task[List[T]] def executeQuerySingle[T](sql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Task[T] protected val effect: Runner }
Example 106
Source File: RunnerSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.context.monix import io.getquill.Spec import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import org.scalatest.matchers.should.Matchers._ import scala.util.Failure class RunnerSpec extends Spec { class SideEffect { private var state = 0 def apply() = state = 1 def applied = state == 1 } implicit val scheduler = Scheduler.global "plain runner" - { val runner = Runner.default import runner._ "should lazily evaluate" in { val sideEffect = new SideEffect val task = wrap(sideEffect()) sideEffect.applied should equal(false) task.runSyncUnsafe() sideEffect.applied should equal(true) } "should encapsulate exception throw" in { wrap(throw new RuntimeException("Surprise!")).materialize.runSyncUnsafe() should matchPattern { case Failure(e) if (e.getMessage == "Surprise!") => } } "should push an effect correctly" in { push(Task(1))(_ + 1).runSyncUnsafe() should equal(2) } "should convert a sequence correctly" in { seq(List(Task(1), Task(2), Task(3))).runSyncUnsafe() should equal(List(1, 2, 3)) } "plain schedule should be a no-op" in { val t = Task(1) (schedule(t) eq (t)) must equal(true) } "boundary operator must force async boundary" in { val (first, second) = boundary(Task(Thread.currentThread().getName)) .flatMap(prevName => Task((prevName, Thread.currentThread().getName))) .runSyncUnsafe() first must not equal (second) } } "using scheduler runner" - { val prefix = "quill-test-pool" val customScheduler = Scheduler.io(prefix) val runner = Runner.using(customScheduler) import runner._ "should run in specified scheduler" in { // the global scheduler is imported but want to explicitly tell this to run on it, just for clarity val threadName = schedule(Task(Thread.currentThread().getName)).runSyncUnsafe()(Scheduler.global, CanBlock.permit) threadName.startsWith(prefix) must equal(true) } "should async-boundary in specified scheduler" in { // the global scheduler is imported but want to explicitly tell this to run on it, just for clarity val threadName = boundary(Task(Thread.currentThread().getName)).runSyncUnsafe()(Scheduler.global, CanBlock.permit) threadName.startsWith(prefix) must equal(true) } "should async-boundary correctly" in { val prefix2 = "quill-test-pool2" // the global scheduler is imported but want to explicitly tell this to run on it, just for clarity val (first, second) = Task(Thread.currentThread().getName) .executeOn(Scheduler.io(prefix2)) .flatMap(prevName => boundary(Task((prevName, Thread.currentThread().getName)))) .runSyncUnsafe()(Scheduler.global, CanBlock.permit) first.startsWith(prefix2) must equal(true) second.startsWith(prefix) must equal(true) first must not equal second } } }
Example 107
Source File: CassandraStreamContext.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill import com.datastax.driver.core.{ Cluster, ResultSet, Row } import com.typesafe.config.Config import io.getquill.context.cassandra.util.FutureConversions._ import io.getquill.util.{ ContextLogger, LoadConfig } import monix.eval.Task import monix.execution.Scheduler import monix.execution.Scheduler.Implicits import monix.reactive.Observable import scala.jdk.CollectionConverters._ import scala.util.{ Failure, Success } class CassandraStreamContext[N <: NamingStrategy]( naming: N, cluster: Cluster, keyspace: String, preparedStatementCacheSize: Long ) extends CassandraClusterSessionContext[N](naming, cluster, keyspace, preparedStatementCacheSize) { def this(naming: N, config: CassandraContextConfig) = this(naming, config.cluster, config.keyspace, config.preparedStatementCacheSize) def this(naming: N, config: Config) = this(naming, CassandraContextConfig(config)) def this(naming: N, configPrefix: String) = this(naming, LoadConfig(configPrefix)) private val logger = ContextLogger(classOf[CassandraStreamContext[_]]) override type Result[T] = Observable[T] override type RunQueryResult[T] = T override type RunQuerySingleResult[T] = T override type RunActionResult = Unit override type RunBatchActionResult = Unit protected def page(rs: ResultSet): Task[Iterable[Row]] = Task.defer { val available = rs.getAvailableWithoutFetching val page = rs.asScala.take(available) if (rs.isFullyFetched) Task.now(page) else Task.fromFuture(rs.fetchMoreResults().asScala(Implicits.global)).map(_ => page) } def executeQuery[T](cql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Observable[T] = { Observable .fromTask(prepareRowAndLog(cql, prepare)) .mapEvalF(p => session.executeAsync(p).asScala(Implicits.global)) .flatMap(Observable.fromAsyncStateAction((rs: ResultSet) => page(rs).map((_, rs)))(_)) .takeWhile(_.nonEmpty) .flatMap(Observable.fromIterable) .map(extractor) } def executeQuerySingle[T](cql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Observable[T] = executeQuery(cql, prepare, extractor) def executeAction[T](cql: String, prepare: Prepare = identityPrepare): Observable[Unit] = { Observable .fromTask(prepareRowAndLog(cql, prepare)) .mapEvalF(p => session.executeAsync(p).asScala(Implicits.global)) .map(_ => ()) } def executeBatchAction(groups: List[BatchGroup]): Observable[Unit] = Observable.fromIterable(groups).flatMap { case BatchGroup(cql, prepare) => Observable.fromIterable(prepare) .flatMap(executeAction(cql, _)) .map(_ => ()) } private def prepareRowAndLog(cql: String, prepare: Prepare = identityPrepare): Task[PrepareRow] = { Task.async0[PrepareRow] { (scheduler, callback) => implicit val executor: Scheduler = scheduler super.prepareAsync(cql) .map(prepare) .onComplete { case Success((params, bs)) => logger.logQuery(cql, params) callback.onSuccess(bs) case Failure(ex) => callback.onError(ex) } } } }
Example 108
Source File: CassandraMonixContext.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill import com.datastax.driver.core.{ Cluster, ResultSet, Row } import com.typesafe.config.Config import io.getquill.context.cassandra.CqlIdiom import io.getquill.context.monix.{ MonixContext, Runner } import io.getquill.util.{ ContextLogger, LoadConfig } import io.getquill.context.cassandra.util.FutureConversions._ import monix.eval.Task import monix.execution.Scheduler import monix.reactive.Observable import scala.jdk.CollectionConverters._ import scala.util.{ Failure, Success } class CassandraMonixContext[N <: NamingStrategy]( naming: N, cluster: Cluster, keyspace: String, preparedStatementCacheSize: Long ) extends CassandraClusterSessionContext[N](naming, cluster, keyspace, preparedStatementCacheSize) with MonixContext[CqlIdiom, N] { // not using this here override val effect = Runner.default def this(naming: N, config: CassandraContextConfig) = this(naming, config.cluster, config.keyspace, config.preparedStatementCacheSize) def this(naming: N, config: Config) = this(naming, CassandraContextConfig(config)) def this(naming: N, configPrefix: String) = this(naming, LoadConfig(configPrefix)) private val logger = ContextLogger(classOf[CassandraMonixContext[_]]) override type StreamResult[T] = Observable[T] override type RunActionResult = Unit override type Result[T] = Task[T] override type RunQueryResult[T] = List[T] override type RunQuerySingleResult[T] = T override type RunBatchActionResult = Unit protected def page(rs: ResultSet): Task[Iterable[Row]] = Task.defer { val available = rs.getAvailableWithoutFetching val page = rs.asScala.take(available) if (rs.isFullyFetched) Task.now(page) else Task.fromFuture(rs.fetchMoreResults().asScalaWithDefaultGlobal).map(_ => page) } def streamQuery[T](fetchSize: Option[Int], cql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Observable[T] = { Observable .fromTask(prepareRowAndLog(cql, prepare)) .mapEvalF(p => session.executeAsync(p).asScalaWithDefaultGlobal) .flatMap(Observable.fromAsyncStateAction((rs: ResultSet) => page(rs).map((_, rs)))(_)) .takeWhile(_.nonEmpty) .flatMap(Observable.fromIterable) .map(extractor) } def executeQuery[T](cql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Task[List[T]] = { streamQuery[T](None, cql, prepare, extractor) .foldLeftL(List[T]())({ case (l, r) => r +: l }).map(_.reverse) } def executeQuerySingle[T](cql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor): Task[T] = executeQuery(cql, prepare, extractor).map(handleSingleResult(_)) def executeAction[T](cql: String, prepare: Prepare = identityPrepare): Task[Unit] = { prepareRowAndLog(cql, prepare) .flatMap(r => Task.fromFuture(session.executeAsync(r).asScalaWithDefaultGlobal)) .map(_ => ()) } def executeBatchAction(groups: List[BatchGroup]): Task[Unit] = Observable.fromIterable(groups).flatMap { case BatchGroup(cql, prepare) => Observable.fromIterable(prepare) .flatMap(prep => Observable.fromTask(executeAction(cql, prep))) .map(_ => ()) }.completedL private def prepareRowAndLog(cql: String, prepare: Prepare = identityPrepare): Task[PrepareRow] = { Task.async0[PrepareRow] { (scheduler, callback) => implicit val executor: Scheduler = scheduler super.prepareAsync(cql) .map(prepare) .onComplete { case Success((params, bs)) => logger.logQuery(cql, params) callback.onSuccess(bs) case Failure(ex) => callback.onError(ex) } } } }
Example 109
Source File: QueryResultTypeCassandraMonixSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.context.cassandra.monix import io.getquill.context.cassandra.QueryResultTypeCassandraSpec import monix.eval.Task import monix.execution.Scheduler.Implicits.global import monix.reactive.Observable class QueryResultTypeCassandraMonixSpec extends QueryResultTypeCassandraSpec { val context = testMonixDB import context._ def result[T](t: Task[T]) = await(t.runToFuture(global)) def result[T](t: Observable[T]) = await(t.foldLeftL(List.empty[T])(_ :+ _).runToFuture) override def beforeAll = { result(context.run(deleteAll)) result(context.run(liftQuery(entries).foreach(e => insert(e)))) () } "query" in { result(context.run(selectAll)) mustEqual entries } "stream" in { result(context.stream(selectAll)) mustEqual entries } "querySingle" - { "size" in { result(context.run(entitySize)) mustEqual 3 } "parametrized size" in { result(context.run(parametrizedSize(lift(10000)))) mustEqual 0 } } }
Example 110
Source File: PrepareMonixJdbcSpecBase.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill import java.sql.{ Connection, PreparedStatement, ResultSet } import io.getquill.context.jdbc.ResultSetExtractor import io.getquill.context.sql.ProductSpec import monix.eval.Task import org.scalactic.Equality trait PrepareMonixJdbcSpecBase extends ProductSpec { implicit val productEq = new Equality[Product] { override def areEqual(a: Product, b: Any): Boolean = b match { case Product(_, desc, sku) => desc == a.description && sku == a.sku case _ => false } } def productExtractor: ResultSet => Product def withOrderedIds(products: List[Product]) = products.zipWithIndex.map { case (product, id) => product.copy(id = id.toLong + 1) } def singleInsert(conn: => Connection)(prep: Connection => Task[PreparedStatement]) = { Task(conn).bracket { conn => prep(conn).bracket { stmt => Task(stmt.execute()) }(stmt => Task(stmt.close())) }(conn => Task(conn.close())) } def batchInsert(conn: => Connection)(prep: Connection => Task[List[PreparedStatement]]) = { Task(conn).bracket { conn => prep(conn).flatMap(stmts => Task.sequence( stmts.map(stmt => Task(stmt).bracket { stmt => Task(stmt.execute()) }(stmt => Task(stmt.close()))) )) }(conn => Task(conn.close())) } def extractResults[T](conn: => Connection)(prep: Connection => Task[PreparedStatement])(extractor: ResultSet => T) = { Task(conn).bracket { conn => prep(conn).bracket { stmt => Task(stmt.executeQuery()).bracket { rs => Task(ResultSetExtractor(rs, extractor)) }(rs => Task(rs.close())) }(stmt => Task(stmt.close())) }(conn => Task(conn.close())) } def extractProducts(conn: => Connection)(prep: Connection => Task[PreparedStatement]) = extractResults(conn)(prep)(productExtractor) }
Example 111
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.oracle import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 112
Source File: ProductJdbcSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.oracle import io.getquill.context.sql.ProductSpec import monix.eval.Task import monix.execution.Scheduler class ProductJdbcSpec extends ProductSpec { val context = testContext import testContext._ implicit val scheduler = Scheduler.global override def beforeAll = { testContext.run(quote(query[Product].delete)).runSyncUnsafe() () } "Product" - { "Insert multiple products" in { val (inserted, product) = (for { i <- Task.sequence(productEntries.map(product => testContext.run(productInsert(lift(product))))) ps <- testContext.run(productById(lift(i(2)))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual productEntries(2).description product.id mustEqual inserted(2) } "Single insert product" in { val (inserted, product) = (for { i <- testContext.run(productSingleInsert) ps <- testContext.run(productById(lift(i))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual "Window" product.id mustEqual inserted } "Single insert with inlined free variable" in { val prd = Product(0L, "test1", 1L) val (inserted, returnedProduct) = (for { i <- testContext.run { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returning(_.id) } rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test1" returnedProduct.sku mustEqual 1L returnedProduct.id mustEqual inserted } "Single insert with free variable and explicit quotation" in { val prd = Product(0L, "test2", 2L) val q1 = quote { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returning(_.id) } val (inserted, returnedProduct) = (for { i <- testContext.run(q1) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test2" returnedProduct.sku mustEqual 2L returnedProduct.id mustEqual inserted } "Single product insert with a method quotation" in { val prd = Product(0L, "test3", 3L) val (inserted, returnedProduct) = (for { i <- testContext.run(productInsert(lift(prd))) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test3" returnedProduct.sku mustEqual 3L returnedProduct.id mustEqual inserted } } }
Example 113
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.postgres import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 114
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.sqlserver import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 115
Source File: ProductJdbcSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.sqlserver import io.getquill.context.sql.ProductSpec import monix.eval.Task import monix.execution.Scheduler class ProductJdbcSpec extends ProductSpec { val context = testContext import testContext._ implicit val scheduler = Scheduler.global override def beforeAll = { testContext.run(quote(query[Product].delete)).runSyncUnsafe() () } "Product" - { "Insert multiple products" in { val (inserted, product) = (for { i <- Task.sequence(productEntries.map(product => testContext.run(productInsert(lift(product))))) ps <- testContext.run(productById(lift(i(2)))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual productEntries(2).description product.id mustEqual inserted(2) } "Single insert product" in { val (inserted, product) = (for { i <- testContext.run(productSingleInsert) ps <- testContext.run(productById(lift(i))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual "Window" product.id mustEqual inserted } "Single insert with inlined free variable" in { val prd = Product(0L, "test1", 1L) val (inserted, returnedProduct) = (for { i <- testContext.run { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) } rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test1" returnedProduct.sku mustEqual 1L returnedProduct.id mustEqual inserted } "Single insert with free variable and explicit quotation" in { val prd = Product(0L, "test2", 2L) val q1 = quote { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) } val (inserted, returnedProduct) = (for { i <- testContext.run(q1) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test2" returnedProduct.sku mustEqual 2L returnedProduct.id mustEqual inserted } "Single product insert with a method quotation" in { val prd = Product(0L, "test3", 3L) val (inserted, returnedProduct) = (for { i <- testContext.run(productInsert(lift(prd))) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test3" returnedProduct.sku mustEqual 3L returnedProduct.id mustEqual inserted } } }
Example 116
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.mysql import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 117
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.sqlite import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 118
Source File: ProductJdbcSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.sqlite import io.getquill.context.sql.ProductSpec import monix.eval.Task import monix.execution.Scheduler class ProductJdbcSpec extends ProductSpec { val context = testContext import testContext._ implicit val scheduler = Scheduler.global override def beforeAll = { testContext.run(quote(query[Product].delete)).runSyncUnsafe() () } "Product" - { "Insert multiple products" in { val (inserted, product) = (for { i <- Task.sequence(productEntries.map(product => testContext.run(productInsert(lift(product))))) ps <- testContext.run(productById(lift(i(2)))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual productEntries(2).description product.id mustEqual inserted(2) } "Single insert product" in { val (inserted, product) = (for { i <- testContext.run(productSingleInsert) ps <- testContext.run(productById(lift(i))) } yield (i, ps.head)).runSyncUnsafe() product.description mustEqual "Window" product.id mustEqual inserted } "Single insert with inlined free variable" in { val prd = Product(0L, "test1", 1L) val (inserted, returnedProduct) = (for { i <- testContext.run { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) } rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test1" returnedProduct.sku mustEqual 1L returnedProduct.id mustEqual inserted } "Single insert with free variable and explicit quotation" in { val prd = Product(0L, "test2", 2L) val q1 = quote { product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) } val (inserted, returnedProduct) = (for { i <- testContext.run(q1) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test2" returnedProduct.sku mustEqual 2L returnedProduct.id mustEqual inserted } "Single product insert with a method quotation" in { val prd = Product(0L, "test3", 3L) val (inserted, returnedProduct) = (for { i <- testContext.run(productInsert(lift(prd))) rps <- testContext.run(productById(lift(i))) } yield (i, rps.head)).runSyncUnsafe() returnedProduct.description mustEqual "test3" returnedProduct.sku mustEqual 3L returnedProduct.id mustEqual inserted } } }
Example 119
Source File: MonixJdbcContextSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill.h2 import io.getquill.MonixSpec import monix.eval.Task class MonixJdbcContextSpec extends MonixSpec { val context = testContext import testContext._ "provides transaction support" - { "success" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "success - stream" in { (for { _ <- testContext.run(qr1.delete) seq <- testContext.transaction { for { _ <- testContext.run(qr1.insert(_.i -> 33)) s <- accumulate(testContext.stream(qr1)) } yield s } r <- testContext.run(qr1) } yield (seq.map(_.i), r.map(_.i))).runSyncUnsafe() mustEqual ((List(33), List(33))) } "failure" in { (for { _ <- testContext.run(qr1.delete) e <- testContext.transaction { Task.sequence(Seq( testContext.run(qr1.insert(_.i -> 18)), Task.eval { throw new IllegalStateException } )) }.onErrorHandleWith { case e: Exception => Task(e.getClass.getSimpleName) } r <- testContext.run(qr1) } yield (e, r.isEmpty)).runSyncUnsafe() mustEqual (("IllegalStateException", true)) } "nested" in { (for { _ <- testContext.run(qr1.delete) _ <- testContext.transaction { testContext.transaction { testContext.run(qr1.insert(_.i -> 33)) } } r <- testContext.run(qr1) } yield r).runSyncUnsafe().map(_.i) mustEqual List(33) } "prepare" in { testContext.prepareParams( "select * from Person where name=? and age > ?", ps => (List("Sarah", 127), ps) ).runSyncUnsafe() mustEqual List("127", "'Sarah'") } } }
Example 120
Source File: ResultSetIteratorSpec.scala From quill with Apache License 2.0 | 5 votes |
package io.getquill import io.getquill.context.monix.Runner import io.getquill.util.LoadConfig import monix.eval.Task import monix.execution.Scheduler import org.scalatest.BeforeAndAfterAll import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.must.Matchers import org.scalatest.matchers.should.Matchers._ import scala.collection.mutable.ArrayBuffer class ResultSetIteratorSpec extends AnyFreeSpec with Matchers with BeforeAndAfterAll { val ds = JdbcContextConfig(LoadConfig("testPostgresDB")).dataSource implicit val scheduler = Scheduler.global val ctx = new PostgresMonixJdbcContext(Literal, ds, Runner.default) import ctx._ case class Person(name: String, age: Int) val peopleInsert = quote((p: Person) => query[Person].insert(p)) val peopleEntries = List( Person("Alex", 60), Person("Bert", 55), Person("Cora", 33) ) override def beforeAll = { ctx.transaction { for { _ <- ctx.run(query[Person].delete) _ <- ctx.run(liftQuery(peopleEntries).foreach(p => peopleInsert(p))) } yield () }.runSyncUnsafe() } "traverses correctly" in { val results = Task(ds.getConnection).bracket { conn => Task { val stmt = conn.prepareStatement("select * from person") val rs = new ResultSetIterator[String](stmt.executeQuery(), extractor = (rs) => { rs.getString(1) }) val accum = ArrayBuffer[String]() while (rs.hasNext) accum += rs.next() accum } } { conn => Task(conn.close()) }.runSyncUnsafe() results should contain theSameElementsAs (peopleEntries.map(_.name)) } "can take head element" in { val result = Task(ds.getConnection).bracket { conn => Task { val stmt = conn.prepareStatement("select * from person where name = 'Alex'") val rs = new ResultSetIterator(stmt.executeQuery(), extractor = (rs) => { rs.getString(1) }) rs.head } } { conn => Task(conn.close()) }.runSyncUnsafe() result must equal("Alex") } }
Example 121
Source File: PermissionsRoutes.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.javadsl.server.Rejections._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator import ch.epfl.bluebrain.nexus.iam.marshallers.instances._ import ch.epfl.bluebrain.nexus.iam.permissions.Permissions import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract} import ch.epfl.bluebrain.nexus.iam.types.ResourceF._ import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import io.circe.{Decoder, DecodingFailure} import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class PermissionsRoutes(permissions: Permissions[Task], realms: Realms[Task])(implicit http: HttpConfig) { def routes: Route = (pathPrefix("permissions") & pathEndOrSingleSlash) { operationName(s"/${http.prefix}/permissions") { authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller => concat( get { parameter("rev".as[Long].?) { case Some(rev) => complete(permissions.fetchAt(rev).runNotFound) case None => complete(permissions.fetch.runToFuture) } }, (put & parameter("rev" ? 0L)) { rev => entity(as[PatchPermissions]) { case Replace(set) => complete(permissions.replace(set, rev).runToFuture) case _ => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'.")) } }, delete { parameter("rev".as[Long]) { rev => complete(permissions.delete(rev).runToFuture) } }, (patch & parameter("rev" ? 0L)) { rev => entity(as[PatchPermissions]) { case Append(set) => complete(permissions.append(set, rev).runToFuture) case Subtract(set) => complete(permissions.subtract(set, rev).runToFuture) case _ => reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'.")) } } ) } } } } object PermissionsRoutes { private[routes] sealed trait PatchPermissions extends Product with Serializable private[routes] object PatchPermissions { final case class Append(permissions: Set[Permission]) extends PatchPermissions final case class Subtract(permissions: Set[Permission]) extends PatchPermissions final case class Replace(permissions: Set[Permission]) extends PatchPermissions implicit val patchPermissionsDecoder: Decoder[PatchPermissions] = Decoder.instance { hc => for { permissions <- hc.get[Set[Permission]]("permissions") tpe = hc.get[String]("@type").getOrElse("Replace") patch <- tpe match { case "Replace" => Right(Replace(permissions)) case "Append" => Right(Append(permissions)) case "Subtract" => Right(Subtract(permissions)) case _ => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history)) } } yield patch } } }
Example 122
Source File: IdentitiesRoutes.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator import ch.epfl.bluebrain.nexus.iam.marshallers.instances._ import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Caller import ch.epfl.bluebrain.nexus.iam.types.Caller.JsonLd._ import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class IdentitiesRoutes(realms: Realms[Task])(implicit http: HttpConfig) { def routes: Route = { (pathPrefix("identities") & pathEndOrSingleSlash) { operationName(s"/${http.prefix}/identities") { authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller => get { complete(caller) } } } } } }
Example 123
Source File: AuthDirectives.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.directives import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.directives.Credentials import akka.http.scaladsl.server.{Directive0, Directive1} import cats.implicits._ import ch.epfl.bluebrain.nexus.rdf.implicits._ import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.auth.AccessToken import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.IamError.AccessDenied import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission} import ch.epfl.bluebrain.nexus.rdf.Iri.{AbsoluteIri, Path} import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.Future object AuthDirectives { def authorizeFor(permission: Permission)( implicit acls: Acls[Task], s: Scheduler, c: Caller, hc: HttpConfig ): Directive0 = extractResourceAddress.flatMap { address => onSuccess { acls .hasPermission(Path./, permission, ancestors = false) .ifM(Task.unit, Task.raiseError(AccessDenied(address, permission))) .runToFuture } } }
Example 124
Source File: instances.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.marshallers import akka.http.scaladsl.marshalling.GenericMarshallers.eitherMarshaller import akka.http.scaladsl.marshalling._ import akka.http.scaladsl.model.MediaTypes.`application/json` import akka.http.scaladsl.model._ import ch.epfl.bluebrain.nexus.commons.circe.syntax._ import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport.OrderedKeys import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes._ import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom import ch.epfl.bluebrain.nexus.iam.acls.AclRejection import ch.epfl.bluebrain.nexus.iam.config.AppConfig._ import ch.epfl.bluebrain.nexus.iam.permissions.PermissionsRejection import ch.epfl.bluebrain.nexus.iam.realms.RealmRejection import ch.epfl.bluebrain.nexus.iam.types.IamError.InternalError import ch.epfl.bluebrain.nexus.iam.types.{IamError, ResourceRejection} import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport import io.circe._ import io.circe.syntax._ import monix.eval.Task import monix.execution.Scheduler import scala.collection.immutable.Seq import scala.concurrent.Future import scala.concurrent.duration.FiniteDuration object instances extends FailFastCirceSupport { implicit val finiteDurationEncoder: Encoder[FiniteDuration] = Encoder.encodeString.contramap(fd => s"${fd.toMillis} ms") implicit val resourceRejectionEncoder: Encoder[ResourceRejection] = Encoder.instance { case r: AclRejection => Encoder[AclRejection].apply(r) case r: RealmRejection => Encoder[RealmRejection].apply(r) case r: PermissionsRejection => Encoder[PermissionsRejection].apply(r) case _ => Encoder[IamError].apply(InternalError("unspecified")) } implicit val resourceRejectionStatusFrom: StatusFrom[ResourceRejection] = StatusFrom { case r: AclRejection => AclRejection.aclRejectionStatusFrom(r) case r: RealmRejection => RealmRejection.realmRejectionStatusFrom(r) case r: PermissionsRejection => PermissionsRejection.permissionsRejectionStatusFrom(r) } override def unmarshallerContentTypes: Seq[ContentTypeRange] = List(`application/json`, `application/ld+json`, `application/sparql-results+json`) implicit final def rejection[A <: ResourceRejection: Encoder]( implicit statusFrom: StatusFrom[A], printer: Printer = Printer.noSpaces.copy(dropNullValues = true), ordered: OrderedKeys = orderedKeys ): ToResponseMarshaller[A] = { val marshallers = Seq(`application/ld+json`, `application/json`).map { contentType => Marshaller.withFixedContentType[A, HttpResponse](contentType) { rejection => HttpResponse( status = statusFrom(rejection), entity = HttpEntity(contentType, printer.print(rejection.asJson.sortKeys)) ) } } Marshaller.oneOf(marshallers: _*) } implicit class EitherTask[R <: ResourceRejection, A](task: Task[Either[R, A]])(implicit s: Scheduler) { def runWithStatus(code: StatusCode): Future[Either[R, (StatusCode, A)]] = task.map(_.map(code -> _)).runToFuture } implicit class OptionTask[A](task: Task[Option[A]])(implicit s: Scheduler) { def runNotFound: Future[A] = task.flatMap { case Some(a) => Task.pure(a) case None => Task.raiseError(IamError.NotFound) }.runToFuture } }
Example 125
Source File: RepairFromMessages.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam import java.net.URLDecoder import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.PersistenceQuery import ch.epfl.bluebrain.nexus.iam.acls.Acls import ch.epfl.bluebrain.nexus.iam.permissions.Permissions import ch.epfl.bluebrain.nexus.iam.realms.Realms import ch.epfl.bluebrain.nexus.iam.types.Label import ch.epfl.bluebrain.nexus.rdf.Iri.Path import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import scala.concurrent.Future object RepairFromMessages { // $COVERAGE-OFF$ private val log = Logger[RepairFromMessages.type] def repair( p: Permissions[Task], r: Realms[Task], a: Acls[Task] )(implicit as: ActorSystem, sc: Scheduler, pm: CanBlock): Unit = { val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) pq.currentPersistenceIds() .mapAsync(1) { case PermissionsId() => p.agg.currentState(p.persistenceId).runToFuture case RealmId(label) => r.agg.currentState(label.value).runToFuture case AclId(path) => a.agg.currentState(path.asString).runToFuture case other => log.warn(s"Unknown persistence id '$other'") Future.successful(()) } .runFold(0) { case (acc, _) => if (acc % 100 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .runSyncDiscard() log.info("Repair from messages table completed.") } sealed abstract class PersistenceId(prefix: String) { private val len = prefix.length protected def dropPrefix(arg: String): Option[String] = if (arg.startsWith(prefix)) Some(arg.drop(len)) else None } object RealmId extends PersistenceId("realms-") { def unapply(arg: String): Option[Label] = dropPrefix(arg).map(Label.unsafe) } object AclId extends PersistenceId("acls-") { def unapply(arg: String): Option[Path] = dropPrefix(arg).flatMap(str => Path(URLDecoder.decode(str, "UTF-8")).toOption) } object PermissionsId { def unapply(arg: String): Boolean = arg == "permissions-permissions" } implicit class RichFuture[A](val future: Future[A]) extends AnyVal { def runSyncDiscard()(implicit s: Scheduler, permit: CanBlock): Unit = Task.fromFuture(future).map(_ => ()).runSyncUnsafe() } // $COVERAGE-ON$ }
Example 126
Source File: IdentitiesRoutesSpec.scala From nexus-iam with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.iam.routes import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.testkit.ScalatestRouteTest import ch.epfl.bluebrain.nexus.commons.test.Resources import ch.epfl.bluebrain.nexus.iam.auth.{AccessToken, TokenRejection} import ch.epfl.bluebrain.nexus.iam.config.{AppConfig, Settings} import ch.epfl.bluebrain.nexus.iam.marshallers.instances._ import ch.epfl.bluebrain.nexus.iam.realms._ import ch.epfl.bluebrain.nexus.iam.testsyntax._ import ch.epfl.bluebrain.nexus.iam.types.Caller import ch.epfl.bluebrain.nexus.iam.types.IamError.InvalidAccessToken import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Authenticated, User} import com.typesafe.config.{Config, ConfigFactory} import io.circe.Json import monix.eval.Task import org.mockito.matchers.MacroBasedMatchers import org.mockito.{IdiomaticMockito, Mockito} import org.scalatest.BeforeAndAfter import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike import scala.concurrent.duration._ //noinspection TypeAnnotation class IdentitiesRoutesSpec extends AnyWordSpecLike with Matchers with ScalatestRouteTest with BeforeAndAfter with MacroBasedMatchers with Resources with ScalaFutures with IdiomaticMockito { override implicit def patienceConfig: PatienceConfig = PatienceConfig(3.seconds, 100.milliseconds) override def testConfig: Config = ConfigFactory.load("test.conf") private val appConfig: AppConfig = Settings(system).appConfig private implicit val http = appConfig.http private val realms: Realms[Task] = mock[Realms[Task]] before { Mockito.reset(realms) } "The IdentitiesRoutes" should { val routes = Routes.wrap(new IdentitiesRoutes(realms).routes) "return forbidden" in { val err = InvalidAccessToken(TokenRejection.InvalidAccessToken) realms.caller(any[AccessToken]) shouldReturn Task.raiseError(err) Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check { status shouldEqual StatusCodes.Unauthorized } } "return anonymous" in { realms.caller(any[AccessToken]) shouldReturn Task.pure(Caller.anonymous) Get("/identities") ~> routes ~> check { status shouldEqual StatusCodes.OK responseAs[Json].sort shouldEqual jsonContentOf("/identities/anonymous.json") } } "return all identities" in { val user = User("theuser", "therealm") val auth = Authenticated("therealm") val caller = Caller(user, Set(user, Anonymous, auth)) realms.caller(any[AccessToken]) shouldReturn Task.pure(caller) Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check { status shouldEqual StatusCodes.OK responseAs[Json].sort shouldEqual jsonContentOf("/identities/identities.json") } } } }
Example 127
Source File: HttpMockServerResource.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.http.server import com.github.agourlay.cornichon.core.{ RunState, Session } import com.github.agourlay.cornichon.dsl.BlockScopedResource import com.github.agourlay.cornichon.http.server.HttpMockServerResource.SessionKeys._ import io.circe.Json import monix.eval.Task import monix.execution.Scheduler case class HttpMockServerResource(interface: Option[String], label: String, portRange: Option[Range]) extends BlockScopedResource { implicit val scheduler = Scheduler.Implicits.global val sessionTarget: String = label val openingTitle: String = s"Starting HTTP mock server '$label'" val closingTitle: String = s"Shutting down HTTP mock server '$label'" def use[A](outsideRunState: RunState)(f: RunState => Task[A]): Task[(Session, A)] = { val mockRequestHandler = new MockServerRequestHandler() val initSession: String => Session = id => Session.newEmpty.addValueUnsafe(s"$label-url", id) val resourceContext: RunState => Session => RunState = r1 => s1 => r1.mergeSessions(s1) val runWithServer = initSession.andThen(resourceContext(outsideRunState)).andThen(f) val mockServer = new MockHttpServer(interface, portRange, mockRequestHandler.mockService)(runWithServer) mockServer.useServer().map { res => val resourceResults = requestsResults(mockRequestHandler) (resourceResults, res) } } def requestsResults(mockRequestHandler: MockServerRequestHandler): Session = { val jsonRequests = mockRequestHandler.fetchRecordedRequestsAsJson() Session.newEmpty .addValueUnsafe(s"$sessionTarget$receivedBodiesSuffix", Json.fromValues(jsonRequests).spaces2) .addValueUnsafe(s"$sessionTarget$nbReceivedCallsSuffix", jsonRequests.size.toString) } } object HttpMockServerResource { object SessionKeys { val nbReceivedCallsSuffix = "-nb-received-calls" val receivedBodiesSuffix = "-received-bodies" } }
Example 128
Source File: TurnstileAPI.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.framework.examples.propertyCheck.turnstile import com.github.agourlay.cornichon.framework.examples.HttpServer import monix.eval.Task import monix.execution.atomic.AtomicBoolean import monix.execution.{ CancelableFuture, Scheduler } import org.http4s._ import org.http4s.implicits._ import org.http4s.dsl._ import org.http4s.server.Router import org.http4s.server.blaze.BlazeServerBuilder class TurnstileAPI extends Http4sDsl[Task] { implicit val s = Scheduler.Implicits.global private val turnstileLocked = AtomicBoolean(true) private val turnstileService = HttpRoutes.of[Task] { case POST -> Root / "push-coin" => if (turnstileLocked.get()) { turnstileLocked.set(false) Ok("payment accepted") } else BadRequest("payment refused") case POST -> Root / "walk-through" => if (turnstileLocked.get()) BadRequest("door blocked") else { turnstileLocked.set(true) Ok("door turns") } } private val routes = Router( "/" -> turnstileService ) def start(httpPort: Int): CancelableFuture[HttpServer] = BlazeServerBuilder[Task](executionContext = s) .bindHttp(httpPort, "localhost") .withoutBanner .withNio2(true) .withHttpApp(routes.orNotFound) .allocated .map { case (_, stop) => new HttpServer(stop) } .runToFuture }
Example 129
Source File: ReverseAPI.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.framework.examples.propertyCheck.stringReverse import com.github.agourlay.cornichon.framework.examples.HttpServer import monix.eval.Task import monix.execution.{ CancelableFuture, Scheduler } import org.http4s._ import org.http4s.implicits._ import org.http4s.dsl._ import org.http4s.server.Router import org.http4s.server.blaze.BlazeServerBuilder class ReverseAPI extends Http4sDsl[Task] { implicit val s = Scheduler.Implicits.global object WordQueryParamMatcher extends QueryParamDecoderMatcher[String]("word") private val reverseService = HttpRoutes.of[Task] { case POST -> Root / "double-reverse" :? WordQueryParamMatcher(word) => Ok(word.reverse.reverse) } private val routes = Router( "/" -> reverseService ) def start(httpPort: Int): CancelableFuture[HttpServer] = BlazeServerBuilder[Task](executionContext = s) .bindHttp(httpPort, "localhost") .withoutBanner .withNio2(true) .withHttpApp(routes.orNotFound) .allocated .map { case (_, stop) => new HttpServer(stop) } .runToFuture }
Example 130
Source File: ForAllStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.check import cats.data.StateT import com.github.agourlay.cornichon.core.Done.rightDone import com.github.agourlay.cornichon.core.{ Generator, _ } import monix.eval.Task case class ForAllStep[A, B, C, D, E, F](description: String, maxNumberOfRuns: Int)(ga: RandomContext => Generator[A], gb: RandomContext => Generator[B], gc: RandomContext => Generator[C], gd: RandomContext => Generator[D], ge: RandomContext => Generator[E], gf: RandomContext => Generator[F])(f: A => B => C => D => E => F => Step) extends WrapperStep { val baseTitle = s"ForAll values of generators check '$description'" val title = s"$baseTitle with maxNumberOfRuns=$maxNumberOfRuns" override val stateUpdate: StepState = StateT { runState => val randomContext = runState.randomContext val genA = ga(randomContext) val genB = gb(randomContext) val genC = gc(randomContext) val genD = gd(randomContext) val genE = ge(randomContext) val genF = gf(randomContext) def repeatEvaluationOnSuccess(runNumber: Int)(runState: RunState): Task[(RunState, Either[FailedStep, Done])] = if (runNumber > maxNumberOfRuns) Task.now((runState, rightDone)) else { val s = runState.session val generatedA = genA.value(s)() val generatedB = genB.value(s)() val generatedC = genC.value(s)() val generatedD = genD.value(s)() val generatedE = genE.value(s)() val generatedF = genF.value(s)() val preRunLog = InfoLogInstruction(s"Run #$runNumber", runState.depth) val invariantRunState = runState.nestedContext.recordLog(preRunLog) val invariantStep = f(generatedA)(generatedB)(generatedC)(generatedD)(generatedE)(generatedF) invariantStep.runStep(invariantRunState).flatMap { case (newState, l @ Left(_)) => val postRunLog = InfoLogInstruction(s"Run #$runNumber - Failed", runState.depth) val failedState = runState.mergeNested(newState).recordLog(postRunLog) Task.now((failedState, l)) case (newState, _) => val postRunLog = InfoLogInstruction(s"Run #$runNumber", runState.depth) // success case we are not propagating the Session so runs do not interfere with each-others val nextRunState = runState.recordLogStack(newState.logStack).recordLog(postRunLog).registerCleanupSteps(newState.cleanupSteps) repeatEvaluationOnSuccess(runNumber + 1)(nextRunState) } } repeatEvaluationOnSuccess(1)(runState.nestedContext) .timed .map { case (executionTime, (checkState, res)) => val depth = runState.depth val exec = Some(executionTime) val fullLogs = res match { case Left(_) => FailureLogInstruction(s"$baseTitle block failed ", depth, exec) +: checkState.logStack :+ failedTitleLog(depth) case _ => SuccessLogInstruction(s"$baseTitle block succeeded", depth, exec) +: checkState.logStack :+ successTitleLog(depth) } (runState.mergeNested(checkState, fullLogs), res) } } }
Example 131
Source File: AssertStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.regular.assertStep import cats.data._ import cats.data.Validated.Invalid import cats.syntax.either._ import com.github.agourlay.cornichon.core.ScenarioRunner._ import com.github.agourlay.cornichon.core._ import monix.eval.Task import scala.concurrent.duration.Duration case class AssertStep(title: String, action: ScenarioContext => Assertion, show: Boolean = true) extends LogValueStep[Done] { def setTitle(newTitle: String): Step = copy(title = newTitle) override def runLogValueStep(runState: RunState): Task[Either[NonEmptyList[CornichonError], Done]] = Task.delay { val assertion = action(runState.scenarioContext) assertion.validated match { case Invalid(e) => e.asLeft case _ => Done.rightDone } } override def onError(errors: NonEmptyList[CornichonError], runState: RunState, executionTime: Duration): (LogInstruction, FailedStep) = errorsToFailureStep(this, runState.depth, errors, Some(executionTime)) override def logOnSuccess(result: Done, runState: RunState, executionTime: Duration): LogInstruction = successLog(title, runState.depth, show, executionTime) }
Example 132
Source File: EffectStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.regular import cats.data.{ EitherT, NonEmptyList } import cats.syntax.either._ import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.ScenarioRunner._ import monix.eval.Task import scala.concurrent.duration.Duration import scala.concurrent.{ ExecutionContext, Future } case class EffectStep(title: String, effect: ScenarioContext => Future[Either[CornichonError, Session]], show: Boolean = true) extends SessionValueStep { def setTitle(newTitle: String): Step = copy(title = newTitle) override def runSessionValueStep(runState: RunState): Task[Either[NonEmptyList[CornichonError], Session]] = Task.deferFuture(effect(runState.scenarioContext)).map(_.leftMap(NonEmptyList.one)) override def onError(errors: NonEmptyList[CornichonError], runState: RunState, executionTime: Duration): (LogInstruction, FailedStep) = errorsToFailureStep(this, runState.depth, errors, Some(executionTime)) override def logOnSuccess(result: Session, runState: RunState, executionTime: Duration): LogInstruction = successLog(title, runState.depth, show, executionTime) } object EffectStep { def fromEitherT(title: String, effect: ScenarioContext => EitherT[Future, CornichonError, Session], show: Boolean = true): EffectStep = { val effectT: ScenarioContext => Future[Either[CornichonError, Session]] = s => effect(s).value EffectStep(title, effectT, show) } def fromSync(title: String, effect: ScenarioContext => Session, show: Boolean = true): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => Future.successful(effect(s).asRight) EffectStep(title, effectF, show) } def fromSyncE(title: String, effect: ScenarioContext => Either[CornichonError, Session], show: Boolean = true): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => Future.successful(effect(s)) EffectStep(title, effectF, show) } def fromAsync(title: String, effect: ScenarioContext => Future[Session], show: Boolean = true)(implicit ec: ExecutionContext): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => effect(s).map(Right.apply) EffectStep(title, effectF, show) } }
Example 133
Source File: RepeatConcurrentlyStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.StateT import cats.instances.list._ import cats.syntax.foldable._ import cats.syntax.either._ import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.Done._ import monix.eval.Task import monix.reactive.Observable import scala.concurrent.duration.FiniteDuration import scala.util.control.NonFatal case class RepeatConcurrentlyStep(times: Int, nested: List[Step], parallelism: Int, maxTime: FiniteDuration) extends WrapperStep { require(parallelism > 0, "repeat concurrently block must contain a positive 'parallelism' factor") require(times > 0, "repeat concurrently block must contain a positive 'times' factor") require(times >= parallelism, "repeat concurrently block must contain a 'parallelism' factor <= to the number of repeat 'times'") val title = s"Repeat concurrently block '$times' times with parallel factor '$parallelism' and maxTime '$maxTime'" override val stateUpdate: StepState = StateT { runState => val nestedRunState = runState.nestedContext val initialDepth = runState.depth Observable.fromIterable(List.fill(times)(Done)) .mapParallelUnordered(parallelism)(_ => ScenarioRunner.runStepsShortCircuiting(nested, nestedRunState)) .takeUntil(Observable.evalDelayed(maxTime, Done)) .toListL .timed .flatMap { case (executionTime, results) => if (results.size != times) { val error = RepeatConcurrentlyTimeout(times, results.size) val errorState = runState.recordLog(failedTitleLog(initialDepth)).recordLog(FailureLogInstruction(error.renderedMessage, initialDepth, Some(executionTime))) val failedStep = FailedStep.fromSingle(this, error) Task.now(errorState -> failedStep.asLeft) } else { val failedStepRuns = results.collect { case (s, r @ Left(_)) => (s, r) } failedStepRuns.headOption.fold[Task[(RunState, Either[FailedStep, Done])]] { val successStepsRun = results.collect { case (s, r @ Right(_)) => (s, r) } val allRunStates = successStepsRun.map(_._1) //TODO all logs should be merged? // all runs were successful, we pick the first one for the logs val firstStateLog = allRunStates.head.logStack val wrappedLogStack = SuccessLogInstruction(s"Repeat concurrently block succeeded", initialDepth, Some(executionTime)) +: firstStateLog :+ successTitleLog(initialDepth) // TODO merge all sessions together - require diffing Sessions otherwise it produces a huge map full of duplicate as they all started from the same. val updatedSession = allRunStates.head.session // merge all cleanups steps val allCleanupSteps = allRunStates.foldMap(_.cleanupSteps) val successState = runState.withSession(updatedSession).recordLogStack(wrappedLogStack).registerCleanupSteps(allCleanupSteps) Task.now(successState -> rightDone) } { case (s, failedStep) => val ratio = s"'${failedStepRuns.size}/$times' run(s)" val wrapLogStack = FailureLogInstruction(s"Repeat concurrently block failed for $ratio", initialDepth) +: s.logStack :+ failedTitleLog(initialDepth) Task.now(runState.mergeNested(s, wrapLogStack) -> failedStep) } } }.onErrorRecover { case NonFatal(e) => val failedStep = FailedStep.fromSingle(this, RepeatConcurrentlyError(e)) (runState.recordLog(failedTitleLog(initialDepth)), failedStep.asLeft) } } } case class RepeatConcurrentlyTimeout(times: Int, success: Int) extends CornichonError { lazy val baseErrorMessage = s"Repeat concurrently block did not reach completion in time: $success/$times finished" } case class RepeatConcurrentlyError(cause: Throwable) extends CornichonError { lazy val baseErrorMessage = "Repeat concurrently block has thrown an error" override val causedBy = CornichonError.fromThrowable(cause) :: Nil }
Example 134
Source File: ConcurrentlyStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.StateT import cats.instances.list._ import cats.syntax.foldable._ import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.Done._ import monix.eval.Task import monix.reactive.Observable import scala.concurrent.duration.FiniteDuration import scala.util.control.NonFatal case class ConcurrentlyStep(nested: List[Step], maxTime: FiniteDuration) extends WrapperStep { val title = s"Concurrently block with maxTime '$maxTime'" override val stateUpdate: StepState = StateT { runState => val nestedRunState = runState.nestedContext val initialDepth = runState.depth Observable.fromIterable(nested) .mapParallelUnordered(nested.size)(s => ScenarioRunner.runStepsShortCircuiting(s :: Nil, nestedRunState)) .takeUntil(Observable.evalDelayed(maxTime, ())) .toListL .timed .flatMap { case (executionTime, results) => if (results.size != nested.size) { val error = ConcurrentlyTimeout(nested.size, results.size) val errorState = runState.recordLog(failedTitleLog(initialDepth)).recordLog(FailureLogInstruction(error.renderedMessage, initialDepth, Some(executionTime))) val failedStep = FailedStep.fromSingle(this, error) Task.now(errorState -> Left(failedStep)) } else { val failedStepRuns = results.collect { case (s, r @ Left(_)) => (s, r) } failedStepRuns.headOption.fold[Task[(RunState, Either[FailedStep, Done])]] { val successStepsRun = results.collect { case (s, r @ Right(_)) => (s, r) } val allRunStates = successStepsRun.map(_._1) //TODO all logs should be merged? // all runs were successful, we pick the first one for the logs val firstStateLog = allRunStates.head.logStack val wrappedLogStack = SuccessLogInstruction(s"Concurrently block succeeded", initialDepth, Some(executionTime)) +: firstStateLog :+ successTitleLog(initialDepth) // TODO merge all sessions together - require diffing Sessions or it produces a huge map full of duplicate as they all started from the same. val updatedSession = allRunStates.head.session // merge all cleanups steps val allCleanupSteps = allRunStates.foldMap(_.cleanupSteps) val successState = runState.withSession(updatedSession).recordLogStack(wrappedLogStack).registerCleanupSteps(allCleanupSteps) Task.now((successState, rightDone)) } { case (s, failedStep) => val ratio = s"'${failedStepRuns.size}/${nested.size}' run(s)" val wrapLogStack = FailureLogInstruction(s"Concurrently block failed for $ratio", initialDepth) +: s.logStack :+ failedTitleLog(initialDepth) Task.now((runState.mergeNested(s, wrapLogStack), failedStep)) } } }.onErrorRecover { case NonFatal(e) => val failedStep = FailedStep.fromSingle(this, ConcurrentlyError(e)) (runState.recordLog(failedTitleLog(initialDepth)), Left(failedStep)) } } } case class ConcurrentlyTimeout(total: Int, success: Int) extends CornichonError { lazy val baseErrorMessage = s"Concurrently block did not reach completion in time: $success/$total finished" } case class ConcurrentlyError(cause: Throwable) extends CornichonError { lazy val baseErrorMessage = "Concurrently block has thrown an error" override val causedBy = CornichonError.fromThrowable(cause) :: Nil }
Example 135
Source File: FlatMapStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.StateT import com.github.agourlay.cornichon.core._ import monix.eval.Task // Transparent wrapper - Steps are flatten in the main execution case class FlatMapStep(started: Step, nestedProducers: Session => List[Step]) extends WrapperStep { val title: String = "" override val stateUpdate: StepState = StateT { runState => ScenarioRunner.runStepsShortCircuiting(started :: Nil, runState).flatMap { case t @ (rs2, res) => if (res.isLeft) Task.now(t) else { val nestedStep = nestedProducers(rs2.session) ScenarioRunner.runStepsShortCircuiting(nestedStep, rs2) } } } }
Example 136
Source File: RetryMaxStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.{ NonEmptyList, StateT } import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.Done._ import monix.eval.Task case class RetryMaxStep(nested: List[Step], limit: Int) extends WrapperStep { require(limit > 0, "retry max limit must be a positive number") val title = s"RetryMax block with limit '$limit'" override val stateUpdate: StepState = StateT { runState => def retryMaxSteps(runState: RunState, limit: Int, retriesNumber: Long): Task[(Long, RunState, Either[FailedStep, Done])] = ScenarioRunner.runStepsShortCircuiting(nested, runState.resetLogStack).flatMap { case (retriedState, Left(_)) if limit > 0 => // In case of success all logs are returned but they are not printed by default. retryMaxSteps(runState.recordLogStack(retriedState.logStack), limit - 1, retriesNumber + 1) case (retriedState, l @ Left(_)) => // In case of failure only the logs of the last run are shown to avoid giant traces. Task.now((retriesNumber, retriedState, l)) case (retriedState, _) => val successState = runState.withSession(retriedState.session).recordLogStack(retriedState.logStack) Task.now((retriesNumber, successState, rightDone)) } retryMaxSteps(runState.nestedContext, limit, 0) .timed .map { case (executionTime, run) => val (retries, retriedState, report) = run val depth = runState.depth val (logStack, res) = report.fold( failedStep => { val wrappedLogStack = FailureLogInstruction(s"RetryMax block with limit '$limit' failed", depth, Some(executionTime)) +: retriedState.logStack :+ failedTitleLog(depth) val artificialFailedStep = FailedStep.fromSingle(failedStep.step, RetryMaxBlockReachedLimit(limit, failedStep.errors)) (wrappedLogStack, Left(artificialFailedStep)) }, _ => { val wrappedLogStack = SuccessLogInstruction(s"RetryMax block with limit '$limit' succeeded after '$retries' retries", depth, Some(executionTime)) +: retriedState.logStack :+ successTitleLog(depth) (wrappedLogStack, rightDone) } ) (runState.mergeNested(retriedState, logStack), res) } } } case class RetryMaxBlockReachedLimit(limit: Int, errors: NonEmptyList[CornichonError]) extends CornichonError { lazy val baseErrorMessage = s"Retry max block failed '$limit' times" override val causedBy = errors.toList }
Example 137
Source File: RepeatWithStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.{ NonEmptyList, StateT } import com.github.agourlay.cornichon.core.Done.rightDone import com.github.agourlay.cornichon.core._ import monix.eval.Task case class RepeatWithStep(nested: List[Step], elements: List[String], elementName: String) extends WrapperStep { require(elements.nonEmpty, "repeatWith block must contain a non empty sequence of elements") val printElements = s"[${elements.mkString(", ")}]" val title = s"RepeatWith block with elements $printElements" override val stateUpdate: StepState = StateT { runState => def repeatSuccessSteps(remainingElements: List[String], runState: RunState): Task[(RunState, Either[(String, FailedStep), Done])] = remainingElements match { case Nil => Task.now((runState, rightDone)) case element :: tail => // reset logs at each loop to have the possibility to not aggregate in failure case val rs = runState.resetLogStack val runStateWithIndex = rs.addToSession(elementName, element) ScenarioRunner.runStepsShortCircuiting(nested, runStateWithIndex).flatMap { case (onceMoreRunState, stepResult) => stepResult.fold( failed => { // In case of failure only the logs of the last run are shown to avoid giant traces. Task.now((onceMoreRunState, Left((element, failed)))) }, _ => { val successState = runState.mergeNested(onceMoreRunState) repeatSuccessSteps(tail, successState) } ) } } repeatSuccessSteps(elements, runState.nestedContext).timed .map { case (executionTime, (repeatedState, report)) => val depth = runState.depth val (logStack, res) = report match { case Right(_) => val wrappedLogStack = SuccessLogInstruction(s"RepeatWith block with elements $printElements succeeded", depth, Some(executionTime)) +: repeatedState.logStack :+ successTitleLog(depth) (wrappedLogStack, rightDone) case Left((failedElement, failedStep)) => val wrappedLogStack = FailureLogInstruction(s"RepeatWith block with elements $printElements failed at element '$failedElement'", depth, Some(executionTime)) +: repeatedState.logStack :+ failedTitleLog(depth) val artificialFailedStep = FailedStep.fromSingle(failedStep.step, RepeatWithBlockContainFailedSteps(failedElement, failedStep.errors)) (wrappedLogStack, Left(artificialFailedStep)) } (runState.mergeNested(repeatedState, logStack), res) } } } case class RepeatWithBlockContainFailedSteps(element: String, errors: NonEmptyList[CornichonError]) extends CornichonError { lazy val baseErrorMessage = s"RepeatWith block failed for element '$element'" override val causedBy = errors.toList }
Example 138
Source File: WithDataInputStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.{ NonEmptyList, StateT } import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.json.CornichonJson import com.github.agourlay.cornichon.core.ScenarioRunner._ import com.github.agourlay.cornichon.core.Done._ import com.github.agourlay.cornichon.util.Printing._ import monix.eval.Task case class WithDataInputStep(nested: List[Step], where: String) extends WrapperStep { val title = s"With data input block $where" override val stateUpdate: StepState = StateT { runState => def runInputs(inputs: List[List[(String, String)]], runState: RunState): Task[(RunState, Either[(List[(String, String)], FailedStep), Done])] = if (inputs.isEmpty) Task.now((runState, rightDone)) else { val currentInputs = inputs.head val runInfo = InfoLogInstruction(s"Run with inputs ${printArrowPairs(currentInputs)}", runState.depth) val bootstrapFilledInput = runState.addToSession(currentInputs).withLog(runInfo).goDeeper ScenarioRunner.runStepsShortCircuiting(nested, bootstrapFilledInput).flatMap { case (filledState, stepsResult) => stepsResult.fold( failedStep => { // Prepend previous logs Task.now((runState.mergeNested(filledState), Left((currentInputs, failedStep)))) }, _ => { // Logs are propagated but not the session runInputs(inputs.tail, runState.recordLogStack(filledState.logStack)) } ) } } runState.scenarioContext.fillPlaceholders(where) .flatMap(CornichonJson.parseDataTable) .fold( t => Task.now(handleErrors(this, runState, NonEmptyList.one(t))), parsedTable => { val inputs = parsedTable.map { line => line.toList.map { case (key, json) => (key, CornichonJson.jsonStringValue(json)) } } runInputs(inputs, runState.nestedContext) .timed .map { case (executionTime, (inputsState, inputsRes)) => val initialDepth = runState.depth val (logStack, res) = inputsRes match { case Right(_) => val wrappedLogStack = SuccessLogInstruction("With data input succeeded for all inputs", initialDepth, Some(executionTime)) +: inputsState.logStack :+ successTitleLog(initialDepth) (wrappedLogStack, rightDone) case Left((failedInputs, failedStep)) => val wrappedLogStack = FailureLogInstruction("With data input failed for one input", initialDepth, Some(executionTime)) +: inputsState.logStack :+ failedTitleLog(initialDepth) val artificialFailedStep = FailedStep.fromSingle(failedStep.step, WithDataInputBlockFailedStep(failedInputs, failedStep.errors)) (wrappedLogStack, Left(artificialFailedStep)) } (runState.mergeNested(inputsState, logStack), res) } } ) } } case class WithDataInputBlockFailedStep(failedInputs: List[(String, String)], errors: NonEmptyList[CornichonError]) extends CornichonError { lazy val baseErrorMessage = s"WithDataInput block failed for inputs ${printArrowPairs(failedInputs)}" override val causedBy = errors.toList }
Example 139
Source File: RepeatStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import cats.data.{ NonEmptyList, StateT } import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.Done._ import monix.eval.Task case class RepeatStep(nested: List[Step], occurrence: Int, indexName: Option[String]) extends WrapperStep { require(occurrence > 0, "repeat block must contain a positive number of occurrence") val title = s"Repeat block with occurrence '$occurrence'" override val stateUpdate: StepState = StateT { runState => def repeatSuccessSteps(retriesNumber: Int, runState: RunState): Task[(Int, RunState, Either[FailedStep, Done])] = { // reset logs at each loop to have the possibility to not aggregate in failure case val rs = runState.resetLogStack val runStateWithIndex = indexName.fold(rs)(in => rs.addToSession(in, (retriesNumber + 1).toString)) ScenarioRunner.runStepsShortCircuiting(nested, runStateWithIndex).flatMap { case (onceMoreRunState, stepResult) => stepResult.fold( failed => { // In case of failure only the logs of the last run are shown to avoid giant traces. Task.now((retriesNumber, onceMoreRunState, Left(failed))) }, _ => { val successState = runState.withSession(onceMoreRunState.session).recordLogStack(onceMoreRunState.logStack) // only show last successful run to avoid giant traces. if (retriesNumber == occurrence - 1) Task.now((retriesNumber, successState, rightDone)) else repeatSuccessSteps(retriesNumber + 1, runState.withSession(onceMoreRunState.session)) } ) } } repeatSuccessSteps(0, runState.nestedContext) .timed .map { case (executionTime, run) => val (retries, repeatedState, report) = run val depth = runState.depth val (logStack, res) = report.fold( failedStep => { val wrappedLogStack = FailureLogInstruction(s"Repeat block with occurrence '$occurrence' failed after '$retries' occurrence", depth, Some(executionTime)) +: repeatedState.logStack :+ failedTitleLog(depth) val artificialFailedStep = FailedStep.fromSingle(failedStep.step, RepeatBlockContainFailedSteps(retries, failedStep.errors)) (wrappedLogStack, Left(artificialFailedStep)) }, _ => { val wrappedLockStack = SuccessLogInstruction(s"Repeat block with occurrence '$occurrence' succeeded", depth, Some(executionTime)) +: repeatedState.logStack :+ successTitleLog(depth) (wrappedLockStack, rightDone) } ) (runState.mergeNested(repeatedState, logStack), res) } } } case class RepeatBlockContainFailedSteps(failedOccurrence: Int, errors: NonEmptyList[CornichonError]) extends CornichonError { lazy val baseErrorMessage = s"Repeat block failed at occurrence $failedOccurrence" override val causedBy = errors.toList }
Example 140
Source File: RepeatDuringStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.wrapped import java.util.concurrent.TimeUnit import cats.data.{ NonEmptyList, StateT } import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.Done._ import monix.eval.Task import scala.concurrent.duration.FiniteDuration case class RepeatDuringStep(nested: List[Step], duration: FiniteDuration) extends WrapperStep { val title = s"Repeat block during '$duration'" override val stateUpdate: StepState = StateT { runState => val initialDepth = runState.depth def repeatStepsDuring(runState: RunState, duration: FiniteDuration, retriesNumber: Long): Task[(Long, RunState, Either[FailedStep, Done])] = ScenarioRunner.runStepsShortCircuiting(nested, runState.resetLogStack) // reset logs at each loop to have the possibility to not aggregate in failure case .timed .flatMap { case (executionTime, run) => val (repeatedOnceMore, res) = run val remainingTime = duration - executionTime res.fold( failedStep => { // In case of failure only the logs of the last run are shown to avoid giant traces. Task.now((retriesNumber, repeatedOnceMore, Left(failedStep))) }, _ => { val successState = runState.mergeNested(repeatedOnceMore) if (remainingTime.gt(FiniteDuration(0, TimeUnit.MILLISECONDS))) repeatStepsDuring(successState, remainingTime, retriesNumber + 1) else // In case of success all logs are returned but they are not printed by default. Task.now((retriesNumber, successState, rightDone)) } ) } repeatStepsDuring(runState.nestedContext, duration, 0) .timed .map { case (executionTime, run) => val (retries, repeatedRunState, report) = run val (logStack, res) = report.fold( failedStep => { val wrappedLogStack = FailureLogInstruction(s"Repeat block during '$duration' failed after being retried '$retries' times", initialDepth, Some(executionTime)) +: repeatedRunState.logStack :+ failedTitleLog(initialDepth) val artificialFailedStep = FailedStep.fromSingle(failedStep.step, RepeatDuringBlockContainFailedSteps(duration, failedStep.errors)) (wrappedLogStack, Left(artificialFailedStep)) }, _ => { val wrappedLogStack = SuccessLogInstruction(s"Repeat block during '$duration' succeeded after '$retries' retries", initialDepth, Some(executionTime)) +: repeatedRunState.logStack :+ successTitleLog(initialDepth) (wrappedLogStack, rightDone) } ) (runState.mergeNested(repeatedRunState, logStack), res) } } } case class RepeatDuringBlockContainFailedSteps(duration: FiniteDuration, errors: NonEmptyList[CornichonError]) extends CornichonError { lazy val baseErrorMessage = s"RepeatDuring block failed before '$duration'" override val causedBy = errors.toList }
Example 141
Source File: EffectStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.cats import cats.data.{ EitherT, NonEmptyList } import cats.effect.Effect import cats.syntax.either._ import com.github.agourlay.cornichon.core.ScenarioRunner.{ errorsToFailureStep, successLog } import com.github.agourlay.cornichon.core._ import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.duration.Duration case class EffectStep[F[_]: Effect](title: String, effect: ScenarioContext => F[Either[CornichonError, Session]], show: Boolean = true) extends SessionValueStep { def setTitle(newTitle: String): Step = copy(title = newTitle) override def runSessionValueStep(runState: RunState): Task[Either[NonEmptyList[CornichonError], Session]] = Task.fromEffect(effect(runState.scenarioContext)).map(_.leftMap(NonEmptyList.one)) override def onError(errors: NonEmptyList[CornichonError], runState: RunState, executionTime: Duration): (LogInstruction, FailedStep) = errorsToFailureStep(this, runState.depth, errors, Some(executionTime)) override def logOnSuccess(result: Session, runState: RunState, executionTime: Duration): LogInstruction = successLog(title, runState.depth, show, executionTime) } object EffectStep { def fromEitherT[F[_]: Effect](title: String, effect: ScenarioContext => EitherT[F, CornichonError, Session], show: Boolean = true): Step = { val effectT: ScenarioContext => F[Either[CornichonError, Session]] = s => effect(s).value EffectStep(title, effectT, show) } def fromSync(title: String, effect: ScenarioContext => Session, show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.now(effect(s).asRight) EffectStep(title, effectF, show) } def fromSyncE(title: String, effect: ScenarioContext => Either[CornichonError, Session], show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.now(effect(s)) EffectStep(title, effectF, show) } def fromAsync[F[_]: Effect](title: String, effect: ScenarioContext => F[Session], show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.fromEffect(effect(s)).map(Right.apply) EffectStep(title, effectF, show) } }
Example 142
Source File: FeatureRunner.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.core import com.github.agourlay.cornichon.dsl.BaseFeature import com.github.agourlay.cornichon.matchers.MatcherResolver import monix.eval.Task import monix.reactive.Observable case class FeatureRunner(featureDef: FeatureDef, baseFeature: BaseFeature, explicitSeed: Option[Long]) { private val featureContext = FeatureContext( beforeSteps = baseFeature.beforeEachScenario.toList, finallySteps = baseFeature.afterEachScenario.toList, featureIgnored = featureDef.ignored.isDefined, focusedScenarios = featureDef.focusedScenarios, withSeed = explicitSeed.orElse(baseFeature.seed), customExtractors = baseFeature.registerExtractors, allMatchers = (MatcherResolver.builtInMatchers ::: baseFeature.registerMatchers).groupBy(_.key) ) final def runScenario(s: Scenario): Task[ScenarioReport] = { println(s"Starting scenario '${s.name}'") ScenarioRunner.runScenario(Session.newEmpty, featureContext)(s) } final def runFeature(filterScenario: Scenario => Boolean)(scenarioResultHandler: ScenarioReport => ScenarioReport): Task[List[ScenarioReport]] = { val scenariosToRun = featureDef.scenarios.filter(filterScenario) if (scenariosToRun.isEmpty) FeatureRunner.noop else { // Run 'before feature' hooks baseFeature.beforeFeature.foreach(f => f()) // featureParallelism is limited to avoid spawning too much work at once val featureParallelism = if (baseFeature.executeScenariosInParallel) Math.min(scenariosToRun.size, FeatureRunner.maxParallelism) else 1 Observable.fromIterable(scenariosToRun) .mapParallelUnordered(featureParallelism)(runScenario(_).map(scenarioResultHandler)) .toListL .map { results => // Run 'after feature' hooks baseFeature.afterFeature.foreach(f => f()) results } } } } object FeatureRunner { // the tests are mostly IO bound so we can start a bit more on a single core lazy val maxParallelism: Int = Runtime.getRuntime.availableProcessors() + 1 private val noop = Task.now(Nil) }
Example 143
Source File: ScenarioReport.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.core import cats.data.Validated.Valid import cats.data.{ NonEmptyList, ValidatedNel } import cats.kernel.Monoid import monix.eval.Task import scala.concurrent.Future import scala.concurrent.duration.{ Duration, FiniteDuration } sealed trait ScenarioReport { def isSuccess: Boolean def scenarioName: String def session: Session def logs: List[LogInstruction] def duration: FiniteDuration } object ScenarioReport { def build(scenarioName: String, runState: RunState, result: ValidatedNel[FailedStep, Done], duration: FiniteDuration): ScenarioReport = result.fold( failedSteps => FailureScenarioReport(scenarioName, failedSteps, runState.session, runState.logStack, duration, runState.randomContext.initialSeed), _ => SuccessScenarioReport(scenarioName, runState.session, runState.logStack, duration, runState.randomContext.initialSeed) ) } case class SuccessScenarioReport(scenarioName: String, session: Session, logStack: List[LogInstruction], duration: FiniteDuration, seed: Long) extends ScenarioReport { val isSuccess = true // keeping it lazy to avoid the reverse in case of no rendering lazy val logs = logStack.reverse // In case of success, logs are only shown if the scenario contains DebugLogInstruction lazy val shouldShowLogs: Boolean = logStack.exists(_.isInstanceOf[DebugLogInstruction]) } case class IgnoreScenarioReport(scenarioName: String, reason: String, session: Session) extends ScenarioReport { val logs = Nil val isSuccess = false val duration = Duration.Zero } case class PendingScenarioReport(scenarioName: String, session: Session) extends ScenarioReport { val logs = Nil val isSuccess = false val duration = Duration.Zero } case class FailureScenarioReport(scenarioName: String, failedSteps: NonEmptyList[FailedStep], session: Session, logStack: List[LogInstruction], duration: FiniteDuration, seed: Long) extends ScenarioReport { val isSuccess = false val msg = s"""|Scenario '$scenarioName' failed: |${failedSteps.toList.iterator.map(_.messageForFailedStep).mkString("\nand\n")} |seed for the run was '$seed' |""".stripMargin lazy val logs = logStack.reverse lazy val renderedColoredLogs = LogInstruction.renderLogs(logs) lazy val renderedLogs = LogInstruction.renderLogs(logs, colorized = false) } sealed abstract class Done case object Done extends Done { val rightDone = Right(Done) val validDone = Valid(Done) val futureDone = Future.successful(Done) val taskDone = Task.now(Done) implicit val monoid = new Monoid[Done] { def empty: Done = Done def combine(x: Done, y: Done): Done = x } } case class FailedStep(step: Step, errors: NonEmptyList[CornichonError]) { lazy val messageForFailedStep = s""" |at step: |${step.title} | |with error(s): |${errors.toList.iterator.map(_.renderedMessage).mkString("\nand\n")} |""".stripMargin } object FailedStep { def fromSingle(step: Step, error: CornichonError) = FailedStep(step, NonEmptyList.one(error)) }
Example 144
Source File: MatchersProperties.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.matchers import java.time.Instant import java.time.format.DateTimeFormatter import com.github.agourlay.cornichon.matchers.Matchers._ import io.circe.Json import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalacheck._ import org.scalacheck.Prop._ import org.typelevel.claimant.Claim object MatchersProperties extends Properties("Matchers") { val reasonablyRandomInstantGen: Gen[Instant] = for { randomOffset <- Arbitrary.arbLong.arbitrary } yield Instant.now().plusMillis(randomOffset % 1000000000000L) val instantGen: Gen[Instant] = for { randomOffset <- Arbitrary.arbLong.arbitrary } yield Instant.now().plusMillis(randomOffset) property("any-integer correct for any int") = forAll(Gen.size) { int => Claim { anyInteger.predicate(Json.fromInt(int)) } } property("any-integer incorrect for any alphanum string") = forAll(Gen.alphaNumStr) { alphanum => Claim { !anyInteger.predicate(Json.fromString(alphanum)) } } property("any-positive-integer correct for any positive int") = forAll(Gen.choose(1, Int.MaxValue)) { int => Claim { anyPositiveInteger.predicate(Json.fromInt(int)) } } property("any-positive-integer incorrect for any alphanum string") = forAll(Gen.alphaNumStr) { alphanum => Claim { !anyPositiveInteger.predicate(Json.fromString(alphanum)) } } property("any-negative-integer correct for any negative int") = forAll(Gen.negNum[Int]) { int => Claim { anyNegativeInteger.predicate(Json.fromInt(int)) } } property("any-negative-integer incorrect for any alphanum string") = forAll(Gen.alphaNumStr) { alphanum => Claim { !anyNegativeInteger.predicate(Json.fromString(alphanum)) } } property("any-uuid correct for any valid UUID") = forAll(Gen.uuid) { uuid => Claim { anyUUID.predicate(Json.fromString(uuid.toString)) } } property("any-uuid incorrect for any alphanum string") = forAll(Gen.alphaNumStr) { alphanum => Claim { !anyUUID.predicate(Json.fromString(alphanum)) } } property("any-date-time correct for all ISO-compliant values, including Y10K+ dates") = forAll(instantGen) { instant => Claim { anyDateTime.predicate(Json.fromString(DateTimeFormatter.ISO_INSTANT.format(instant))) } } property("any-date-time correct in parallel") = { forAll(reasonablyRandomInstantGen) { instant => val booleans = 1.to(64).map { _ => Task.delay { anyDateTime.predicate(Json.fromString(DateTimeFormatter.ISO_INSTANT.format(instant))) } } val res = Task.parSequenceUnordered(booleans).runSyncUnsafe().foldLeft(List.empty[Boolean]) { case (acc, e) => e :: acc } Claim(res.forall(_ == true)) } } }
Example 145
Source File: EffectStepSpec.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.regular import com.github.agourlay.cornichon.core.{ CornichonError, Scenario, ScenarioRunner, Session } import com.github.agourlay.cornichon.steps.cats.{ EffectStep => CEffectStep } import com.github.agourlay.cornichon.testHelpers.CommonTestSuite import monix.eval.Task import utest._ import scala.concurrent.Future import scala.util.control.NoStackTrace object EffectStepSpec extends TestSuite with CommonTestSuite { val tests = Tests { test("EffectStep Async - return error if an Effect step throw an exception") { val step = EffectStep(title = "buggy effect", _ => throwExceptionWithStackTrace()) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) scenarioFailsWithMessage(res) { """|Scenario 'scenario with broken effect step' failed: | |at step: |buggy effect | |with error(s): |exception thrown com.github.agourlay.cornichon.testHelpers.CommonTesting$$anon$1: boom! | | |seed for the run was '1' |""".stripMargin } } test("EffectStep Async - return error if an Effect step for Future.failed") { val step = EffectStep(title = "buggy effect", _ => Future.failed(new RuntimeException("boom"))) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("EffectStep Sync - return error if an Effect step throw an exception") { val step = EffectStep.fromSync(title = "buggy effect", _ => throwExceptionWithStackTrace()) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("EffectStep SyncE - valid if effect is an Either.Right") { val step = EffectStep.fromSyncE(title = "valid effect", sc => Right(sc.session)) val s = Scenario("scenario with valid effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(res.isSuccess) } test("EffectStep SyncE - invalid if effect is an Either.Left") { val step = EffectStep.fromSyncE(title = "valid effect", _ => Left(CornichonError.fromString("ohh nooes"))) val s = Scenario("scenario with invalid effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("CatsEffectStep Async - return error if an Effect step throw an exception") { val step = CEffectStep[Task](title = "buggy effect", _ => throwExceptionWithStackTrace()) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("CatsEffectStep Async - return error if an Effect step for Task.raiseError") { val step = CEffectStep[Task](title = "buggy effect", _ => Task.raiseError(new RuntimeException("boom") with NoStackTrace)) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("CatsEffectStep Sync - return error if an Effect step throw an exception") { val step = CEffectStep[Task](title = "buggy effect", _ => throwExceptionWithStackTrace()) val s = Scenario("scenario with broken effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } test("CatsEffectStep SyncE - valid if effect is an Either.Right") { val step = CEffectStep.fromSyncE(title = "valid effect", sc => Right(sc.session)) val s = Scenario("scenario with valid effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(res.isSuccess) } test("CatsEffectStep SyncE - invalid if effect is an Either.Left") { val step = CEffectStep.fromSyncE(title = "valid effect", _ => Left(CornichonError.fromString("ohh nooes"))) val s = Scenario("scenario with invalid effect step", step :: Nil) val res = awaitTask(ScenarioRunner.runScenario(Session.newEmpty)(s)) assert(!res.isSuccess) } } }
Example 146
Source File: DoobieInstancesSuite.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.doobie import cats.Applicative import cats.data.ReaderT import cats.effect.{IO, SyncIO} import com.github.ghik.silencer.silent import doobie.ConnectionIO import monix.eval.{Coeval, Task} import monix.execution.Scheduler import tofu.doobie.instances.implicits._ import tofu.env.Env import tofu.lift.Lift import tofu.zioInstances.implicits._ import zio.interop.catz._ object DoobieInstancesSuite { def summonImplicitsViaLiftToIO[F[_]: Applicative, R](implicit L: Lift[F, IO]): Unit = { Lift[F, ConnectionIO] Lift[F, ConnectionRIO[R, *]] Lift[ReaderT[F, R, *], ConnectionRIO[R, *]] () } def summonCatsEffectImplicits[R](): Unit = { Lift[SyncIO, ConnectionIO] Lift[SyncIO, ConnectionRIO[R, *]] Lift[ReaderT[SyncIO, R, *], ConnectionRIO[R, *]] Lift[IO, ConnectionIO] Lift[IO, ConnectionRIO[R, *]] Lift[ReaderT[IO, R, *], ConnectionRIO[R, *]] () } def summonMonixImplicitsViaScheduler[R](implicit sc: Scheduler): Unit = { Lift[Coeval, ConnectionIO] Lift[Coeval, ConnectionRIO[R, *]] Lift[ReaderT[Coeval, R, *], ConnectionRIO[R, *]] Lift[Task, ConnectionIO] Lift[Task, ConnectionRIO[R, *]] Lift[ReaderT[Task, R, *], ConnectionRIO[R, *]] Lift[Env[R, *], ConnectionRIO[R, *]] () } def summonMonixImplicitsUnambiguously[R](implicit @silent sc: Scheduler, L: Lift[Task, IO]): Unit = { Lift[Task, ConnectionIO] Lift[Task, ConnectionRIO[R, *]] Lift[ReaderT[Task, R, *], ConnectionRIO[R, *]] () } def summonZioImplicits[R](): zio.Task[Unit] = zio.Task.concurrentEffect.map { implicit CE => Lift[zio.Task, ConnectionIO] Lift[zio.Task, ConnectionRIO[R, *]] Lift[zio.RIO[R, *], ConnectionRIO[R, *]] () } def summonLiftConnectionIO[R](): Unit = { LiftConnectionIO[ConnectionIO] LiftConnectionIO[ConnectionRIO[R, *]] () } }
Example 147
Source File: EnvSyntax.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import monix.eval.Task private[env] trait EnvSyntax { implicit def toEnvOptionOps[E, A](env: Env[E, Option[A]]): EnvOptionOps[E, A] = new EnvOptionOps(env) } class EnvOptionOps[E, A](val ea: Env[E, Option[A]]) extends AnyVal { import EnvOptionOps._ def orElseF[B >: A](eb: Env[E, Option[B]]): Env[E, Option[B]] = (ea, eb) match { case (EnvTask(ta), EnvTask(tb)) => EnvTask(ta.flatMap { case None => tb case s @ Some(_) => Task.pure(s) }) case _ => ea.flatMap { case None => eb case s @ Some(_) => Env.pure(s) } } def orElseT[B >: A](tb: Task[Option[B]]): Env[E, Option[B]] = ea.mapTask(_.flatMap { case None => tb case s @ Some(_) => Task.pure(s) }) def orElse[B >: A](b: => Option[B]): Env[E, Option[B]] = ea.mapTask(_.map(_.orElse(b))) def getOrElseF[B >: A](eb: Env[E, B]): Env[E, B] = eb match { case EnvTask(tb) => ea.mapTask(getOrElseTask(tb)) case _ => Env(ctx => getOrElseTask(eb.run(ctx))(ea.run(ctx))) } def getOrElseT[B >: A](tb: Task[B]): Env[E, B] = ea.mapTask(getOrElseTask(tb)) def getOrElse[B >: A](a: => B): Env[E, B] = ea.map(_.getOrElse(a)) def orRaise(e: Throwable): Env[E, A] = ea.mapTask(_.flatMap(_.fold(Task.raiseError[A](e))(Task.pure))) } object EnvOptionOps { @inline private def getOrElseTask[A](tb: Task[A])(ta: Task[Option[A]]): Task[A] = ta.flatMap(_.fold(tb)(Task.pure)) }
Example 148
Source File: Memoization.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import monix.catnap.MVar import monix.eval.Task final class Memoization[A] private (memo: MVar[Task, Option[A]]) { private def initWith(x: Task[A]): Task[A] = memo.take.bracketE(_.fold(x)(Task.pure)) { case (_, Right(b)) => memo.put(Some(b)) case (prev, _) => memo.put(prev) } def getOrElse(x: Task[A]): Task[A] = for { state <- memo.read value <- state.fold(initWith(x))(Task.pure) } yield value } object Memoization { def apply[A]: Task[Task[Memoization[A]]] = Task.delay(unsafe()) def unsafe[A](): Task[Memoization[A]] = MVar[Task].of(Option.empty[A]).map(mvar => new Memoization[A](mvar)).memoize }
Example 149
Source File: EnvInstances.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import cats.arrow.{ArrowChoice, FunctionK, Profunctor} import cats.effect.IO import cats.{Applicative, Monad, Parallel, ~>} import monix.eval.{Task, TaskLift} import monix.execution.Scheduler import tofu.lift.{UnliftIO, UnsafeExecFuture} import tofu.optics.Contains import tofu.syntax.funk._ import scala.concurrent.Future private[env] trait EnvInstances { self: Env.type => private object anyEnvInstance extends EnvFunctorstance[Any] final implicit def envInstance[E]: EnvFunctorstance[E] = anyEnvInstance.asInstanceOf[EnvFunctorstance[E]] private object envParallelInstance extends Applicative[Env[Any, *]] { override def pure[A](x: A): Env[Any, A] = Env.pure(x) override def ap[A, B](ff: Env[Any, A => B])(fa: Env[Any, A]): Env[Any, B] = Env.parMap2(ff, fa)(_.apply(_)) override def map2[A, B, Z](fa: Env[Any, A], fb: Env[Any, B])(f: (A, B) => Z): Env[Any, Z] = Env.parMap2(fa, fb)(f) override val unit: Env[Any, Unit] = Env.unit override def map[A, B](fa: Env[Any, A])(f: A => B): Env[Any, B] = fa.map(f) override def replicateA[A](n: Int, fa: Env[Any, A]): Env[Any, List[A]] = fa.mapTask(t => Task.parSequence(Iterable.fill(n)(t)).map(_.toList)) } private object anyEnvParallelInstance extends Parallel[Env[Any, *]] { type F[a] = Env[Any, a] override def applicative: Applicative[Env[Any, *]] = envParallelInstance override def monad: Monad[Env[Any, *]] = anyEnvInstance override val sequential: ~>[Env[Any, *], Env[Any, *]] = FunctionK.id override val parallel: ~>[Env[Any, *], Env[Any, *]] = FunctionK.id } final implicit def envParallelInstance[E]: Parallel[Env[E, *]] = anyEnvParallelInstance.asInstanceOf[Parallel[Env[E, *]]] final implicit val envProfuctorInstance: Profunctor[Env] with ArrowChoice[Env] = new Profunctor[Env] with ArrowChoice[Env] { override def choose[A, B, C, D](f: Env[A, C])(g: Env[B, D]): Env[Either[A, B], Either[C, D]] = Env { case Left(a) => f.run(a).map(Left(_)) case Right(b) => g.run(b).map(Right(_)) } override def lift[A, B](f: A => B): Env[A, B] = Env(a => Task.pure(f(a))) override def first[A, B, C](fa: Env[A, B]): Env[(A, C), (B, C)] = fa.first[C] override def second[A, B, C](fa: Env[A, B]): Env[(C, A), (C, B)] = fa.second[C] override def compose[A, B, C](f: Env[B, C], g: Env[A, B]): Env[A, C] = f.compose(g) override def rmap[A, B, C](fab: Env[A, B])(f: B => C): Env[A, C] = fab.map(f) override def lmap[A, B, C](fab: Env[A, B])(f: C => A): Env[C, B] = fab.localP(f) override def id[A]: Env[A, A] = Env.context override def dimap[A, B, C, D](fab: Env[A, B])(f: C => A)(g: B => D): Env[C, D] = fab.dimap(f)(g) override def split[A, B, C, D](f: Env[A, B], g: Env[C, D]): Env[(A, C), (B, D)] = f.split(g) override def left[A, B, C](fab: Env[A, B]): Env[Either[A, C], Either[B, C]] = fab.left[C] override def right[A, B, C](fab: Env[A, B]): Env[Either[C, A], Either[C, B]] = fab.right[C] override def choice[A, B, C](f: Env[A, C], g: Env[B, C]): Env[Either[A, B], C] = f.choice(g) override def merge[A, B, C](f: Env[A, B], g: Env[A, C]): Env[A, (B, C)] = Env.parZip2(f, g) } final implicit def envUnliftSubContext[E, E1: E Contains *]: EnvUnliftSubContext[E, E1] = new EnvUnliftSubContext def envUnsafeExecFuture[E](implicit sc: Scheduler): UnsafeExecFuture[Env[E, *]] = new UnsafeExecFuture[Env[E, *]] { def lift[A](fa: Future[A]): Env[E, A] = Env.fromFuture(fa) def unlift: Env[E, Env[E, *] ~> Future] = Env.fromFunc(r => makeFunctionK(_.run(r).runToFuture)) } implicit def envUnliftIO[E](implicit toIO: TaskLift[IO]): UnliftIO[Env[E, *]] = new UnliftIO[Env[E, *]] { def lift[A](fa: IO[A]): Env[E, A] = Env.fromIO(fa) def unlift: Env[E, Env[E, *] ~> IO] = Env.fromFunc(r => funK(_.run(r).to[IO])) } }
Example 150
Source File: EnvRacing.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import cats.effect._ import monix.eval.Task import scala.collection.compat._ private[env] trait EnvRacing { self: Env.type => type Racing[F[_], A, B] = Either[(A, Fiber[F, B]), (Fiber[F, A], B)] private def convertRacingFibers[E, A, B]: Racing[Task, A, B] => Racing[Env[E, *], A, B] = { case Left((a, fibB)) => Left((a, EnvFiber(fibB))) case Right((fibA, b)) => Right((EnvFiber(fibA), b)) } def racePair[E, A, B]( ta: Env[E, A], tb: Env[E, B] ): Env[E, Either[(A, Fiber[Env[E, *], B]), (Fiber[Env[E, *], A], B)]] = (ta, tb) match { case (EnvTask(taskA), EnvTask(taskB)) => fromTask(Task.racePair(taskA, taskB).map(convertRacingFibers)) case _ => Env(ctx => Task.racePair(ta.run(ctx), tb.run(ctx)).map(convertRacingFibers)) } def race[E, A, B](ta: Env[E, A], tb: Env[E, B]): Env[E, Either[A, B]] = (ta, tb) match { case (EnvTask(taskA), EnvTask(taskB)) => fromTask(Task.race(taskA, taskB)) case _ => Env(ctx => Task.race(ta.run(ctx), tb.run(ctx))) } def raceMany[E, A](tta: IterableOnce[Env[E, A]]): Env[E, A] = { val taskAccum = Array.newBuilder[Task[A]] val funcAccum = Array.newBuilder[E => Task[A]] tta.iterator.foreach { case EnvTask(tt) => taskAccum += tt case env => funcAccum += env.run } val tasks = taskAccum.result() val funcs = funcAccum.result() if (funcs.isEmpty) EnvTask(Task.raceMany(tasks)) else Env(ctx => Task.raceMany(funcs.map(_(ctx)) ++ tasks)) } } final private[env] case class EnvFiber[E, A](taskFiber: Fiber[Task, A]) extends Fiber[Env[E, *], A] { override def cancel: Env[E, Unit] = Env.fromTask(taskFiber.cancel) override def join: Env[E, A] = Env.fromTask(taskFiber.join) }
Example 151
Source File: EnvFunctions.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import java.util.concurrent.TimeUnit.MILLISECONDS import cats.Eval import cats.data.ReaderT import cats.effect._ import monix.eval.{Coeval, Task} import monix.execution.Scheduler import scala.concurrent.duration.FiniteDuration import scala.concurrent.{ExecutionContext, Future} import scala.util.Try private[env] trait EnvFunctions extends EnvProducts with EnvTraversing with EnvRacing with EnvSyntax with EnvTransformations { self: Env.type => def apply[E, A](f: E => Task[A]): Env[E, A] = EnvCtx(f) def later[E, A](x: => A): Env[E, A] = fromTask(Task.delay(x)) def pure[E, A](x: A): Env[E, A] = fromTask(Task.pure(x)) def context[E]: Env[E, E] = Env(ctx => Task.now(ctx)) def withContextNow[E, A](f: E => A): Env[E, A] = Env(ctx => Task.now(f(ctx))) def withContext[E, A](f: E => Env[E, A]): Env[E, A] = Env(ctx => f(ctx).run(ctx)) def withContextFork[E, A](f: E => A): Env[E, A] = Env(ctx => Task(f(ctx))) def withContextDelay[E, A](f: E => A): Env[E, A] = Env(ctx => Task.delay(f(ctx))) private[this] val anyUnit: Env[Any, Unit] = fromTask(Task.unit) def unit[E]: Env[E, Unit] = anyUnit.asInstanceOf[Env[E, Unit]] def scheduler[E]: Env[E, Scheduler] = fromTask(Task.deferAction(scheduler => Task.pure(scheduler))) def millis[E]: Env[E, Long] = fromTask(Task.deferAction(scheduler => Task.pure(scheduler.clockRealTime(MILLISECONDS)))) def shift[E]: Env[E, Unit] = fromTask(Task.shift) def shift[E](ec: ExecutionContext): Env[E, Unit] = fromTask(Task.shift(ec)) def sleep[E](duration: FiniteDuration): Env[E, Unit] = fromTask(Task.sleep(duration)) def fromTask[E, A](task: Task[A]): Env[E, A] = EnvTask(task) def delay[E, A](x: => A): Env[E, A] = later(x) def defer[E, A](x: => Env[E, A]): Env[E, A] = Env(ctx => Task.defer(x.run(ctx))) def deferTask[E, A](x: => Task[A]): Env[E, A] = fromTask(Task.defer(x)) def deferFuture[E, A](future: => Future[A]): Env[E, A] = EnvTask(Task.deferFuture(future)) def deferFutureContext[E, A](future: E => Future[A]): Env[E, A] = Env(ctx => Task.deferFuture(future(ctx))) def deferFutureAction[E, A](futAct: Scheduler => Future[A]): Env[E, A] = EnvTask(Task.deferFutureAction(futAct)) def raiseError[E, A](throwable: Throwable): Env[E, A] = EnvTask(Task.raiseError(throwable)) def attempt[E, A](e: Env[E, A]): Env[E, Either[Throwable, A]] = e.attempt def fromFunc[E, A](f: E => A): Env[E, A] = Env.withContextNow(f) def fromReaderT[E, A](reader: ReaderT[Task, E, A]): Env[E, A] = Env(reader.run) def fromTry[E, A](t: Try[A]): Env[E, A] = fromTask(Task.fromTry(t)) def fromEither[E, A](e: Either[Throwable, A]): Env[E, A] = fromTask(Task.fromTry(e.toTry)) def fromFuture[E, A](future: Future[A]): Env[E, A] = EnvTask(Task.fromFuture(future)) def fromTryFunc[E, A](ft: E => Try[A]): Env[E, A] = Env(ctx => Task.fromTry(ft(ctx))) def fromEffect[F[_]: Effect, E, A](fa: F[A]): Env[E, A] = fromTask(Task.fromEffect(fa)) def fromEffectFunc[F[_]: Effect, E, A](ffa: E => F[A]): Env[E, A] = Env(ctx => Task.fromEffect(ffa(ctx))) def fromEval[E, A](ea: Eval[A]): Env[E, A] = fromTask(Task.from(ea)) def fromEvalFunc[E, A](fea: E => Eval[A]): Env[E, A] = Env(ctx => Task.from(fea(ctx))) def fromIO[E, A](ioa: IO[A]): Env[E, A] = fromTask(Task.from(ioa)) def fromIOFunc[E, A](fioa: E => IO[A]): Env[E, A] = Env(ctx => Task.from(fioa(ctx))) def fromCoeval[E, A](ca: Coeval[A]): Env[E, A] = fromTask(ca.to[Task]) def fromCoevalFunc[E, A](fca: E => Coeval[A]): Env[E, A] = Env(ctx => fca(ctx).to[Task]) def tailRecM[E, A, B](a: A)(f: (A) => Env[E, Either[A, B]]): Env[E, B] = Env(ctx => Task.tailRecM(a)(a1 => f(a1).run(ctx))) def when[E](cond: => Boolean)(io: => Env[E, _]): Env[E, Unit] = whenF(delay[E, Boolean](cond))(io) def whenF[E](cond: Env[E, Boolean])(io: => Env[E, _]): Env[E, Unit] = cond.flatMap(run => if (run) io.flatMap(_ => Env.unit[E]) else Env.unit[E]) }
Example 152
Source File: EnvTraversing.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import monix.eval.Task import monix.execution.compat.BuildFrom import tofu.env.internal.CollectionMapper private[env] trait EnvTraversing { def sequence[E, A, M[X] <: Iterable[X]]( in: M[Env[E, A]] )(implicit cbf: BuildFrom[M[Env[E, A]], A, M[A]]): Env[E, M[A]] = Env(ctx => Task.traverse(in)(_.run(ctx))) def traverse[E, A, B, M[X] <: Iterable[X]]( in: M[A] )(f: A => Env[E, B])(implicit cbf: BuildFrom[M[A], B, M[B]]): Env[E, M[B]] = Env(ctx => Task.traverse(in)(x => f(x).run(ctx))) def gather[E, A, M[X] <: Iterable[X]]( in: M[Env[E, A]] )(implicit cbf: BuildFrom[M[Env[E, A]], A, M[A]]): Env[E, M[A]] = Env(ctx => Task.parTraverse(in)(_.run(ctx))) def wander[E, A, B, M[X] <: Iterable[X]]( in: M[A] )(f: A => Env[E, B])(implicit cbf: BuildFrom[M[A], B, M[B]]): Env[E, M[B]] = Env(ctx => Task.parTraverse(in)(x => f(x).run(ctx))) def gatherUnordered[E, A](in: Iterable[Env[E, A]]): Env[E, List[A]] = Env(ctx => Task.parTraverseUnordered(in)(_.run(ctx))) def wanderUnordered[E, A, B, M[X] <: Iterable[X]](in: M[A])(f: A => Env[E, B]): Env[E, List[B]] = Env(ctx => Task.parTraverseUnordered(in)(x => f(x).run(ctx))) object opt { type EitherAllTasks[M[_], E, A] = Either[M[Env[E, A]], M[EnvTask[E, A]]] @inline private[this] def walkTasks[E, A, M[X] <: Iterable[X]]( in: M[Env[E, A]], fallback: => Env[E, M[A]], task: M[Env[E, A]] => (Env[E, A] => Task[A]) => Task[M[A]] ): Env[E, M[A]] = if (in.forall(_.isInstanceOf[EnvTask[E, A]])) Env.fromTask(task(in)(_.asInstanceOf[EnvTask[E, A]].ta)) else fallback def sequence[E, A, M[+X] <: Iterable[X]]( in: M[Env[E, A]] )(implicit cb: BuildFrom[M[Env[E, A]], A, M[A]]): Env[E, M[A]] = walkTasks(in, Env.sequence(in), Task.traverse[Env[E, A], A, M]) def traverse[E, A, B, M[+X] <: Iterable[X]](in: M[A])( f: A => Env[E, B] )(implicit mapper: CollectionMapper[A, Env[E, B], M], cbf2: BuildFrom[M[Env[E, B]], B, M[B]]): Env[E, M[B]] = sequence(mapper.map(in, f)) def parSequence[E, A, M[X] <: Iterable[X]]( in: M[Env[E, A]] )(implicit cbf: BuildFrom[M[Env[E, A]], A, M[A]]): Env[E, M[A]] = walkTasks(in, Env.gather(in), Task.parTraverse[Env[E, A], A, M]) def parTraverse[E, A, B, M[X] <: Iterable[X]](in: M[A])( f: A => Env[E, B] )(implicit mapper: CollectionMapper[A, Env[E, B], M], cbf2: BuildFrom[M[Env[E, B]], B, M[B]]): Env[E, M[B]] = parSequence(mapper.map(in, f)) def parSequenceUnordered[E, A](in: Iterable[Env[E, A]]): Env[E, List[A]] = walkTasks(in.toList, Env.gatherUnordered(in), Task.parTraverseUnordered[Env[E, A], A, List]) def parTraverseUnordered[E, A, B, M[X] <: Iterable[X]](in: M[A])(f: A => Env[E, B]): Env[E, List[B]] = parSequenceUnordered(in.map(f)) @deprecated("use parSequence", since = "0.7.6") def gather[E, A, M[X] <: Iterable[X]]( in: M[Env[E, A]] )(implicit cbf: BuildFrom[M[Env[E, A]], A, M[A]]): Env[E, M[A]] = parSequence(in) @deprecated("use parTraverse", since = "0.7.6") def wander[E, A, B, M[X] <: Iterable[X]](in: M[A])( f: A => Env[E, B] )(implicit mapper: CollectionMapper[A, Env[E, B], M], cbf2: BuildFrom[M[Env[E, B]], B, M[B]]): Env[E, M[B]] = parTraverse(in)(f) @deprecated("use parTraverseUnordered", since = "0.7.6") def wanderUnordered[E, A, B, M[X] <: Iterable[X]](in: M[A])(f: A => Env[E, B]): Env[E, List[B]] = parTraverseUnordered(in)(f) @deprecated("use parSequenceUnordered", since = "0.7.6") def gatherUnordered[E, A](in: Iterable[Env[E, A]]): Env[E, List[A]] = parSequenceUnordered(in) } }
Example 153
Source File: EnvBioSpecializedFunctions.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env.bio import monix.eval.Task trait EnvBioSpecializedFunctions[R, E] { type F[A] = EnvBio[R, E, A] def apply[A](f: R => Task[Either[E, A]]): EnvBio[R, E, A] = EnvBio.apply(f) def applyFatal[A](f: R => Task[A]): EnvBio[R, E, A] = EnvBio.applyFatal(a => f(a)) def pure[A](x: A): EnvBio[R, E, A] = EnvBio.pure(x) def raiseError(e: E): EnvBio[R, E, Nothing] = EnvBio.raiseError(e) def context: EnvBio[R, E, R] = EnvBio.context def fromTask[A](task: Task[A]): EnvBio[R, Throwable, A] = EnvBio.fromTask(task) def fromTaskTotal[A](task: Task[A]): EnvBio[R, Nothing, A] = EnvBio.fromTaskTotal(task) def map2[A, B, C, R1 <: R, E1 >: E](ea: EnvBio[R, E, A], eb: EnvBio[R1, E1, B])(f: (A, B) => C): EnvBio[R1, E1, C] = EnvBio.map2(ea, eb)(f) def map3[A, B, C, D, R1 <: R, E1 >: E](ea: EnvBio[R, E, A], eb: EnvBio[R1, E1, B], ec: EnvBio[R1, E1, C])( f: (A, B, C) => D ): EnvBio[R1, E1, D] = EnvBio.map3(ea, eb, ec)(f) def parMap2[A, B, C, R1 <: R, E1 >: E](ea: EnvBio[R, E, A], eb: EnvBio[R1, E1, B])( f: (A, B) => C ): EnvBio[R1, E1, C] = EnvBio.parMap2(ea, eb)(f) def parMap3[A, B, C, D, R1 <: R, E1 >: E](ea: EnvBio[R, E, A], eb: EnvBio[R1, E1, B], ec: EnvBio[R1, E1, C])( f: (A, B, C) => D ): EnvBio[R1, E1, D] = EnvBio.parMap3(ea, eb, ec)(f) }
Example 154
Source File: EnvBio.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env.bio import monix.eval.Task import scala.concurrent.duration.FiniteDuration abstract class EnvBio[-R, +E, +A] { // todo should expose this to user? protected def runF(ctx: R): Task[A] final def run(ctx: R): Task[Either[E, A]] = runF(ctx).attempt.flatMap { case Left(UserError(err: E @unchecked)) => Task.pure(Left(err)) // todo erasure elimination? case Left(fatalErr) => Task.raiseError(fatalErr) case Right(value) => Task.pure(Right(value)) } def mapTask[B](f: Task[A] => Task[B]): EnvBio[R, E, B] = EnvBio.applyFatal(ctx => f(runF(ctx))) def map[B](f: A => B): EnvBio[R, E, B] = mapTask(_.map(f)) def flatMap[R1 <: R, E1 >: E, B](f: A => EnvBio[R1, E1, B]): EnvBio[R1, E1, B] = EnvBio.applyFatal(ctx => runF(ctx).flatMap(f(_).runF(ctx))) def >>[R1 <: R, E1 >: E, B](fb: => EnvBio[R1, E1, B]): EnvBio[R1, E1, B] = flatMap(_ => fb) def <<[R1 <: R, E1 >: E](fb: => EnvBio[R1, E1, Any]): EnvBio[R1, E1, A] = flatTap(_ => fb) def flatTap[R1 <: R, E1 >: E, B](f: A => EnvBio[R1, E1, B]): EnvBio[R1, E1, A] = flatMap(a => f(a).map(_ => a)) def map2[B, C, R1 <: R, E1 >: E](eb: EnvBio[R1, E1, B])(f: (A, B) => C): EnvBio[R1, E1, C] = flatMap(a => eb.map(f(a, _))) def map3[B, C, D, R1 <: R, E1 >: E](eb: EnvBio[R1, E1, B], ec: EnvBio[R1, E1, C])( f: (A, B, C) => D ): EnvBio[R1, E1, D] = map2(eb)((a, b) => f(a, b, _)).map2(ec)((fun, c) => fun(c)) def parMap2[B, C, R1 <: R, E1 >: E](eb: EnvBio[R1, E1, B])(f: (A, B) => C): EnvBio[R1, E1, C] = EnvBio.applyFatal(ctx => Task.parMap2(runF(ctx), eb.runF(ctx))(f)) def parMap3[B, C, D, R1 <: R, E1 >: E](eb: EnvBio[R1, E1, B], ec: EnvBio[R1, E1, C])( f: (A, B, C) => D ): EnvBio[R1, E1, D] = EnvBio.applyFatal(ctx => Task.parMap3(runF(ctx), eb.runF(ctx), ec.runF(ctx))(f)) def onErrorHandleWith[R1 <: R, E1, A1 >: A](f: E => EnvBio[R1, E1, A1]): EnvBio[R1, E1, A1] = EnvBio.applyFatal(ctx => runF(ctx).onErrorHandleWith { case UserError(e: E @unchecked) => f(e).runF(ctx) case t => Task.raiseError(t) } ) def onErrorHandle[A1 >: A](f: E => A1): EnvBio[R, Nothing, A1] = onErrorHandleWith(e => EnvBio.pure(f(e))) def onErrorRecoverWith[R1 <: R, E1 >: E, A2 >: A](f: PartialFunction[E, EnvBio[R1, E1, A2]]): EnvBio[R1, E1, A2] = EnvBio.applyFatal(ctx => runF(ctx).onErrorRecoverWith { case UserError(e: E @unchecked) if f.isDefinedAt(e) => f(e).runF(ctx) case t => Task.raiseError(t) } ) def onErrorRecover[A1 >: A](f: PartialFunction[E, A1]): EnvBio[R, E, A1] = onErrorRecoverWith(f.andThen(a1 => EnvBio.pure(a1))) def mapError[E1](f: E => E1): EnvBio[R, E1, A] = onErrorHandleWith(e => EnvBio.raiseError(f(e))) def tapError[R1 <: R, E1 >: E, A1 >: A](f: E => EnvBio[R1, E1, A1]): EnvBio[R1, E1, A1] = onErrorHandleWith(e => f(e) >> EnvBio.raiseError(e)) def tapHandle[R1 <: R, E1, A1 >: A](f: E => EnvBio[R1, E1, A1]): EnvBio[R1, E, A1] = onErrorHandleWith(e => f(e).mapError(_ => e)) def timed: EnvBio[R, E, (FiniteDuration, A)] = mapTask(_.timed) def foldWith[X, B, R1 <: R]( h: E => EnvBio[R1, X, B], f: A => EnvBio[R1, X, B] ): EnvBio[R1, X, B] = ctx => this.runF(ctx).attempt.flatMap { case Left(UserError(e: E @unchecked)) => h(e).runF(ctx) case Left(err) => Task.raiseError(err) case Right(x) => f(x).runF(ctx) } } object EnvBio extends EnvBioFunctions with EnvBioInstances {} private[bio] final case class UserError(err: Any) extends Throwable
Example 155
Source File: EnvSuite.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.env import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import tofu.{HasContextRun, RunContext, WithRun} import tofu.lift.{Lift, Unlift, UnliftIO} import scala.concurrent.duration._ class EnvSuite extends AnyFlatSpec with Matchers { "flatMap" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.flatMap(Env.pure) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } "map" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.map(identity) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } "map2" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.map2(Env.unit[Unit])((a, _) => a) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } "map3" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.map3(Env.unit[Unit], Env.unit[Unit])((a, _, _) => a) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } "parMap2" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.parMap2(Env.unit[Unit])((a, _) => a) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } "parMap3" should "not stack overflow on folding large collection" in { (0 to 100000).toList .foldLeft(Env.pure[Unit, Int](3)) { case (acc, _) => acc.parMap3(Env.unit[Unit], Env.unit[Unit])((a, _, _) => a) } .run(()) .runSyncUnsafe(Duration.Inf) shouldBe 3 } } object EnvSuite { def summonEnvInstances[E](): Unit = { implicitly[Lift[Task, Env[E, *]]] implicitly[Unlift[Task, Env[E, *]]] implicitly[UnliftIO[Env[E, *]]] implicitly[RunContext[Env[E, *]]] implicitly[HasContextRun[Env[E, *], Task, E]] implicitly[WithRun[Env[E, *], Task, E]] () } }
Example 156
Source File: TakeWhileInclusiveSuite.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.observable import monix.catnap.MVar import monix.eval.Task import monix.execution.Scheduler.Implicits.global import monix.reactive.Observable import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ class TakeWhileInclusiveSuite extends AnyFlatSpec with Matchers { private def writeElement[A](mvar: MVar[Task, Vector[A]])(a: A): Task[Unit] = mvar.take.flatMap(v => mvar.put(v :+ a)) private def inclusiveElements[A](obs: Observable[A])(p: A => Boolean): Task[(Vector[A], List[A])] = for { mvar <- MVar[Task].of(Vector.empty[A]) produced <- obs.doOnNext(writeElement(mvar)).takeWhileInclusive(p).toListL written <- mvar.read } yield (written, produced) "Observable.takeWhileInclusibe" should "produce and generate same elements" in { inclusiveElements(Observable.range(1, 100))(_ <= 10).runSyncUnsafe(Duration.Inf) shouldEqual ((Vector.range(1, 12), List.range(1, 12))) } }
Example 157
Source File: MonixAsyncHandler.scala From pulsar4s with Apache License 2.0 | 5 votes |
package com.sksamuel.pulsar4s.monixs import java.util.concurrent.CompletableFuture import com.sksamuel.pulsar4s.{AsyncHandler, ConsumerMessage, DefaultProducer, MessageId, Producer} import monix.eval.Task import org.apache.pulsar.client.api import org.apache.pulsar.client.api.Consumer import org.apache.pulsar.client.api.{ProducerBuilder, Reader, TypedMessageBuilder} import scala.compat.java8.FutureConverters import scala.concurrent.Future import scala.language.implicitConversions import scala.util.{Failure, Success, Try} class MonixAsyncHandler extends AsyncHandler[Task] { implicit def completableTToFuture[T](f: => CompletableFuture[T]): Future[T] = FutureConverters.toScala(f) implicit def completableVoidToTask(f: => CompletableFuture[Void]): Task[Unit] = Task.deferFuture(FutureConverters.toScala(f)).map(_ => ()) override def failed(e: Throwable): Task[Nothing] = Task.raiseError(e) override def createProducer[T](builder: ProducerBuilder[T]): Task[Producer[T]] = Task.deferFuture(FutureConverters.toScala(builder.createAsync())).map(new DefaultProducer(_)) override def send[T](t: T, producer: api.Producer[T]): Task[MessageId] = { Task.deferFuture { val future = producer.sendAsync(t) FutureConverters.toScala(future) }.map { id => MessageId.fromJava(id) } } override def receive[T](consumer: api.Consumer[T]): Task[ConsumerMessage[T]] = { Task.deferFuture { val future = consumer.receiveAsync() FutureConverters.toScala(future) }.map(ConsumerMessage.fromJava) } override def getLastMessageId[T](consumer: api.Consumer[T]): Task[MessageId] = { Task.deferFuture { val future = consumer.getLastMessageIdAsync() FutureConverters.toScala(future) }.map(MessageId.fromJava) } def unsubscribeAsync(consumer: api.Consumer[_]): Task[Unit] = consumer.unsubscribeAsync() override def close(producer: api.Producer[_]): Task[Unit] = producer.closeAsync() override def close(consumer: api.Consumer[_]): Task[Unit] = consumer.closeAsync() override def seekAsync(consumer: api.Consumer[_], messageId: MessageId): Task[Unit] = consumer.seekAsync(messageId) override def seekAsync(reader: api.Reader[_], messageId: MessageId): Task[Unit] = reader.seekAsync(messageId) override def seekAsync(reader: api.Reader[_], timestamp: Long): Task[Unit] = reader.seekAsync(timestamp) override def transform[A, B](t: Task[A])(fn: A => Try[B]): Task[B] = t.flatMap { a => fn(a) match { case Success(b) => Task.now(b) case Failure(e) => Task.raiseError(e) } } override def acknowledgeAsync[T](consumer: api.Consumer[T], messageId: MessageId): Task[Unit] = consumer.acknowledgeAsync(messageId) override def acknowledgeCumulativeAsync[T](consumer: api.Consumer[T], messageId: MessageId): Task[Unit] = consumer.acknowledgeCumulativeAsync(messageId) override def negativeAcknowledgeAsync[T](consumer: Consumer[T], messageId: MessageId): Task[Unit] = Task { consumer.negativeAcknowledge(messageId) } override def close(reader: Reader[_]): Task[Unit] = reader.closeAsync() override def flush(producer: api.Producer[_]): Task[Unit] = producer.flushAsync() override def nextAsync[T](reader: Reader[T]): Task[ConsumerMessage[T]] = Task.deferFuture(reader.readNextAsync()).map(ConsumerMessage.fromJava) override def send[T](builder: TypedMessageBuilder[T]): Task[MessageId] = Task.deferFuture(builder.sendAsync()).map(MessageId.fromJava) } object MonixAsyncHandler { implicit def handler: AsyncHandler[Task] = new MonixAsyncHandler }
Example 158
Source File: AsyncHttpClientLowLevelMonixWebsocketTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.asynchttpclient.monix import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.asynchttpclient.ws.{WebSocketListener, WebSocket => AHCWebSocket} import sttp.client._ import sttp.client.asynchttpclient.WebSocketHandler import sttp.client.impl.monix.convertMonixTaskToFuture import sttp.client.testing.ConvertToFuture import sttp.client.testing.websocket.LowLevelListenerWebSocketTest class AsyncHttpClientLowLevelMonixWebsocketTest extends LowLevelListenerWebSocketTest[Task, AHCWebSocket, WebSocketHandler] { override implicit val backend: SttpBackend[Task, Nothing, WebSocketHandler] = AsyncHttpClientMonixBackend().runSyncUnsafe() override implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture override def createHandler(_onTextFrame: String => Unit): WebSocketHandler[AHCWebSocket] = WebSocketHandler.fromListener(new WebSocketListener { override def onOpen(websocket: AHCWebSocket): Unit = {} override def onClose(websocket: AHCWebSocket, code: Int, reason: String): Unit = {} override def onError(t: Throwable): Unit = {} override def onTextFrame(payload: String, finalFragment: Boolean, rsv: Int): Unit = { _onTextFrame(payload) } }) override def sendText(ws: AHCWebSocket, t: String): Unit = ws.sendTextFrame(t).await() override def sendCloseFrame(ws: AHCWebSocket): Unit = ws.sendCloseFrame() }
Example 159
Source File: AsyncHttpClientMonixHttpTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.asynchttpclient.monix import java.util.concurrent.TimeoutException import monix.eval.Task import sttp.client._ import sttp.client.impl.monix.convertMonixTaskToFuture import sttp.client.testing.{CancelTest, ConvertToFuture, HttpTest} import monix.execution.Scheduler.Implicits.global import scala.concurrent.duration._ class AsyncHttpClientMonixHttpTest extends HttpTest[Task] with CancelTest[Task, Nothing] { override implicit val backend: SttpBackend[Task, Nothing, NothingT] = AsyncHttpClientMonixBackend().runSyncUnsafe() override implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture override def timeoutToNone[T](t: Task[T], timeoutMillis: Int): Task[Option[T]] = t.map(Some(_)) .timeout(timeoutMillis.milliseconds) .onErrorRecover { case _: TimeoutException => None } override def throwsExceptionOnUnsupportedEncoding = false }
Example 160
Source File: AsyncHttpClientHighLevelMonixWebsocketTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.asynchttpclient.monix import monix.eval.Task import monix.execution.Scheduler.Implicits.global import sttp.client._ import sttp.client.asynchttpclient.{AsyncHttpClientHighLevelWebsocketTest, WebSocketHandler} import sttp.client.impl.monix.{TaskMonadAsyncError, convertMonixTaskToFuture} import sttp.client.monad.MonadError import sttp.client.testing.ConvertToFuture import sttp.client.ws.WebSocket import scala.concurrent.duration._ class AsyncHttpClientHighLevelMonixWebsocketTest extends AsyncHttpClientHighLevelWebsocketTest[Task] { override implicit val backend: SttpBackend[Task, Nothing, WebSocketHandler] = AsyncHttpClientMonixBackend().runSyncUnsafe() override implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture override implicit val monad: MonadError[Task] = TaskMonadAsyncError override def createHandler: Option[Int] => Task[WebSocketHandler[WebSocket[Task]]] = MonixWebSocketHandler(_) override def eventually[T](interval: FiniteDuration, attempts: Int)(f: => Task[T]): Task[T] = { (Task.sleep(interval) >> f).onErrorRestart(attempts.toLong) } }
Example 161
Source File: PostSerializeJsonMonixAsyncHttpClientCirce.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.examples object PostSerializeJsonMonixAsyncHttpClientCirce extends App { import sttp.client._ import sttp.client.circe._ import sttp.client.asynchttpclient.monix._ import io.circe.generic.auto._ import monix.eval.Task case class Info(x: Int, y: String) val postTask = AsyncHttpClientMonixBackend().flatMap { implicit backend => val r = basicRequest .body(Info(91, "abc")) .post(uri"https://httpbin.org/post") r.send() .flatMap { response => Task(println(s"""Got ${response.code} response, body:\n${response.body}""")) } .guarantee(backend.close()) } import monix.execution.Scheduler.Implicits.global postTask.runSyncUnsafe() }
Example 162
Source File: WebsocketMonix.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.examples import monix.eval.Task import sttp.client._ import sttp.client.ws.{WebSocket, WebSocketResponse} import sttp.model.ws.WebSocketFrame import sttp.client.asynchttpclient.monix.{AsyncHttpClientMonixBackend, MonixWebSocketHandler} object WebsocketMonix extends App { import monix.execution.Scheduler.Implicits.global def useWebsocket(ws: WebSocket[Task]): Task[Unit] = { def send(i: Int) = ws.send(WebSocketFrame.text(s"Hello $i!")) val receive = ws.receiveText().flatMap(t => Task(println(s"RECEIVED: $t"))) send(1) *> send(2) *> receive *> receive *> ws.close } val websocketTask: Task[Unit] = AsyncHttpClientMonixBackend().flatMap { implicit backend => val response: Task[WebSocketResponse[WebSocket[Task]]] = basicRequest .get(uri"wss://echo.websocket.org") .openWebsocketF(MonixWebSocketHandler()) response .flatMap(r => useWebsocket(r.result)) .guarantee(backend.close()) } websocketTask.runSyncUnsafe() }
Example 163
Source File: MonixWebSocketHandler.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.httpclient.monix import monix.eval.Task import monix.execution.Scheduler import sttp.client.httpclient.WebSocketHandler import sttp.client.httpclient.internal.NativeWebSocketHandler import sttp.client.impl.monix.{MonixAsyncQueue, TaskMonadAsyncError} import sttp.client.ws.{WebSocket, WebSocketEvent} object MonixWebSocketHandler { val IncomingBufferCapacity = 2 // has to be at least 2 (opening frame + one data frame) def apply()(implicit s: Scheduler ): Task[WebSocketHandler[WebSocket[Task]]] = { Task { val queue = new MonixAsyncQueue[WebSocketEvent](Some(IncomingBufferCapacity)) NativeWebSocketHandler(queue, TaskMonadAsyncError) } } }
Example 164
Source File: HttpClientMonixBackend.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.httpclient.monix import java.io.InputStream import java.net.http.HttpRequest.BodyPublishers import java.net.http.{HttpClient, HttpRequest} import java.nio.ByteBuffer import cats.effect.Resource import monix.eval.Task import monix.execution.Scheduler import monix.reactive.Observable import org.reactivestreams.FlowAdapters import sttp.client.httpclient.HttpClientBackend.EncodingHandler import sttp.client.httpclient.{HttpClientAsyncBackend, HttpClientBackend, WebSocketHandler} import sttp.client.impl.monix.TaskMonadAsyncError import sttp.client.testing.SttpBackendStub import sttp.client.{FollowRedirectsBackend, SttpBackend, SttpBackendOptions} import scala.util.{Success, Try} class HttpClientMonixBackend private ( client: HttpClient, closeClient: Boolean, customizeRequest: HttpRequest => HttpRequest, customEncodingHandler: EncodingHandler )(implicit s: Scheduler) extends HttpClientAsyncBackend[Task, Observable[ByteBuffer]]( client, TaskMonadAsyncError, closeClient, customizeRequest, customEncodingHandler ) { override def streamToRequestBody(stream: Observable[ByteBuffer]): Task[HttpRequest.BodyPublisher] = { monad.eval(BodyPublishers.fromPublisher(FlowAdapters.toFlowPublisher(stream.toReactivePublisher))) } override def responseBodyToStream(responseBody: InputStream): Try[Observable[ByteBuffer]] = { Success( Observable .fromInputStream(Task.now(responseBody)) .map(ByteBuffer.wrap) .guaranteeCase(_ => Task(responseBody.close())) ) } } object HttpClientMonixBackend { private def apply( client: HttpClient, closeClient: Boolean, customizeRequest: HttpRequest => HttpRequest, customEncodingHandler: EncodingHandler )(implicit s: Scheduler ): SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler] = new FollowRedirectsBackend( new HttpClientMonixBackend(client, closeClient, customizeRequest, customEncodingHandler)(s) ) def apply( options: SttpBackendOptions = SttpBackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, customEncodingHandler: EncodingHandler = PartialFunction.empty )(implicit s: Scheduler = Scheduler.global ): Task[SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler]] = Task.eval( HttpClientMonixBackend( HttpClientBackend.defaultClient(options), closeClient = true, customizeRequest, customEncodingHandler )(s) ) def resource( options: SttpBackendOptions = SttpBackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, customEncodingHandler: EncodingHandler = PartialFunction.empty )(implicit s: Scheduler = Scheduler.global ): Resource[Task, SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler]] = Resource.make(apply(options, customizeRequest, customEncodingHandler))(_.close()) def usingClient( client: HttpClient, customizeRequest: HttpRequest => HttpRequest = identity, customEncodingHandler: EncodingHandler = PartialFunction.empty )(implicit s: Scheduler = Scheduler.global): SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler] = HttpClientMonixBackend(client, closeClient = false, customizeRequest, customEncodingHandler)(s) def stub: SttpBackendStub[Task, Observable[ByteBuffer], WebSocketHandler] = SttpBackendStub(TaskMonadAsyncError) }
Example 165
Source File: HttpClientHighLevelMonixWebsocketTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.httpclient.monix import java.nio.ByteBuffer import monix.eval.Task import monix.execution.Scheduler.Implicits.global import monix.reactive.Observable import sttp.client._ import sttp.client.httpclient.WebSocketHandler import sttp.client.impl.monix.{TaskMonadAsyncError, convertMonixTaskToFuture} import sttp.client.monad.MonadError import sttp.client.testing.ConvertToFuture import sttp.client.testing.websocket.HighLevelWebsocketTest import sttp.client.ws.WebSocket import sttp.client.testing.HttpTest.wsEndpoint import scala.concurrent.duration._ class HttpClientHighLevelMonixWebsocketTest extends HighLevelWebsocketTest[Task, WebSocketHandler] { implicit val backend: SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler] = HttpClientMonixBackend().runSyncUnsafe() implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture implicit val monad: MonadError[Task] = TaskMonadAsyncError override def createHandler: Option[Int] => Task[WebSocketHandler[WebSocket[Task]]] = _ => MonixWebSocketHandler() it should "handle backpressure correctly" in { basicRequest .get(uri"$wsEndpoint/ws/echo") .openWebsocketF(createHandler(None)) .flatMap { response => val ws = response.result send(ws, 1000) >> eventually(10.millis, 500) { ws.isOpen.map(_ shouldBe true) } } .toFuture() } override def eventually[T](interval: FiniteDuration, attempts: Int)(f: => Task[T]): Task[T] = { (Task.sleep(interval) >> f).onErrorRestart(attempts.toLong) } }
Example 166
Source File: OkHttpHighLevelMonixWebsocketTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.okhttp.monix import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.Assertion import sttp.client._ import sttp.client.impl.monix.{TaskMonadAsyncError, convertMonixTaskToFuture} import sttp.client.monad.MonadError import sttp.client.monad.syntax._ import sttp.client.okhttp.WebSocketHandler import sttp.client.okhttp.monix.internal.SendMessageException import sttp.client.testing.ConvertToFuture import sttp.client.testing.websocket.HighLevelWebsocketTest import sttp.client.ws.WebSocket import sttp.client.testing.HttpTest.wsEndpoint import scala.concurrent.duration._ class OkHttpHighLevelMonixWebsocketTest extends HighLevelWebsocketTest[Task, WebSocketHandler] { override implicit val backend: SttpBackend[Task, Nothing, WebSocketHandler] = OkHttpMonixBackend().runSyncUnsafe() override implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture override implicit val monad: MonadError[Task] = TaskMonadAsyncError override def createHandler: Option[Int] => Task[WebSocketHandler[WebSocket[Task]]] = MonixWebSocketHandler(_) it should "error if the endpoint is not a websocket" in { monad .handleError { basicRequest .get(uri"$wsEndpoint/echo") .openWebsocketF(createHandler(None)) .map(_ => fail: Assertion) } { case e: Exception => (e shouldBe a[SttpClientException.ReadException]).unit } .toFuture() } it should "error if incoming messages overflow the buffer" in { basicRequest .get(uri"$wsEndpoint/ws/echo") .openWebsocketF(createHandler(Some(3))) .flatMap { response => val ws = response.result send(ws, 1000) >> eventually(10 millis, 400)(ws.isOpen.map(_ shouldBe false)) } .onErrorRecover { case _: SendMessageException => succeed } .toFuture() } override def eventually[T](interval: FiniteDuration, attempts: Int)(f: => Task[T]): Task[T] = { (Task.sleep(interval) >> f).onErrorRestart(attempts) } }
Example 167
Source File: MonixAsyncQueue.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.impl.monix import monix.eval.Task import sttp.model.ws.WebSocketBufferFull import monix.execution.{Scheduler, AsyncQueue => MAsyncQueue} import sttp.client.ws.internal.AsyncQueue class MonixAsyncQueue[A](bufferCapacity: Option[Int])(implicit s: Scheduler) extends AsyncQueue[Task, A] { private val queue = bufferCapacity match { case Some(capacity) => MAsyncQueue.bounded[A](capacity) case None => MAsyncQueue.unbounded[A]() } override def offer(t: A): Unit = { if (!queue.tryOffer(t)) { throw new WebSocketBufferFull() } } override def poll: Task[A] = Task.deferFuture(queue.poll()) }
Example 168
Source File: TaskMonadAsyncError.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.impl.monix import monix.eval.Task import sttp.client.monad.{Canceler, MonadAsyncError} import scala.util.{Failure, Success} object TaskMonadAsyncError extends MonadAsyncError[Task] { override def unit[T](t: T): Task[T] = Task.now(t) override def map[T, T2](fa: Task[T])(f: (T) => T2): Task[T2] = fa.map(f) override def flatMap[T, T2](fa: Task[T])(f: (T) => Task[T2]): Task[T2] = fa.flatMap(f) override def async[T](register: (Either[Throwable, T] => Unit) => Canceler): Task[T] = Task.cancelable { cb => val canceler = register { case Left(t) => cb(Failure(t)) case Right(t) => cb(Success(t)) } Task(canceler.cancel()) } override def error[T](t: Throwable): Task[T] = Task.raiseError(t) override protected def handleWrappedError[T](rt: Task[T])(h: PartialFunction[Throwable, Task[T]]): Task[T] = rt.onErrorRecoverWith(h) override def eval[T](t: => T): Task[T] = Task(t) }
Example 169
Source File: MonixStreamingTest.scala From sttp with Apache License 2.0 | 5 votes |
package sttp.client.impl.monix import java.nio.ByteBuffer import monix.eval.Task import monix.reactive.Observable import sttp.client.testing.ConvertToFuture import sttp.client.testing.streaming.StreamingTest abstract class MonixStreamingTest extends StreamingTest[Task, Observable[ByteBuffer]] { override implicit val convertToFuture: ConvertToFuture[Task] = convertMonixTaskToFuture override def bodyProducer(chunks: Iterable[Array[Byte]]): Observable[ByteBuffer] = Observable .fromIterable(chunks) .map(ByteBuffer.wrap) override def bodyConsumer(stream: Observable[ByteBuffer]): Task[String] = stream .flatMap(v => Observable.fromIterable(v.array())) .toListL .map(bs => new String(bs.toArray, "utf8")) }
Example 170
Source File: MonixMtlInstances.scala From meow-mtl with MIT License | 5 votes |
package com.olegpy.meow.internal import cats.Semigroup import cats.syntax.semigroup._ import cats.{Applicative, Functor, Monad} import cats.mtl.{ApplicativeLocal, DefaultFunctorTell, DefaultMonadState} import monix.eval.TaskLocal import monix.eval.Task private[meow] object MonixMtlInstances { class TaskLocalApplicativeLocal[E](taskLocal: TaskLocal[E]) extends ApplicativeLocal[Task, E] { override def local[A](f: E => E)(fa: Task[A]): Task[A] = taskLocal.bindL(taskLocal.read map f)(fa) override def scope[A](e: E)(fa: Task[A]): Task[A] = taskLocal.bind(e)(fa) override val applicative: Applicative[Task] = Task.catsAsync override def ask: Task[E] = taskLocal.read override def reader[A](f: E => A): Task[A] = ask.map(f) } class TaskLocalMonadState[S](taskLocal: TaskLocal[S]) extends DefaultMonadState[Task, S] { override val monad: Monad[Task] = Task.catsAsync override def get: Task[S] = taskLocal.read override def set(s: S): Task[Unit] = taskLocal.write(s) } class TaskLocalFunctorTell[E: Semigroup](taskLocal: TaskLocal[E]) extends DefaultFunctorTell[Task, E] { override val functor: Functor[Task] = Task.catsAsync override def tell(l: E): Task[Unit] = taskLocal.read.flatMap(e => taskLocal.write(e |+| l)) } }
Example 171
Source File: RouteGuideMonixService.scala From grpcexample with MIT License | 5 votes |
package io.grpc.routeguide import java.util.concurrent.TimeUnit.NANOSECONDS import java.util.logging.Logger import concurrency.AtomicRef import monix.eval.Task import monix.reactive.Observable class RouteGuideMonixService(features: Seq[Feature]) extends RouteGuideGrpcMonix.RouteGuide { val logger: Logger = Logger.getLogger(classOf[RouteGuideMonixService].getName) private val routeNotes: AtomicRef[Map[Point, Seq[RouteNote]]] = new AtomicRef(Map.empty) override def routeChat(notes: Observable[RouteNote]): Observable[RouteNote] = notes.flatMap { note => addNote(note) Observable.fromIterable(getNotes(note.getLocation)) } private def findFeature(point: Point): Feature = { features.find { feature => feature.getLocation.latitude == point.latitude && feature.getLocation.longitude == point.longitude } getOrElse new Feature(location = Some(point)) } private def getNotes(point: Point): Seq[RouteNote] = { routeNotes.get.getOrElse(point, Seq.empty) } private def addNote(note: RouteNote): Unit = { routeNotes.updateAndGet { notes => val existingNotes = notes.getOrElse(note.getLocation, Seq.empty) val updatedNotes = existingNotes :+ note notes + (note.getLocation -> updatedNotes) } } }
Example 172
Source File: MonixStreams.scala From neotypes with MIT License | 5 votes |
package neotypes.monix.stream import monix.eval.Task import monix.reactive.Observable trait MonixStreams { implicit final val monixStream: neotypes.Stream.Aux[Observable, Task] = new neotypes.Stream[Observable] { override final type F[T] = Task[T] override final def init[T](value: () => Task[Option[T]]): Observable[T] = Observable .repeatEvalF(Task.suspend(value())) .takeWhile(option => option.isDefined) .collect { case Some(t) => t } override final def onComplete[T](s: Observable[T])(f: => Task[Unit]): Observable[T] = s.guarantee(f) override final def fToS[T](f: Task[Observable[T]]): Observable[T] = Observable.fromTask(f).flatten } }
Example 173
Source File: Monix.scala From neotypes with MIT License | 5 votes |
package neotypes.monix import cats.effect.{ExitCase, Resource} import monix.eval.Task trait Monix { implicit final def monixAsync: neotypes.Async.Aux[Task, Monix.TaskResource] = Monix.instance } object Monix { private[neotypes] final type TaskResource[A] = Resource[Task, A] private final val instance: neotypes.Async.Aux[Task, TaskResource] = new neotypes.Async[Task] { override final type R[A] = Resource[Task, A] override final def async[T](cb: (Either[Throwable, T] => Unit) => Unit): Task[T] = Task.async(cb) override final def delay[A](t: => A): Task[A] = Task.delay(t) override final def failed[T](e: Throwable): Task[T] = Task.raiseError(e) override final def flatMap[T, U](m: Task[T])(f: T => Task[U]): Task[U] = m.flatMap(f) override final def guarantee[A, B](fa: Task[A]) (f: A => Task[B]) (finalizer: (A, Option[Throwable]) => Task[Unit]): Task[B] = Resource.makeCase(fa) { case (a, ExitCase.Completed | ExitCase.Canceled) => finalizer(a, None) case (a, ExitCase.Error(ex)) => finalizer(a, Some(ex)) }.use(f) override final def map[T, U](m: Task[T])(f: T => U): Task[U] = m.map(f) override final def recoverWith[T, U >: T](m: Task[T])(f: PartialFunction[Throwable, Task[U]]): Task[U] = m.onErrorRecoverWith(f) override final def resource[A](input: => A)(close: A => Task[Unit]): Resource[Task, A] = Resource.make(Task.delay(input))(close) } }
Example 174
Source File: GrpcMonix.scala From grpcmonix with MIT License | 5 votes |
package grpcmonix import com.google.common.util.concurrent.ListenableFuture import io.grpc.stub.StreamObserver import monix.eval.{Callback, Task} import monix.execution.Ack.{Continue, Stop} import monix.execution.{Ack, Scheduler} import monix.reactive.Observable import monix.reactive.observables.ObservableLike.{Operator, Transformer} import monix.reactive.observers.Subscriber import monix.reactive.subjects.PublishSubject import org.reactivestreams.{Subscriber => SubscriberR} import scalapb.grpc.Grpc import scala.concurrent.Future object GrpcMonix { type GrpcOperator[I, O] = StreamObserver[O] => StreamObserver[I] def guavaFutureToMonixTask[T](future: ListenableFuture[T]): Task[T] = Task.deferFuture { Grpc.guavaFuture2ScalaFuture(future) } def grpcOperatorToMonixOperator[I,O](grpcOperator: GrpcOperator[I,O]): Operator[I,O] = { outputSubsriber: Subscriber[O] => val outputObserver: StreamObserver[O] = monixSubscriberToGrpcObserver(outputSubsriber) val inputObserver: StreamObserver[I] = grpcOperator(outputObserver) grpcObserverToMonixSubscriber(inputObserver, outputSubsriber.scheduler) } def monixSubscriberToGrpcObserver[T](subscriber: Subscriber[T]): StreamObserver[T] = new StreamObserver[T] { override def onError(t: Throwable): Unit = subscriber.onError(t) override def onCompleted(): Unit = subscriber.onComplete() override def onNext(value: T): Unit = subscriber.onNext(value) } def reactiveSubscriberToGrpcObserver[T](subscriber: SubscriberR[_ >: T]): StreamObserver[T] = new StreamObserver[T] { override def onError(t: Throwable): Unit = subscriber.onError(t) override def onCompleted(): Unit = subscriber.onComplete() override def onNext(value: T): Unit = subscriber.onNext(value) } def grpcObserverToMonixSubscriber[T](observer: StreamObserver[T], s: Scheduler): Subscriber[T] = new Subscriber[T] { override implicit def scheduler: Scheduler = s override def onError(t: Throwable): Unit = observer.onError(t) override def onComplete(): Unit = observer.onCompleted() override def onNext(value: T): Future[Ack] = try { observer.onNext(value) Continue } catch { case t: Throwable => observer.onError(t) Stop } } def grpcObserverToMonixCallback[T](observer: StreamObserver[T]): Callback[T] = new Callback[T] { override def onError(t: Throwable): Unit = observer.onError(t) override def onSuccess(value: T): Unit = { observer.onNext(value) observer.onCompleted() } } def liftByGrpcOperator[I, O](observable: Observable[I], operator: GrpcOperator[I, O]): Observable[O] = observable.liftByOperator( grpcOperatorToMonixOperator(operator) ) def unliftByTransformer[I, O](transformer: Transformer[I, O], subscriber: Subscriber[O]): Subscriber[I] = new Subscriber[I] { private[this] val subject = PublishSubject[I]() subject.transform(transformer).subscribe(subscriber) override implicit def scheduler: Scheduler = subscriber.scheduler override def onError(t: Throwable): Unit = subject.onError(t) override def onComplete(): Unit = subject.onComplete() override def onNext(value: I): Future[Ack] = subject.onNext(value) } }
Example 175
Source File: Server.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp import cats.Parallel import cats.effect.Effect import com.smartbackpackerapp.http.auth.JwtTokenAuthMiddleware import fs2.StreamApp.ExitCode import fs2.{Scheduler, Stream, StreamApp} import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.http4s.client.blaze.Http1Client import org.http4s.server.blaze.BlazeBuilder object Server extends HttpServer[Task, Task.Par] class HttpServer[F[_], G[_]](implicit F: Effect[F], P: Parallel[F, G]) extends StreamApp[F] { // Workaround until something like mirror comes out: https://github.com/typelevel/cats/pull/2019 implicit val parallel: Parallel[F, F] = P.asInstanceOf[Parallel[F, F]] private lazy val ApiToken: F[Option[String]] = F.delay(sys.env.get("SB_API_TOKEN")) override def stream(args: List[String], requestShutdown: F[Unit]): Stream[F, ExitCode] = Scheduler(corePoolSize = 2).flatMap { implicit scheduler => for { httpClient <- Http1Client.stream[F]() ctx = new Module[F](httpClient) _ <- Stream.eval(ctx.migrateDb) _ <- Stream.eval(ctx.startMetricsReporter) apiToken <- Stream.eval(ApiToken) authMiddleware <- Stream.eval(JwtTokenAuthMiddleware[F](apiToken)) exitCode <- BlazeBuilder[F] .bindHttp(sys.env.getOrElse("PORT", "8080").toInt, "0.0.0.0") .mountService(authMiddleware(ctx.httpEndpointsWithMetrics)) .serve } yield exitCode } }
Example 176
Source File: DestinationInfoHttpEndpointSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.http import cats.Parallel import cats.syntax.option._ import com.smartbackpackerapp.common.TaskAssertion import com.smartbackpackerapp.config.SBConfiguration import com.smartbackpackerapp.http.Http4sUtils._ import com.smartbackpackerapp.model.{Country, CountryCode, CountryName, Currency, VisaNotRequired, VisaRequirementsData} import com.smartbackpackerapp.repository.algebra.VisaRequirementsRepository import com.smartbackpackerapp.service.{AbstractExchangeRateService, CurrencyExchangeDTO, DestinationInfoService} import monix.eval.Task import org.http4s.{HttpService, Query, Request, Status, Uri} import org.scalatest.prop.PropertyChecks import org.scalatest.{FlatSpecLike, Matchers} class DestinationInfoHttpEndpointSpec extends FlatSpecLike with Matchers with DestinationInfoHttpEndpointFixture { forAll(examples) { (from, to, expectedStatus, expectedCountry, expectedVisa) => it should s"retrieve visa requirements from $from to $to" in TaskAssertion { val request = Request[Task](uri = Uri(path = s"/$ApiVersion/traveling/$from/to/$to", query = Query(("baseCurrency", Some("EUR"))))) httpService(request).value.map { task => task.fold(fail("Empty response")){ response => response.status should be (expectedStatus) val body = response.body.asString assert(body.contains(expectedCountry)) assert(body.contains(expectedVisa)) } } } } } trait DestinationInfoHttpEndpointFixture extends PropertyChecks { val examples = Table( ("from", "code", "expectedStatus","expectedCountry", "expectedVisa"), ("AR", "GB", Status.Ok, "United Kingdom", "VisaNotRequired"), ("AR", "KO", Status.NotFound, "Country not found", """{"code":"100","error":"Country not found KO"}"""), ("AR", "AR", Status.BadRequest, "Countries must be different", """{"code":"101","error":"Countries must be different!"}""") ) private val repo = new VisaRequirementsRepository[Task] { override def findVisaRequirements(from: CountryCode, to: CountryCode): Task[Option[VisaRequirementsData]] = Task { if (to.value == "KO") none[VisaRequirementsData] else VisaRequirementsData( from = Country(CountryCode("AR"), CountryName("Argentina"), Currency("ARS")), to = Country(CountryCode("GB"), CountryName("United Kingdom"), Currency("GBP")), visaCategory = VisaNotRequired, description = "90 days within any 180 day period" ).some } } private lazy val sbConfig = new SBConfiguration[Task] private val rateService = new AbstractExchangeRateService[Task](sbConfig) { override protected def retrieveExchangeRate(uri: String): Task[CurrencyExchangeDTO] = Task { CurrencyExchangeDTO("EUR", "", Map("RON" -> 4.59)) } } private implicit val errorHandler = new HttpErrorHandler[Task] private implicit val parallel: Parallel[Task, Task] = Parallel[Task, Task.Par].asInstanceOf[Parallel[Task, Task]] val httpService: HttpService[Task] = taskMiddleware( new DestinationInfoHttpEndpoint( new DestinationInfoService[Task](sbConfig, repo, rateService) ).service ) }
Example 177
Source File: Http4sUtils.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.http import cats.{Applicative, Monad} import cats.data.{Kleisli, OptionT} import cats.effect.IO import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.http4s.server.AuthMiddleware import org.http4s.{EntityBody, Request} import scala.concurrent.Await import scala.concurrent.duration.Duration object Http4sUtils { private def authUser[F[_]](implicit F: Applicative[F]): Kleisli[OptionT[F, ?], Request[F], String] = Kleisli(_ => OptionT.liftF(F.pure("access_token"))) def middleware[F[_]: Monad]: AuthMiddleware[F, String] = AuthMiddleware.apply[F, String](authUser) val taskMiddleware: AuthMiddleware[Task, String] = middleware[Task] val ioMiddleware: AuthMiddleware[IO, String] = middleware[IO] implicit class ByteVector2String(body: EntityBody[IO]) { def asString: String = { val array = body.compile.toVector.unsafeRunSync().toArray new String(array.map(_.toChar)) } } implicit class ByteVector2StringTask(body: EntityBody[Task]) { def asString: String = { val array = Await.result(body.compile.toVector.runAsync, Duration.Inf).toArray new String(array.map(_.toChar)) } } }
Example 178
Source File: DestinationInfoServiceSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.Parallel import cats.data.EitherT import cats.syntax.option._ import com.smartbackpackerapp.common.TaskAssertion import com.smartbackpackerapp.config.SBConfiguration import com.smartbackpackerapp.model._ import com.smartbackpackerapp.repository.algebra.VisaRequirementsRepository import monix.eval.Task import org.scalatest.{FlatSpecLike, Matchers} class DestinationInfoServiceSpec extends FlatSpecLike with Matchers { private lazy val sbConfig = new SBConfiguration[Task] private val repo = new VisaRequirementsRepository[Task] { override def findVisaRequirements(from: CountryCode, to: CountryCode): Task[Option[VisaRequirementsData]] = Task { VisaRequirementsData( from = Country(CountryCode("AR"), CountryName("Argentina"), Currency("ARS")), to = Country(CountryCode("RO"), CountryName("Romania"), Currency("RON")), visaCategory = VisaNotRequired, description = "90 days within any 180 day period" ).some } } private val rateService = new AbstractExchangeRateService[Task](sbConfig) { override protected def retrieveExchangeRate(uri: String): Task[CurrencyExchangeDTO] = Task { CurrencyExchangeDTO("EUR", "", Map("RON" -> 4.59)) } } private implicit val parallel: Parallel[Task, Task] = Parallel[Task, Task.Par].asInstanceOf[Parallel[Task, Task]] private val service = new DestinationInfoService[Task](sbConfig, repo, rateService) it should "retrieve destination information" in TaskAssertion { EitherT(service.find(CountryCode("AR"), CountryCode("RO"), Currency("EUR"))).map { info => info.countryCode.value should be ("RO") info.countryName.value should be ("Romania") info.exchangeRate should be (ExchangeRate(Currency("EUR"), Currency("RON"), 4.59)) info.visaRequirements should be (VisaRequirements(VisaNotRequired, "90 days within any 180 day period")) }.value } it should "validate countries" in TaskAssertion { EitherT(service.find(CountryCode("AR"), CountryCode("AR"), Currency("EUR"))).leftMap { error => error should be (CountriesMustBeDifferent) }.value } }
Example 179
Source File: MonixExample.scala From korolev with Apache License 2.0 | 5 votes |
import korolev.Context import korolev.akka._ import korolev.server.{KorolevServiceConfig, StateLoader} import korolev.state.javaSerialization._ import korolev.monix._ import monix.eval.Task import monix.execution.Scheduler.Implicits.global object MonixExample extends SimpleAkkaHttpKorolevApp { val ctx = Context[Task, Option[String], Any] import ctx._ import levsha.dsl._ import html._ private val aInput = elementId() private val bInput = elementId() def service: AkkaHttpService = akkaHttpService { KorolevServiceConfig[Task, Option[String], Any]( stateLoader = StateLoader.default(None), document = maybeResult => optimize { Html( body( form( input(aInput, `type` := "number", event("input")(onChange)), span("+"), input(bInput, `type` := "number", event("input")(onChange)), span("="), maybeResult.map(result => span(result)), ) ) ) } ) } private def onChange(access: Access) = for { a <- access.valueOf(aInput) b <- access.valueOf(bInput) _ <- if (a.trim.isEmpty || b.trim.isEmpty) Task.unit else access.transition(_ => Some((a.toInt + b.toInt).toString)) } yield () }
Example 180
Source File: TagRoutes.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.http.scaladsl.model.StatusCodes.{Created, OK} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.iam.client.types._ import ch.epfl.bluebrain.nexus.kg.config.AppConfig import ch.epfl.bluebrain.nexus.kg.config.Contexts.tagCtxUri import ch.epfl.bluebrain.nexus.kg.config.Vocabulary.nxv import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives._ import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._ import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources._ import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import ch.epfl.bluebrain.nexus.rdf.implicits._ import io.circe.syntax._ import io.circe.{Encoder, Json} import kamon.Kamon import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class TagRoutes private[routes] (resourceType: String, tags: Tags[Task], schema: Ref, write: Permission)( implicit acls: AccessControlLists, caller: Caller, project: Project, config: AppConfig ) { def routes(id: AbsoluteIri): Route = // Consume the tag segment pathPrefix("tags") { concat( // Create tag (post & parameter("rev".as[Long]) & pathEndOrSingleSlash) { rev => operationName(opName) { (hasPermission(write) & projectNotDeprecated) { entity(as[Json]) { source => Kamon.currentSpan().tag("resource.operation", "create") complete(tags.create(Id(project.ref, id), rev, source, schema).value.runWithStatus(Created)) } } } }, // Fetch a tag (get & projectNotDeprecated & pathEndOrSingleSlash) { operationName(opName) { hasPermission(read).apply { parameter("rev".as[Long].?) { case Some(rev) => complete(tags.fetch(Id(project.ref, id), rev, schema).value.runWithStatus(OK)) case _ => complete(tags.fetch(Id(project.ref, id), schema).value.runWithStatus(OK)) } } } } ) } private implicit def tagsEncoder: Encoder[TagSet] = Encoder.instance(tags => Json.obj(nxv.tags.prefix -> Json.arr(tags.map(_.asJson).toSeq: _*)).addContext(tagCtxUri)) private def opName: String = resourceType match { case "resources" => s"/${config.http.prefix}/resources/{org}/{project}/{schemaId}/{id}/tags" case _ => s"/${config.http.prefix}/$resourceType/{org}/{project}/{id}/tags" } }
Example 181
Source File: Clients.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import ch.epfl.bluebrain.nexus.admin.client.AdminClient import ch.epfl.bluebrain.nexus.commons.es.client.ElasticSearchClient import ch.epfl.bluebrain.nexus.commons.http.HttpClient import ch.epfl.bluebrain.nexus.commons.http.HttpClient.UntypedHttpClient import ch.epfl.bluebrain.nexus.commons.search.QueryResults import ch.epfl.bluebrain.nexus.commons.sparql.client.BlazegraphClient import ch.epfl.bluebrain.nexus.iam.client.IamClient import ch.epfl.bluebrain.nexus.storage.client.StorageClient import io.circe.Json import monix.eval.Task final case class Clients[F[_]]()( implicit val sparql: BlazegraphClient[F], val elasticSearch: ElasticSearchClient[F], val admin: AdminClient[F], val iam: IamClient[F], val defaultRemoteStorage: StorageClient[F], val rsSearch: HttpClient[F, QueryResults[Json]], val http: UntypedHttpClient[Task], val uclJson: HttpClient[Task, Json] ) object Clients { implicit def esClient[F[_]](implicit clients: Clients[F]): ElasticSearchClient[F] = clients.elasticSearch implicit def sparqlClient[F[_]](implicit clients: Clients[F]): BlazegraphClient[F] = clients.sparql }
Example 182
Source File: ArchiveRoutes.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.http.scaladsl.model.StatusCodes.{Created, OK} import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.model.{HttpEntity, MediaTypes} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.iam.client.types._ import ch.epfl.bluebrain.nexus.kg.KgError.{InvalidOutputFormat, UnacceptedResponseContentType} import ch.epfl.bluebrain.nexus.kg.archives.Archive._ import ch.epfl.bluebrain.nexus.kg.config.AppConfig import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives.hasPermission import ch.epfl.bluebrain.nexus.kg.directives.PathDirectives._ import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._ import ch.epfl.bluebrain.nexus.kg.directives.QueryDirectives.outputFormat import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources._ import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.Tar import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import io.circe.Json import kamon.instrumentation.akka.http.TracingDirectives.operationName import monix.eval.Task import monix.execution.Scheduler.Implicits.global class ArchiveRoutes private[routes] (archives: Archives[Task])( implicit acls: AccessControlLists, project: Project, caller: Caller, config: AppConfig ) { private val responseType = MediaTypes.`application/x-tar` def routes(id: AbsoluteIri): Route = { val resId = Id(project.ref, id) concat( // Create archive (put & pathEndOrSingleSlash) { operationName(s"/${config.http.prefix}/archives/{org}/{project}/{id}") { (hasPermission(write) & projectNotDeprecated) { entity(as[Json]) { source => complete(archives.create(resId, source).value.runWithStatus(Created)) } } } }, // Fetch archive (get & outputFormat(strict = true, Tar) & pathEndOrSingleSlash) { case Tar => getArchive(resId) case format: NonBinaryOutputFormat => getResource(resId)(format) case other => failWith(InvalidOutputFormat(other.toString)) } ) } private def getResource(resId: ResId)(implicit format: NonBinaryOutputFormat): Route = completeWithFormat(archives.fetch(resId).value.runWithStatus(OK)) private def getArchive(resId: ResId): Route = { parameter("ignoreNotFound".as[Boolean] ? false) { ignoreNotFound => onSuccess(archives.fetchArchive(resId, ignoreNotFound).value.runToFuture) { case Right(source) => headerValueByType[Accept](()) { accept => if (accept.mediaRanges.exists(_.matches(responseType))) complete(HttpEntity(responseType, source)) else failWith( UnacceptedResponseContentType( s"File Media Type '$responseType' does not match the Accept header value '${accept.mediaRanges.mkString(", ")}'" ) ) } case Left(err) => complete(err) } } } } object ArchiveRoutes { final def apply(archives: Archives[Task])( implicit acls: AccessControlLists, caller: Caller, project: Project, config: AppConfig ): ArchiveRoutes = new ArchiveRoutes(archives) }
Example 183
Source File: Status.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.routes import akka.Done import akka.actor.ActorSystem import akka.cluster.{Cluster, MemberStatus} import akka.event.Logging import akka.persistence.cassandra.CassandraPluginConfig import akka.persistence.cassandra.session.scaladsl.CassandraSession import ch.epfl.bluebrain.nexus.kg.config.AppConfig.PersistenceConfig import monix.eval.Task import scala.concurrent.Future sealed trait Status { def check: Task[Boolean] } object Status { class CassandraStatus(implicit as: ActorSystem, persistence: PersistenceConfig) extends Status { implicit val ec = as.dispatcher private val log = Logging(as, "CassandraHeathCheck") private val config = new CassandraPluginConfig(as, as.settings.config.getConfig(persistence.journalPlugin)) private val (p, s) = (config.sessionProvider, config.sessionSettings) private val session = new CassandraSession(as, p, s, ec, log, "health", _ => Future.successful(Done.done())) private val query = s"SELECT now() FROM ${config.keyspace}.messages;" override def check: Task[Boolean] = Task.deferFuture(session.selectOne(query).map(_ => true).recover { case err => log.error("Error while attempting to query for health check", err) false }) } class ClusterStatus(cluster: Cluster) extends Status { override def check: Task[Boolean] = Task.pure( !cluster.isTerminated && cluster.state.leader.isDefined && cluster.state.members.nonEmpty && !cluster.state.members.exists(_.status != MemberStatus.Up) && cluster.state.unreachable.isEmpty ) } }
Example 184
Source File: MigrateV12ToV13.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.{EventEnvelope, NoOffset, PersistenceQuery} import cats.implicits._ import ch.epfl.bluebrain.nexus.admin.client.AdminClient import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.commons.test.Resources import ch.epfl.bluebrain.nexus.iam.client.types._ import ch.epfl.bluebrain.nexus.kg.config.AppConfig import ch.epfl.bluebrain.nexus.kg.config.Vocabulary.nxv import ch.epfl.bluebrain.nexus.kg.resources.Event.{Created, Updated} import ch.epfl.bluebrain.nexus.kg.resources.{OrganizationRef, ResId, Views} import com.typesafe.scalalogging.Logger import io.circe.Json import io.circe.parser.parse import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import scala.concurrent.Future object MigrateV12ToV13 extends Resources { private val log = Logger[MigrateV12ToV13.type] private val newMapping = jsonContentOf("/elasticsearch/mapping.json") private val defaultEsId = nxv.defaultElasticSearchIndex.value private implicit val mockedAcls: AccessControlLists = AccessControlLists.empty def migrate( views: Views[Task], adminClient: AdminClient[Task] )(implicit config: AppConfig, as: ActorSystem, sc: Scheduler, pm: CanBlock): Unit = { implicit val token: Option[AuthToken] = config.iam.serviceAccountToken def checkAndUpdateMapping(id: ResId, rev: Long, source: Json)( implicit project: Project, caller: Caller ): Task[Unit] = { source.hcursor.get[String]("mapping").flatMap(parse) match { case Left(err) => log.error(s"Error while fetching mapping for view id ${id.show}. Reason: '$err'") Task.unit case Right(mapping) if mapping == newMapping => Task.unit case _ => views.update(id, rev, source deepMerge Json.obj("mapping" -> newMapping)).value.flatMap { case Left(err) => log.error(s"Error updating the view with id '${id.show}' and rev '$rev'. Reason: '$err'") Task.unit case _ => log.info(s"View with id '${id.show}' and rev '$rev' was successfully updated.") Task.unit } } } def fetchProject(orgRef: OrganizationRef, id: ResId)(f: Project => Task[Unit]): Task[Unit] = { adminClient.fetchProject(orgRef.id, id.parent.id).flatMap { case Some(project) => f(project) case None => log.error(s"Project with id '${id.parent.id}' was not found for view with id '${id.show}'") Task.unit } } log.info("Migrating views mappings.") val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) Task .fromFuture { pq.currentEventsByTag(s"type=${nxv.ElasticSearchView.value.asString}", NoOffset) .mapAsync(1) { case EventEnvelope(_, _, _, Created(id, orgRef, _, _, source, _, subject)) if id.value == defaultEsId => fetchProject(orgRef, id) { project => checkAndUpdateMapping(id, 1L, source)(project, Caller(subject, Set(subject))) }.runToFuture case EventEnvelope(_, _, _, Updated(id, orgRef, rev, _, source, _, subject)) if id.value == defaultEsId => fetchProject(orgRef, id) { project => checkAndUpdateMapping(id, rev, source)(project, Caller(subject, Set(subject))) }.runToFuture case _ => Future.unit } .runFold(0) { case (acc, _) => if (acc % 10 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .map(_ => ()) } .runSyncUnsafe() log.info("Finished migrating views mappings.") } }
Example 185
Source File: AuthDirectives.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.directives import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.directives.FutureDirectives.onComplete import akka.http.scaladsl.server.{Directive0, Directive1} import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.iam.client.types._ import ch.epfl.bluebrain.nexus.iam.client.{IamClient, IamClientError} import ch.epfl.bluebrain.nexus.kg.KgError.{AuthenticationFailed, AuthorizationFailed, InternalError} import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler.Implicits.global import scala.util.{Failure, Success} object AuthDirectives { private val logger = Logger[this.type] def extractCaller(implicit iam: IamClient[Task], token: Option[AuthToken]): Directive1[Caller] = onComplete(iam.identities.runToFuture).flatMap { case Success(caller) => provide(caller) case Failure(_: IamClientError.Unauthorized) => failWith(AuthenticationFailed) case Failure(_: IamClientError.Forbidden) => failWith(AuthorizationFailed) case Failure(err) => val message = "Error when trying to extract the subject" logger.error(message, err) failWith(InternalError(message)) } }
Example 186
Source File: ProjectAttributesCoordinator.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.async import akka.actor.{ActorRef, ActorSystem} import cats.effect.Async import cats.implicits._ import ch.epfl.bluebrain.nexus.admin.client.types.Project import ch.epfl.bluebrain.nexus.kg.async.ProjectAttributesCoordinatorActor.Msg._ import ch.epfl.bluebrain.nexus.kg.cache.ProjectCache import ch.epfl.bluebrain.nexus.kg.config.AppConfig import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef import ch.epfl.bluebrain.nexus.kg.resources.syntax._ import ch.epfl.bluebrain.nexus.kg.resources.{Files, OrganizationRef} import ch.epfl.bluebrain.nexus.kg.storage.Storage.StorageOperations.FetchAttributes import ch.epfl.bluebrain.nexus.sourcing.projections.Projections import monix.eval.Task def stop(projectRef: ProjectRef): F[Unit] = { ref ! Stop(projectRef.id) F.unit } } object ProjectAttributesCoordinator { def apply(files: Files[Task], projectCache: ProjectCache[Task])( implicit config: AppConfig, fetchAttributes: FetchAttributes[Task], as: ActorSystem, P: Projections[Task, String] ): ProjectAttributesCoordinator[Task] = { val coordinatorRef = ProjectAttributesCoordinatorActor.start(files, None, config.cluster.shards) new ProjectAttributesCoordinator[Task](projectCache, coordinatorRef) } }
Example 187
Source File: RepairFromMessages.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg import java.net.URLDecoder import java.util.UUID import akka.actor.ActorSystem import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal import akka.persistence.query.PersistenceQuery import ch.epfl.bluebrain.nexus.kg.resources.{Id, Repo, ResId} import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef import ch.epfl.bluebrain.nexus.rdf.Iri import com.typesafe.scalalogging.Logger import monix.eval.Task import monix.execution.Scheduler import monix.execution.schedulers.CanBlock import scala.concurrent.Future import scala.util.Try object RepairFromMessages { // $COVERAGE-OFF$ private val log = Logger[RepairFromMessages.type] def repair(repo: Repo[Task])(implicit as: ActorSystem, sc: Scheduler, pm: CanBlock): Unit = { log.info("Repairing dependent tables from messages.") val pq = PersistenceQuery(as).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) Task .fromFuture { pq.currentPersistenceIds() .mapAsync(1) { case ResourceId(id) => (repo.get(id, None).value >> Task.unit).runToFuture case other => log.warn(s"Unknown persistence id '$other'") Future.successful(()) } .runFold(0) { case (acc, _) => if (acc % 1000 == 0) log.info(s"Processed '$acc' persistence ids.") acc + 1 } .map(_ => ()) } .runSyncUnsafe() log.info("Finished repairing dependent tables from messages.") } object ResourceId { private val regex = "^resources\\-([0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12})\\-(.+)$".r def unapply(arg: String): Option[ResId] = arg match { case regex(stringUuid, stringId) => for { uuid <- Try(UUID.fromString(stringUuid)).toOption iri <- Iri.absolute(URLDecoder.decode(stringId, "UTF-8")).toOption } yield Id(ProjectRef(uuid), iri) case _ => None } } // $COVERAGE-ON$ }
Example 188
Source File: ResolverCacheSpec.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.cache import akka.actor.ExtendedActorSystem import akka.serialization.Serialization import akka.testkit._ import ch.epfl.bluebrain.nexus.commons.test.ActorSystemFixture import ch.epfl.bluebrain.nexus.iam.client.types.Identity.Anonymous import ch.epfl.bluebrain.nexus.kg.TestHelper import ch.epfl.bluebrain.nexus.kg.config.AppConfig._ import ch.epfl.bluebrain.nexus.kg.config.{AppConfig, Settings} import ch.epfl.bluebrain.nexus.kg.resolve.Resolver._ import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.{ProjectLabel, ProjectRef} import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.{Inspectors, TryValues} import scala.concurrent.duration._ //noinspection NameBooleanParameters class ResolverCacheSpec extends ActorSystemFixture("ResolverCacheSpec", true) with Matchers with Inspectors with ScalaFutures with TryValues with TestHelper { override implicit def patienceConfig: PatienceConfig = PatienceConfig(3.seconds.dilated, 5.milliseconds) private implicit val appConfig: AppConfig = Settings(system).appConfig val ref1 = ProjectRef(genUUID) val ref2 = ProjectRef(genUUID) val label1 = ProjectLabel(genString(), genString()) val label2 = ProjectLabel(genString(), genString()) val resolver: InProjectResolver = InProjectResolver(ref1, genIri, 1L, false, 10) val crossRefs: CrossProjectResolver = CrossProjectResolver(Set(genIri), List(ref1, ref2), Set(Anonymous), ref1, genIri, 0L, false, 1) val crossLabels: CrossProjectResolver = CrossProjectResolver(Set(genIri), List(label1, label2), Set(Anonymous), ref1, genIri, 0L, false, 1) val resolverProj1: Set[InProjectResolver] = List.fill(5)(resolver.copy(id = genIri)).toSet val resolverProj2: Set[InProjectResolver] = List.fill(5)(resolver.copy(id = genIri, ref = ref2)).toSet private val cache = ResolverCache[Task] "ResolverCache" should { "index resolvers" in { val list = (resolverProj1 ++ resolverProj2).toList forAll(list) { resolver => cache.put(resolver).runToFuture.futureValue cache.get(resolver.ref, resolver.id).runToFuture.futureValue shouldEqual Some(resolver) } } "list resolvers" in { cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs resolverProj1 cache.get(ref2).runToFuture.futureValue should contain theSameElementsAs resolverProj2 } "deprecate resolver" in { val resolver = resolverProj1.head cache.put(resolver.copy(deprecated = true, rev = 2L)).runToFuture.futureValue cache.get(resolver.ref, resolver.id).runToFuture.futureValue shouldEqual None cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs resolverProj1.filterNot(_ == resolver) } "serialize cross project resolver" when { val serialization = new Serialization(system.asInstanceOf[ExtendedActorSystem]) "parameterized with ProjectRef" in { val bytes = serialization.serialize(crossRefs).success.value val out = serialization.deserialize(bytes, classOf[CrossProjectResolver]).success.value out shouldEqual crossRefs } "parameterized with ProjectLabel" in { val bytes = serialization.serialize(crossLabels).success.value val out = serialization.deserialize(bytes, classOf[CrossProjectResolver]).success.value out shouldEqual crossLabels } } } }
Example 189
Source File: StorageCacheSpec.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg.cache import java.nio.file.Paths import java.time.Clock import akka.testkit._ import ch.epfl.bluebrain.nexus.commons.test.ActorSystemFixture import ch.epfl.bluebrain.nexus.kg.TestHelper import ch.epfl.bluebrain.nexus.kg.config.AppConfig._ import ch.epfl.bluebrain.nexus.kg.config.{AppConfig, Settings} import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.{ProjectRef} import ch.epfl.bluebrain.nexus.kg.storage.Storage.DiskStorage import ch.epfl.bluebrain.nexus.rdf.implicits._ import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.scalatest.concurrent.ScalaFutures import org.scalatest.matchers.should.Matchers import org.scalatest.{Inspectors, TryValues} import scala.concurrent.duration._ //noinspection NameBooleanParameters class StorageCacheSpec extends ActorSystemFixture("StorageCacheSpec", true) with Matchers with Inspectors with ScalaFutures with TryValues with TestHelper { override implicit def patienceConfig: PatienceConfig = PatienceConfig(3.seconds.dilated, 5.milliseconds) private implicit val clock: Clock = Clock.systemUTC private implicit val appConfig: AppConfig = Settings(system).appConfig val ref1 = ProjectRef(genUUID) val ref2 = ProjectRef(genUUID) val time = clock.instant() val lastId = url"http://example.com/lastA" // initialInstant.minusSeconds(1L + genInt().toLong) val tempStorage = DiskStorage(ref1, genIri, 1L, false, true, "alg", Paths.get("/tmp"), read, write, 1024L) val lastStorageProj1 = tempStorage.copy(id = lastId) val lastStorageProj2 = tempStorage.copy(ref = ref2, id = lastId) val storagesProj1: List[DiskStorage] = List.fill(5)(tempStorage.copy(id = genIri)) :+ lastStorageProj1 val storagesProj2: List[DiskStorage] = List.fill(5)(tempStorage.copy(ref = ref2, id = genIri)) :+ lastStorageProj2 private val cache = StorageCache[Task] "StorageCache" should { "index storages" in { forAll((storagesProj1 ++ storagesProj2).zipWithIndex) { case (storage, index) => implicit val instant = time.plusSeconds(index.toLong) cache.put(storage).runToFuture.futureValue cache.get(storage.ref, storage.id).runToFuture.futureValue shouldEqual Some(storage) } } "get latest default storage" in { cache.getDefault(ref1).runToFuture.futureValue shouldEqual Some(lastStorageProj1) cache.getDefault(ref2).runToFuture.futureValue shouldEqual Some(lastStorageProj2) cache.getDefault(ProjectRef(genUUID)).runToFuture.futureValue shouldEqual None } "list storages" in { cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs storagesProj1 cache.get(ref2).runToFuture.futureValue should contain theSameElementsAs storagesProj2 } "deprecate storage" in { val storage = storagesProj1.head implicit val instant = time.plusSeconds(30L) cache.put(storage.copy(deprecated = true, rev = 2L)).runToFuture.futureValue cache.get(storage.ref, storage.id).runToFuture.futureValue shouldEqual None cache.get(ref1).runToFuture.futureValue should contain theSameElementsAs storagesProj1.filterNot(_ == storage) } } }
Example 190
Source File: Signed.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.transaction import com.wavesplatform.transaction.TxValidationError.InvalidSignature import monix.eval.{Coeval, Task} import monix.execution.Scheduler import monix.execution.schedulers.SchedulerService import scala.concurrent.Await import scala.concurrent.duration.Duration trait Signed extends Authorized { protected val signatureValid: Coeval[Boolean] protected val signedDescendants: Coeval[Seq[Signed]] = Coeval(Nil) protected val signaturesValidMemoized: Task[Either[InvalidSignature, this.type]] = Signed.validateTask[this.type](this).memoize val signaturesValid: Coeval[Either[InvalidSignature, this.type]] = Coeval.evalOnce(Await.result(signaturesValidMemoized.runToFuture(Signed.scheduler), Duration.Inf)) } object Signed { type E[A] = Either[InvalidSignature, A] private implicit lazy val scheduler: SchedulerService = { val parallelism = (Runtime.getRuntime.availableProcessors() / 2).max(1).min(4) Scheduler.computation(parallelism, "sig-validator") } def validateOrdered[S <: Signed](ss: Seq[S]): E[Seq[S]] = Await.result( Task .parTraverse(ss)(s => s.signaturesValidMemoized) .map( _.collectFirst { case Left(v) => Left(v) }.getOrElse(Right(ss)) ) .runAsyncLogErr, Duration.Inf ) private def validateTask[S <: Signed](signedEntity: S): Task[E[S]] = Task { import cats.instances.either._ import cats.instances.list._ import cats.syntax.traverse._ if (!signedEntity.signatureValid()) { Task.now(Left(InvalidSignature(signedEntity, None))) } else if (signedEntity.signedDescendants().isEmpty) { Task.now(Right(signedEntity)) } else { Task .parTraverseUnordered(signedEntity.signedDescendants())(s => s.signaturesValidMemoized) .map(_.sequence.map(_ => signedEntity)) } }.flatten }
Example 191
Source File: BalanceDistribution.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.api.common import com.google.common.collect.AbstractIterator import com.google.common.primitives.{Ints, Longs} import com.wavesplatform.account.Address import com.wavesplatform.database.{AddressId, DBExt, DBResource, Keys} import com.wavesplatform.state.Portfolio import com.wavesplatform.state.Portfolio.longSemigroup import monix.eval.Task import monix.reactive.Observable import org.iq80.leveldb.DB import scala.annotation.tailrec import scala.jdk.CollectionConverters._ trait BalanceDistribution { import BalanceDistribution._ def balanceDistribution( db: DB, height: Int, after: Option[Address], overrides: Map[Address, Portfolio], globalPrefix: Array[Byte], addressId: Array[Byte] => AddressId, balanceOf: Portfolio => Long ): Observable[(Address, Long)] = db.resourceObservable .flatMap { resource => resource.iterator.seek( globalPrefix ++ after.flatMap(address => resource.get(Keys.addressId(address))).fold(Array.emptyByteArray)(id => Longs.toByteArray(id.toLong + 1)) ) Observable.fromIterator(Task(new BalanceIterator(resource, globalPrefix, addressId, balanceOf, height, overrides).asScala.filter(_._2 > 0))) } } object BalanceDistribution { class BalanceIterator( resource: DBResource, globalPrefix: Array[Byte], addressId: Array[Byte] => AddressId, balanceOf: Portfolio => Long, height: Int, private var pendingPortfolios: Map[Address, Portfolio] ) extends AbstractIterator[(Address, Long)] { @inline private def stillSameAddress(expected: AddressId): Boolean = resource.iterator.hasNext && { val maybeNext = resource.iterator.peekNext().getKey maybeNext.startsWith(globalPrefix) && addressId(maybeNext) == expected } @tailrec private def findNextBalance(): Option[(Address, Long)] = { if (!resource.iterator.hasNext) None else { val current = resource.iterator.next() if (!current.getKey.startsWith(globalPrefix)) None else { val aid = addressId(current.getKey) val address = resource.get(Keys.idToAddress(aid)) var balance = Longs.fromByteArray(current.getValue) var currentHeight = Ints.fromByteArray(current.getKey.takeRight(4)) while (stillSameAddress(aid)) { val next = resource.iterator.next() val nextHeight = Ints.fromByteArray(next.getKey.takeRight(4)) if (nextHeight <= height) { currentHeight = nextHeight balance = Longs.fromByteArray(next.getValue) } } pendingPortfolios -= address val adjustedBalance = longSemigroup.combine(balance, pendingPortfolios.get(address).fold(0L)(balanceOf)) if (currentHeight <= height && adjustedBalance > 0) Some(address -> adjustedBalance) else findNextBalance() } } } override def computeNext(): (Address, Long) = findNextBalance() match { case Some(balance) => balance case None => if (pendingPortfolios.nonEmpty) { val (address, portfolio) = pendingPortfolios.head pendingPortfolios -= address address -> balanceOf(portfolio) } else { endOfData() } } } }
Example 192
Source File: ScorexLogging.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.utils import monix.eval.Task import monix.execution.{CancelableFuture, Scheduler} import monix.reactive.Observable import org.slf4j.{Logger, LoggerFactory} case class LoggerFacade(logger: Logger) { def trace(message: => String, throwable: Throwable): Unit = { if (logger.isTraceEnabled) logger.trace(message, throwable) } def trace(message: => String): Unit = { if (logger.isTraceEnabled) logger.trace(message) } def debug(message: => String, arg: Any): Unit = { if (logger.isDebugEnabled) logger.debug(message, arg) } def debug(message: => String): Unit = { if (logger.isDebugEnabled) logger.debug(message) } def info(message: => String): Unit = { if (logger.isInfoEnabled) logger.info(message) } def info(message: => String, arg: Any): Unit = { if (logger.isInfoEnabled) logger.info(message, arg) } def info(message: => String, throwable: Throwable): Unit = { if (logger.isInfoEnabled) logger.info(message, throwable) } def warn(message: => String): Unit = { if (logger.isWarnEnabled) logger.warn(message) } def warn(message: => String, throwable: Throwable): Unit = { if (logger.isWarnEnabled) logger.warn(message, throwable) } def error(message: => String): Unit = { if (logger.isErrorEnabled) logger.error(message) } def error(message: => String, throwable: Throwable): Unit = { if (logger.isErrorEnabled) logger.error(message, throwable) } } trait ScorexLogging { protected lazy val log = LoggerFacade(LoggerFactory.getLogger(this.getClass)) implicit class TaskExt[A](t: Task[A]) { def runAsyncLogErr(implicit s: Scheduler): CancelableFuture[A] = logErr.runToFuture(s) def logErr: Task[A] = { t.onErrorHandleWith(ex => { log.error(s"Error executing task", ex) Task.raiseError[A](ex) }) } } implicit class ObservableExt[A](o: Observable[A]) { def logErr: Observable[A] = { o.onErrorHandleWith(ex => { log.error(s"Error observing item", ex) Observable.raiseError[A](ex) }) } } }
Example 193
Source File: Time.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.utils import java.net.{InetAddress, SocketTimeoutException} import monix.eval.Task import monix.execution.ExecutionModel import monix.execution.schedulers.SchedulerService import org.apache.commons.net.ntp.NTPUDPClient import scala.concurrent.duration.DurationInt trait Time { def correctedTime(): Long def getTimestamp(): Long } class NTP(ntpServer: String) extends Time with ScorexLogging with AutoCloseable { log.info("Initializing time") private val offsetPanicThreshold = 1000000L private val ExpirationTimeout = 60.seconds private val RetryDelay = 10.seconds private val ResponseTimeout = 10.seconds private implicit val scheduler: SchedulerService = Schedulers.singleThread(name = "time-impl", reporter = log.error("Error in NTP", _), ExecutionModel.AlwaysAsyncExecution) private val client = new NTPUDPClient() client.setDefaultTimeout(ResponseTimeout.toMillis.toInt) @volatile private var offset = 0L private val updateTask: Task[Unit] = { def newOffsetTask: Task[Option[(InetAddress, java.lang.Long)]] = Task { try { client.open() val info = client.getTime(InetAddress.getByName(ntpServer)) info.computeDetails() Option(info.getOffset).map { offset => val r = if (Math.abs(offset) > offsetPanicThreshold) throw new Exception("Offset is suspiciously large") else offset (info.getAddress, r) } } catch { case _: SocketTimeoutException => None case t: Throwable => log.warn("Problems with NTP: ", t) None } finally { client.close() } } newOffsetTask.flatMap { case None if !scheduler.isShutdown => updateTask.delayExecution(RetryDelay) case Some((server, newOffset)) if !scheduler.isShutdown => log.trace(s"Adjusting time with $newOffset milliseconds, source: ${server.getHostAddress}.") offset = newOffset updateTask.delayExecution(ExpirationTimeout) case _ => Task.unit } } def correctedTime(): Long = System.currentTimeMillis() + offset private var txTime: Long = 0 def getTimestamp(): Long = { txTime = Math.max(correctedTime(), txTime + 1) txTime } private val taskHandle = updateTask.runAsyncLogErr override def close(): Unit = { log.info("Shutting down Time") taskHandle.cancel() scheduler.shutdown() } }
Example 194
Source File: MicroblockAppender.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.state.appender import cats.data.EitherT import com.wavesplatform.block.Block.BlockId import com.wavesplatform.block.MicroBlock import com.wavesplatform.lang.ValidationError import com.wavesplatform.metrics.{BlockStats, _} import com.wavesplatform.network.MicroBlockSynchronizer.MicroblockData import com.wavesplatform.network._ import com.wavesplatform.state.Blockchain import com.wavesplatform.transaction.BlockchainUpdater import com.wavesplatform.transaction.TxValidationError.InvalidSignature import com.wavesplatform.utils.ScorexLogging import com.wavesplatform.utx.UtxPool import io.netty.channel.Channel import io.netty.channel.group.ChannelGroup import kamon.Kamon import monix.eval.Task import monix.execution.Scheduler import scala.util.{Left, Right} object MicroblockAppender extends ScorexLogging { def apply(blockchainUpdater: BlockchainUpdater with Blockchain, utxStorage: UtxPool, scheduler: Scheduler, verify: Boolean = true)( microBlock: MicroBlock ): Task[Either[ValidationError, BlockId]] = { Task(metrics.microblockProcessingTimeStats.measureSuccessful { blockchainUpdater .processMicroBlock(microBlock, verify) .map { totalBlockId => utxStorage.removeAll(microBlock.transactionData) totalBlockId } }).executeOn(scheduler) } def apply( blockchainUpdater: BlockchainUpdater with Blockchain, utxStorage: UtxPool, allChannels: ChannelGroup, peerDatabase: PeerDatabase, scheduler: Scheduler )(ch: Channel, md: MicroblockData): Task[Unit] = { import md.microBlock val microblockTotalResBlockSig = microBlock.totalResBlockSig (for { _ <- EitherT(Task.now(microBlock.signaturesValid())) _ <- EitherT(apply(blockchainUpdater, utxStorage, scheduler)(microBlock)) } yield ()).value.map { case Right(_) => md.invOpt match { case Some(mi) => allChannels.broadcast(mi, except = md.microblockOwners()) case None => log.warn(s"${id(ch)} Not broadcasting MicroBlockInv") } BlockStats.applied(microBlock) case Left(is: InvalidSignature) => peerDatabase.blacklistAndClose(ch, s"Could not append microblock $microblockTotalResBlockSig: $is") case Left(ve) => BlockStats.declined(microBlock) log.debug(s"${id(ch)} Could not append microblock $microblockTotalResBlockSig: $ve") } } private[this] object metrics { val microblockProcessingTimeStats = Kamon.timer("microblock-appender.processing-time").withoutTags() } }
Example 195
Source File: Context.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.extensions import akka.actor.ActorSystem import com.wavesplatform.account.Address import com.wavesplatform.api.common._ import com.wavesplatform.common.state.ByteStr import com.wavesplatform.events.{BlockchainUpdated, UtxEvent} import com.wavesplatform.lang.ValidationError import com.wavesplatform.settings.WavesSettings import com.wavesplatform.state.Blockchain import com.wavesplatform.transaction.smart.script.trace.TracedResult import com.wavesplatform.transaction.{Asset, DiscardedBlocks, Transaction} import com.wavesplatform.utils.Time import com.wavesplatform.utx.UtxPool import com.wavesplatform.wallet.Wallet import monix.eval.Task import monix.reactive.Observable trait Context { def settings: WavesSettings def blockchain: Blockchain def rollbackTo(blockId: ByteStr): Task[Either[ValidationError, DiscardedBlocks]] def time: Time def wallet: Wallet def utx: UtxPool def transactionsApi: CommonTransactionsApi def blocksApi: CommonBlocksApi def accountsApi: CommonAccountsApi def assetsApi: CommonAssetsApi def broadcastTransaction(tx: Transaction): TracedResult[ValidationError, Boolean] def spendableBalanceChanged: Observable[(Address, Asset)] def blockchainUpdated: Observable[BlockchainUpdated] def utxEvents: Observable[UtxEvent] def actorSystem: ActorSystem }
Example 196
Source File: MicroBlockMiner.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.mining.microblocks import com.wavesplatform.account.KeyPair import com.wavesplatform.block.Block import com.wavesplatform.mining.{MinerDebugInfo, MiningConstraint, MiningConstraints} import com.wavesplatform.settings.MinerSettings import com.wavesplatform.state.Blockchain import com.wavesplatform.transaction.BlockchainUpdater import com.wavesplatform.utx.UtxPool import io.netty.channel.group.ChannelGroup import monix.eval.Task import monix.execution.schedulers.SchedulerService trait MicroBlockMiner { def generateMicroBlockSequence( account: KeyPair, accumulatedBlock: Block, constraints: MiningConstraints, restTotalConstraint: MiningConstraint, lastMicroBlock: Long ): Task[Unit] } object MicroBlockMiner { def apply( setDebugState: MinerDebugInfo.State => Unit, allChannels: ChannelGroup, blockchainUpdater: BlockchainUpdater with Blockchain, utx: UtxPool, settings: MinerSettings, minerScheduler: SchedulerService, appenderScheduler: SchedulerService ): MicroBlockMiner = new MicroBlockMinerImpl( setDebugState, allChannels, blockchainUpdater, utx, settings, minerScheduler, appenderScheduler ) }
Example 197
Source File: DebugApiRouteSpec.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.http import com.wavesplatform.api.http.ApiError.ApiKeyNotValid import com.wavesplatform.network.PeerDatabase import com.wavesplatform.settings.WavesSettings import com.wavesplatform.{NTPTime, TestWallet} import monix.eval.Task //noinspection ScalaStyle class DebugApiRouteSpec extends RouteSpec("/debug") with RestAPISettingsHelper with TestWallet with NTPTime { private val sampleConfig = com.typesafe.config.ConfigFactory.load() private val wavesSettings = WavesSettings.fromRootConfig(sampleConfig) private val configObject = sampleConfig.root() private val route = DebugApiRoute( wavesSettings, ntpTime, null, null, null, null, null, PeerDatabase.NoOp, null, (_, _) => Task.raiseError(new NotImplementedError("")), null, null, null, null, null, null, configObject, _ => Seq.empty ).route routePath("/configInfo") - { "requires api-key header" in { Get(routePath("/configInfo?full=true")) ~> route should produce(ApiKeyNotValid) Get(routePath("/configInfo?full=false")) ~> route should produce(ApiKeyNotValid) } } }
Example 198
Source File: MicroBlockMinerSpec.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.mining import com.wavesplatform.account.Alias import com.wavesplatform.block.Block import com.wavesplatform.common.utils._ import com.wavesplatform.db.WithDomain import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.lagonaki.mocks.TestBlock import com.wavesplatform.mining.microblocks.MicroBlockMinerImpl import com.wavesplatform.mining.microblocks.MicroBlockMinerImpl.MicroBlockMiningResult import com.wavesplatform.settings.TestFunctionalitySettings import com.wavesplatform.transaction.{CreateAliasTransaction, GenesisTransaction, TxVersion} import com.wavesplatform.utils.Schedulers import com.wavesplatform.utx.UtxPoolImpl import com.wavesplatform.{TestValues, TransactionGen} import monix.eval.Task import monix.execution.Scheduler import org.scalamock.scalatest.PathMockFactory import org.scalatest.{FlatSpec, Matchers, PrivateMethodTester} import scala.concurrent.duration._ import scala.util.Random class MicroBlockMinerSpec extends FlatSpec with Matchers with PrivateMethodTester with PathMockFactory with WithDomain with TransactionGen { "Micro block miner" should "generate microblocks in flat interval" in { val scheduler = Schedulers.singleThread("test") val acc = TestValues.keyPair val genesis = GenesisTransaction.create(acc.toAddress, TestValues.bigMoney, TestValues.timestamp).explicitGet() val settings = domainSettingsWithFS(TestFunctionalitySettings.withFeatures(BlockchainFeatures.NG)) withDomain(settings) { d => d.appendBlock(TestBlock.create(Seq(genesis))) val utxPool = new UtxPoolImpl(ntpTime, d.blockchainUpdater, ignoreSpendableBalanceChanged, settings.utxSettings, enablePriorityPool = true) val microBlockMiner = new MicroBlockMinerImpl( _ => (), null, d.blockchainUpdater, utxPool, settings.minerSettings, scheduler, scheduler ) val generateOneMicroBlockTask = PrivateMethod[Task[MicroBlockMiningResult]](Symbol("generateOneMicroBlockTask")) def generateBlocks( block: Block, constraint: MiningConstraint, lastMicroBlock: Long ): Block = { val task = microBlockMiner invokePrivate generateOneMicroBlockTask( acc, block, MiningConstraints(d.blockchainUpdater, d.blockchainUpdater.height, Some(settings.minerSettings)), constraint, lastMicroBlock ) import Scheduler.Implicits.global val startTime = System.nanoTime() val tx = CreateAliasTransaction .selfSigned(TxVersion.V1, acc, Alias.create("test" + Random.nextInt()).explicitGet(), TestValues.fee, TestValues.timestamp) .explicitGet() utxPool.putIfNew(tx).resultE.explicitGet() val result = task.runSyncUnsafe() result match { case res @ MicroBlockMinerImpl.Success(b, totalConstraint) => val isFirstBlock = block.transactionData.isEmpty val elapsed = (res.nanoTime - startTime).nanos.toMillis if (isFirstBlock) elapsed should be < 1000L else elapsed shouldBe settings.minerSettings.microBlockInterval.toMillis +- 1000 generateBlocks(b, totalConstraint, res.nanoTime) case MicroBlockMinerImpl.Stop => d.blockchainUpdater.liquidBlock(d.blockchainUpdater.lastBlockId.get).get case MicroBlockMinerImpl.Retry => throw new IllegalStateException() } } val baseBlock = Block .buildAndSign( 3, TestValues.timestamp, d.lastBlockId, d.lastBlock.header.baseTarget, d.lastBlock.header.generationSignature, Nil, acc, Nil, 0 ) .explicitGet() d.appendBlock(baseBlock) val constraint = OneDimensionalMiningConstraint(5, TxEstimators.one, "limit") val lastBlock = generateBlocks(baseBlock, constraint, 0) lastBlock.transactionData should have size constraint.rest.toInt } } }
Example 199
Source File: Backlog4jInterpreter.scala From BacklogMigration-Redmine with MIT License | 5 votes |
package com.nulabinc.backlog.r2b.interpreters.backlog import cats.~> import com.nulabinc.backlog.r2b.dsl.BacklogDSL.{BacklogProgram, BacklogResponse} import com.nulabinc.backlog.r2b.dsl._ import com.nulabinc.backlog4j.api.option.GetIssuesParams import com.nulabinc.backlog4j.conf.BacklogPackageConfigure import com.nulabinc.backlog4j.{BacklogClient, BacklogClientFactory, Issue} import monix.eval.Task import scala.concurrent.ExecutionContext import scala.jdk.CollectionConverters._ class Backlog4jInterpreter(url: String, key: String) (implicit val exc: ExecutionContext) extends (BacklogADT ~> Task) { private val backlogPackageConfigure = new BacklogPackageConfigure(url) private val configure = backlogPackageConfigure.apiKey(key) private val client: BacklogClient = new BacklogClientFactory(configure).newClient() def run[A](program: BacklogProgram[A]): Task[A] = program.foldMap(this) def getProjectIssues(projectId: Long, offset: Int, count: Int): Seq[Issue] = { val params: GetIssuesParams = new GetIssuesParams(List(projectId).asJava) params.offset(offset.toLong) params.count(count) params.sort(GetIssuesParams.SortKey.Created) params.order(GetIssuesParams.Order.Asc) client.getIssues(params).asScala.toSeq } def deleteIssue(issue: Issue): Task[BacklogResponse[Unit]] = Task { try { Right(client.deleteIssue(issue.getId)) } catch { case ex: Throwable => Left(ResponseError(ex)) } } override def apply[A](fa: BacklogADT[A]): Task[A] = fa match { case Pure(a) => Task(a) case GetProject(projectKey) => runRequest()(client.getProject(projectKey)) case GetProjectIssues(projectId, offset, count) => runRequest()(getProjectIssues(projectId, offset, count)) case DeleteIssue(issue) => deleteIssue(issue) } private def runRequest[A]()(f: A): Task[BacklogResponse[A]] = Task { try { Right(f) } catch { case ex: Throwable => Left(ResponseError(ex)) } } }
Example 200
Source File: AppInterpreter.scala From BacklogMigration-Redmine with MIT License | 5 votes |
package com.nulabinc.backlog.r2b.interpreters import cats.free.Free import cats.~> import com.nulabinc.backlog.r2b.dsl.BacklogDSL.BacklogProgram import com.nulabinc.backlog.r2b.interpreters.AppDSL.AppProgram import com.nulabinc.backlog.r2b.interpreters.ConsoleDSL.ConsoleProgram import com.nulabinc.backlog.r2b.interpreters.backlog.Backlog4jInterpreter import monix.eval.Task sealed trait AppADT[+A] case class Pure[A](a: A) extends AppADT[A] case class Backlog[A](prg: BacklogProgram[A]) extends AppADT[A] case class Console[A](prg: ConsoleProgram[A]) extends AppADT[A] case class Exit(exitCode: Int) extends AppADT[Unit] object AppDSL { type AppProgram[A] = Free[AppADT, A] def pure[A](a: A): AppProgram[A] = Free.liftF(Pure(a)) def backlog[A](prg: BacklogProgram[A]): AppProgram[A] = Free.liftF[AppADT, A](Backlog(prg)) def console[A](prg: ConsoleProgram[A]): AppProgram[A] = Free.liftF(Console(prg)) def exit(reason: String, exitCode: Int): AppProgram[Unit] = { for { _ <- console(ConsoleDSL.print(reason)) _ <- Free.liftF(Exit(exitCode)) } yield () } } case class AppInterpreter(backlogInterpreter: Backlog4jInterpreter, consoleInterpreter: ConsoleInterpreter) extends (AppADT ~> Task) { def run[A](prg: AppProgram[A]): Task[A] = prg.foldMap(this) override def apply[A](fa: AppADT[A]): Task[A] = fa match { case Pure(a) => Task(a) case Backlog(prg) => backlogInterpreter.run(prg) case Console(prg) => prg.foldMap(consoleInterpreter) case Exit(statusCode) => sys.exit(statusCode) } }