monix.execution.Cancelable Scala Examples

The following examples show how to use monix.execution.Cancelable. 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: LanguageClient.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
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 2
Source File: MonixTaskMain.scala    From advanced-scala-code   with Apache License 2.0 5 votes vote down vote up
object MonixTaskMain {

  def main(args: Array[String]): Unit = {
    import org.asynchttpclient.DefaultAsyncHttpClient
    val asyncHttpClient = new DefaultAsyncHttpClient()
    arm.ArmUtils.using(asyncHttpClient) {
      import java.nio.charset.Charset
      import monix.eval.Task
      val result6T = Task.create[String]( (_, callback) => {
        val lf = asyncHttpClient.prepareGet("https://httpbin.org/get").execute()
        val javaFuture = lf.toCompletableFuture

        javaFuture.whenComplete { (response, exc) => {
          if (exc == null) {
            callback.onSuccess(response.getResponseBody(Charset.forName("UTF-8")))
          } else callback.onError(exc)
        }}

        import monix.execution.Cancelable
        Cancelable.apply { () =>
          javaFuture.cancel(true)
        }
      })

      import monix.execution.Scheduler.Implicits.global
      val resultCF = result6T.runToFuture

      import scala.concurrent.Await
      import scala.concurrent.duration._
      val result = Await.result(resultCF, 5.seconds)
      println(result)
    }
  }
} 
Example 3
Source File: DataProducer.scala    From monix-sample   with Apache License 2.0 5 votes vote down vote up
package engine

import monix.execution.Cancelable
import monix.reactive.Observable
import monix.reactive.observers.Subscriber
import shared.models.Signal
import util.Random
import scala.concurrent.duration._

final class DataProducer(interval: FiniteDuration, seed: Long)
  extends Observable[Signal] {

  override def unsafeSubscribeFn(subscriber: Subscriber[Signal]): Cancelable = {
    import subscriber.{scheduler => s}

    val random = Observable
      .fromStateAction(Random.intInRange(-20, 20))(s.currentTimeMillis() + seed)
      .flatMap { x => Observable.now(x).delaySubscription(interval) }

    val generator = random.scan(Signal(0, s.currentTimeMillis())) {
      case (Signal(value, _), rnd) =>
        Signal(value + rnd, s.currentTimeMillis())
    }

    generator
      .drop(1)
      .unsafeSubscribeFn(subscriber)
  }
} 
Example 4
Source File: DataConsumer.scala    From monix-sample   with Apache License 2.0 5 votes vote down vote up
package client

import monix.execution.Cancelable
import monix.reactive.Observable
import monix.reactive.OverflowStrategy.DropNew
import monix.reactive.observers.Subscriber
import org.scalajs.dom
import shared.models.{Event, OverflowEvent, Signal}
import scala.concurrent.duration.FiniteDuration
import scala.scalajs.js.Dynamic.global

final class DataConsumer(interval: FiniteDuration, seed: Long, doBackPressure: Boolean)
  extends Observable[Event] {

  override def unsafeSubscribeFn(subscriber: Subscriber[Event]): Cancelable = {
    val host = dom.window.location.host
    val protocol = if (dom.document.location.protocol == "https:") "wss:" else "ws:"

    val source = if (doBackPressure) {
      val url = s"$protocol//$host/back-pressured-stream?periodMillis=${interval.toMillis}&seed=$seed"
      BackPressuredWebSocketClient(url)
    }
    else {
      val url = s"$protocol//$host/simple-stream?periodMillis=${interval.toMillis}&seed=$seed"
      SimpleWebSocketClient(url, DropNew(1000))
    }

    source
      .collect { case IsEvent(e) => e }
      .unsafeSubscribeFn(subscriber)
  }

  object IsEvent {
    def unapply(message: String) = {
      val json = global.JSON.parse(message)

      json.event.asInstanceOf[String] match {
        case "point" =>
          Some(Signal(
            value = json.value.asInstanceOf[Number].doubleValue(),
            timestamp = json.timestamp.asInstanceOf[Number].longValue()
          ))
        case "overflow" =>
          Some(OverflowEvent(
            dropped = json.dropped.asInstanceOf[Number].longValue(),
            timestamp = json.timestamp.asInstanceOf[Number].longValue()
          ))
        case "error" =>
          val errorType = json.`type`.asInstanceOf[String]
          val message = json.message.asInstanceOf[String]
          throw new BackPressuredWebSocketClient.Exception(
            s"Server-side error throw - $errorType: $message")
        case _ =>
          None
      }
    }
  }
} 
Example 5
Source File: MongoObservableReactivePublisherTest.scala    From scala-commons   with MIT License 5 votes vote down vote up
package com.avsystem.commons
package mongo.async

import com.avsystem.commons.concurrent.RunNowEC
import com.github.ghik.silencer.silent
import com.mongodb.async.{client => mongo}
import monix.execution.{Cancelable, Scheduler}
import org.mockito.ArgumentMatchers.{eq => eqTo, _}
import org.mockito.Mockito
import org.mockito.Mockito._
import org.mongodb.scala.{Completed, Document, FindObservable, MongoCollection, SingleObservable}
import org.scalactic.source.Position
import org.scalatest.freespec.AnyFreeSpec

import scala.concurrent.duration.Duration

@silent("deprecated")
class MongoObservableReactivePublisherTest extends AnyFreeSpec {

  abstract class MockedObservableTests(implicit position: Position) extends MongoObservableExtensions {

    def subscribe[T](obs: mongo.Observable[T], testSubscriber: TestSubscriber[T]): Unit

    "should drop test collection" in {
      val collection = Mockito.mock(classOf[MongoCollection[Document]])
      when(collection.drop()).thenReturn(SingleObservable(Completed()))
      val dropSubscriber = TestSubscriber[Completed]()

      subscribe(collection.drop(), dropSubscriber)

      dropSubscriber.assertNoTerminalEvent()
      dropSubscriber.requestMore(1)
      dropSubscriber.awaitTerminalEvent(Duration(100, "ms"))
      dropSubscriber.assertNoErrors()
      dropSubscriber.assertReceivedOnNext(Seq(Completed()))

      verify(collection).drop()
      verifyNoMoreInteractions(collection)
    }

    "should insert documents" in {
      val collection = Mockito.mock(classOf[MongoCollection[Document]])
      val insertSubscriber = TestSubscriber[Completed]()
      when(collection.insertMany(any())).thenReturn(SingleObservable(Completed()))

      val documents: IndexedSeq[Document] = (1 to 100) map { i: Int => Document("_id" -> i) }
      subscribe(collection.insertMany(documents), insertSubscriber)
      insertSubscriber.requestMore(1)
      insertSubscriber.awaitTerminalEvent(Duration(100, "ms"))
      insertSubscriber.assertNoErrors()
      insertSubscriber.assertReceivedOnNext(Seq(Completed()))

      verify(collection).insertMany(eqTo(documents))
      verifyNoMoreInteractions(collection)
    }

    "should find documents" in {
      val documents: IndexedSeq[Document] = (1 to 100) map { i: Int => Document("_id" -> i) }
      val original = Mockito.mock(classOf[FindObservable[Document]])
      val findSubscriber = TestSubscriber[Document]()
      doNothing().when(original).subscribe(any())

      subscribe(original, findSubscriber)
      findSubscriber.assertNoTerminalEvent()
      findSubscriber.requestMore(101)
      documents.foreach(findSubscriber.onNext)
      findSubscriber.onComplete()
      findSubscriber.awaitTerminalEvent(Duration(100, "ms"))
      findSubscriber.assertNoErrors()
      findSubscriber.assertReceivedOnNext(documents)


      verify(original).subscribe(any(classOf[mongo.Observer[_ >: Document]]))
      verifyNoMoreInteractions(original)
    }
  }

  "A Mongo-Reactive observable" - new MockedObservableTests {
    override def subscribe[T](obs: mongo.Observable[T], testSubscriber: TestSubscriber[T]): Unit =
      obs.asReactive.subscribe(testSubscriber)
  }
  "A Mongo-Monix observable" - new MockedObservableTests {
    override def subscribe[T](obs: mongo.Observable[T], testSubscriber: TestSubscriber[T]): Unit =
      obs.asMonix.subscribe(
        monix.reactive.observers.Subscriber.fromReactiveSubscriber(testSubscriber, Cancelable.empty)(Scheduler(RunNowEC))
      )
  }
} 
Example 6
Source File: UserEventProducer.scala    From frees-rpc-workshop   with Apache License 2.0 5 votes vote down vote up
package scalaexchange
package datagenerator

import com.fortysevendeg.scalacheck.datetime.GenDateTime
import com.fortysevendeg.scalacheck.datetime.instances.joda.jodaForPeriod
import monix.execution.Cancelable
import monix.reactive.Observable
import monix.reactive.observers.Subscriber
import org.joda.time.{DateTime, Period}

import scala.concurrent.duration.FiniteDuration


class UserEventProducer(interval: FiniteDuration) extends Observable[UserEvent] {

  override def unsafeSubscribeFn(subscriber: Subscriber[UserEvent]): Cancelable = {

    val userEventRandom: Observable[UserEvent] =
      Observable
        .fromStateAction(eventsGen)(Nil)
        .flatMap { a =>
          Observable.now(a).delaySubscription(interval)
        }

    userEventRandom.drop(1).unsafeSubscribeFn(subscriber)
  }

  private[this] def eventsGen(initialState: List[UserEvent]): (UserEvent, List[UserEvent]) = {

    import org.scalacheck._

    val dataGen: Arbitrary[UserEvent] = Arbitrary {
      import Gen._
      for {
        id        <- choose(1, 100)
        eventType <- Gen.oneOf(List(ProcessedCheckout, UnprocessedCheckout, Login))
        date      <- GenDateTime.genDateTimeWithinRange(DateTime.parse("2017-12-01"), Period.days(22))
      } yield UserEvent(id, eventType, date.toString())
    }

    val newEvent: UserEvent = dataGen.arbitrary.sample
      .getOrElse(throw DataGenerationException("Exception creating new random event"))

    (newEvent, initialState :+ newEvent)
  }
} 
Example 7
Source File: WatchService.scala    From monix-nio   with Apache License 2.0 5 votes vote down vote up
package monix.nio.file

import java.nio.file.StandardWatchEventKinds.{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }
import java.nio.file.WatchEvent.Kind
import java.nio.file.{ Path, WatchEvent, WatchKey }

import com.sun.nio.file.SensitivityWatchEventModifier
import monix.execution.{ Callback, Cancelable, Scheduler }

import scala.concurrent.{ Future, Promise }
import scala.concurrent.duration.TimeUnit
import scala.util.control.NonFatal


abstract class WatchService extends AutoCloseable {
  def poll(timeout: Long, timeUnit: TimeUnit, cb: Callback[Throwable, Option[WatchKey]]): Unit

  def poll(timeout: Long, timeUnit: TimeUnit): Future[Option[WatchKey]] = {
    val p = Promise[Option[WatchKey]]()
    poll(timeout, timeUnit, Callback.fromPromise(p))
    p.future
  }

  def poll(cb: Callback[Throwable, Option[WatchKey]]): Unit

  def poll(): Future[Option[WatchKey]] = {
    val p = Promise[Option[WatchKey]]()
    poll(Callback.fromPromise(p))
    p.future
  }

  def take(cb: Callback[Throwable, WatchKey]): Unit

  def take(): Future[WatchKey] = {
    val p = Promise[WatchKey]()
    take(Callback.fromPromise(p))
    p.future
  }
}

object WatchService {
  val SupportedEvents: Set[Kind[_]] = Set(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY)

  def apply(path: Path, events: Kind[_]*)(implicit scheduler: Scheduler): WatchService = {
    val watcher = path.getFileSystem.newWatchService()
    val watchFor = if (events.isEmpty) SupportedEvents else events

    path.register(
      watcher,
      watchFor.toArray,
      SensitivityWatchEventModifier.HIGH.asInstanceOf[WatchEvent.Modifier])

    new NIOWatcherServiceImplementation(watcher)
  }

  private final class NIOWatcherServiceImplementation(watcher: java.nio.file.WatchService)(implicit scheduler: Scheduler) extends WatchService {
    override def poll(timeout: Long, timeUnit: TimeUnit, cb: Callback[Throwable, Option[WatchKey]]): Unit = {
      try {
        val key = Option(watcher.poll(timeout, timeUnit))
        cb.onSuccess(key)
      } catch {
        case NonFatal(ex) =>
          cb.onError(ex)
      }
    }

    override def poll(cb: Callback[Throwable, Option[WatchKey]]): Unit = {
      try {
        val key = Option(watcher.poll())
        cb.onSuccess(key)
      } catch {
        case NonFatal(ex) =>
          cb.onError(ex)
      }
    }

    override def take(cb: Callback[Throwable, WatchKey]): Unit = {
      try {
        val key = watcher.take()
        cb.onSuccess(key)
      } catch {
        case NonFatal(ex) =>
          cb.onError(ex)
      }
    }

    override def close(): Unit = cancelable.cancel()

    private[this] val cancelable: Cancelable =
      Cancelable { () =>
        try watcher.close() catch {
          case NonFatal(ex) => scheduler.reportFailure(ex)
        }
      }
  }
} 
Example 8
Source File: ExecutorServiceWrapper.scala    From monix-nio   with Apache License 2.0 5 votes vote down vote up
package monix.nio.internal

import java.util
import java.util.concurrent.{ AbstractExecutorService, ExecutorService, TimeUnit }

import monix.execution.schedulers.{ ReferenceScheduler, SchedulerService }
import monix.execution.{ Cancelable, ExecutionModel, Scheduler }

import scala.collection.JavaConverters._
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, ExecutionContextExecutorService }


  private val currentThread: Scheduler =
    new ReferenceScheduler {
      import monix.execution.Scheduler.global
      def execute(r: Runnable): Unit = r.run()
      def reportFailure(t: Throwable): Unit = throw t
      def scheduleOnce(initialDelay: Long, unit: TimeUnit, r: Runnable): Cancelable =
        global.scheduleOnce(initialDelay, unit, r)
      def executionModel: ExecutionModel =
        ExecutionModel.Default
    }
} 
Example 9
Source File: AsyncChannelObservable.scala    From monix-nio   with Apache License 2.0 5 votes vote down vote up
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 10
Source File: AsyncChannelConsumer.scala    From monix-nio   with Apache License 2.0 5 votes vote down vote up
package monix.nio

import java.nio.ByteBuffer

import monix.execution.Ack.{ Continue, Stop }
import monix.execution.{ Ack, Callback, Cancelable, Scheduler }
import monix.execution.atomic.Atomic
import monix.execution.cancelables.{ AssignableCancelable, SingleAssignCancelable }
import monix.reactive.Consumer
import monix.reactive.observers.Subscriber

import scala.concurrent.{ Future, Promise }
import scala.util.control.NonFatal

private[nio] abstract class AsyncChannelConsumer extends Consumer[Array[Byte], Long] {
  def channel: Option[AsyncChannel]
  def withInitialPosition: Long = 0L
  def init(subscriber: AsyncChannelSubscriber): Future[Unit] = Future.successful(())

  class AsyncChannelSubscriber(consumerCallback: Callback[Throwable, Long])(implicit val scheduler: Scheduler)
    extends Subscriber[Array[Byte]] { self =>

    private[this] lazy val initFuture = init(self)
    private[this] val callbackCalled = Atomic(false)
    private[this] var position = withInitialPosition

    override def onNext(elem: Array[Byte]): Future[Ack] = {
      def write(): Future[Ack] = {
        val promise = Promise[Ack]()
        channel.foreach { sc =>
          try {
            sc
              .write(ByteBuffer.wrap(elem), position)
              .runAsync(
                new Callback[Throwable, Int] {
                  override def onError(exc: Throwable) = {
                    closeChannel()
                    sendError(exc)
                    promise.success(Stop)
                  }

                  override def onSuccess(result: Int): Unit = {
                    position += result
                    promise.success(Continue)
                  }
                })
          } catch {
            case NonFatal(ex) =>
              sendError(ex)
              promise.success(Stop)
          }
        }

        promise.future
      }

      if (initFuture.value.isEmpty) {
        initFuture.flatMap(_ => write())
      } else {
        write()
      }
    }

    override def onComplete(): Unit = {
      channel.collect { case sc if sc.closeOnComplete => closeChannel() }
      if (callbackCalled.compareAndSet(expect = false, update = true))
        consumerCallback.onSuccess(position)
    }

    override def onError(ex: Throwable): Unit = {
      closeChannel()
      sendError(ex)
    }

    private[nio] def onCancel(): Unit = {
      callbackCalled.set(true) 
      closeChannel()
    }

    private[nio] def sendError(t: Throwable) =
      if (callbackCalled.compareAndSet(expect = false, update = true)) {
        scheduler.execute(new Runnable {
          def run() = consumerCallback.onError(t)
        })
      }

    private[nio] final def closeChannel()(implicit scheduler: Scheduler) =
      channel.foreach(_.close().runToFuture)
  }

  override def createSubscriber(cb: Callback[Throwable, Long], s: Scheduler): (Subscriber[Array[Byte]], AssignableCancelable) = {
    val out = new AsyncChannelSubscriber(cb)(s)

    val extraCancelable = Cancelable(() => out.onCancel())
    val conn = SingleAssignCancelable.plusOne(extraCancelable)
    (out, conn)
  }
} 
Example 11
Source File: WatchServiceObservable.scala    From monix-nio   with Apache License 2.0 5 votes vote down vote up
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 12
Source File: TestConnection.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc.testkit

import java.io.PipedInputStream
import java.io.PipedOutputStream
import monix.execution.Cancelable
import monix.execution.Scheduler
import scala.meta.jsonrpc.Connection
import scala.meta.jsonrpc.InputOutput
import scala.meta.jsonrpc.LanguageClient
import scala.meta.jsonrpc.Services


  def apply(
      clientServices: LanguageClient => Services,
      serverServices: LanguageClient => Services
  )(implicit s: Scheduler): TestConnection = {
    val inAlice = new PipedInputStream()
    val inBob = new PipedInputStream()
    val outAlice = new PipedOutputStream(inBob)
    val outBob = new PipedOutputStream(inAlice)
    val aliceIO = new InputOutput(inAlice, outAlice)
    val bobIO = new InputOutput(inBob, outBob)
    val alice = Connection.simple(aliceIO, "alice")(clientServices)
    val bob = Connection.simple(bobIO, "bob")(serverServices)
    new TestConnection(alice, aliceIO, bob, bobIO)
  }

} 
Example 13
Source File: MonixEnrichments.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import java.io.IOException
import java.io.OutputStream
import java.nio.ByteBuffer
import monix.execution.Ack
import monix.execution.Cancelable
import monix.execution.Scheduler
import monix.reactive.Observable
import monix.reactive.Observer
import scribe.LoggerSupport

object MonixEnrichments {

  
  class ObservableCurrentValue[+A](obs: Observable[A])(implicit s: Scheduler)
      extends (() => A)
      with Cancelable {
    private var value: Any = _
    private val cancelable = obs.foreach(newValue => value = newValue)
    override def apply(): A = {
      if (value == null) {
        throw new NoSuchElementException(
          "Reading from empty Observable, consider using MulticastStrategy.behavior(initialValue)"
        )
      } else {
        value.asInstanceOf[A]
      }
    }
    override def cancel(): Unit = cancelable.cancel()
  }

  implicit class XtensionObservable[A](val obs: Observable[A]) extends AnyVal {

    def focus[B: cats.Eq](f: A => B): Observable[B] =
      obs.distinctUntilChangedByKey(f).map(f)

    def toFunction0()(implicit s: Scheduler): () => A =
      toObservableCurrentValue()

    def toObservableCurrentValue()(
        implicit s: Scheduler
    ): ObservableCurrentValue[A] =
      new ObservableCurrentValue[A](obs)
  }

  implicit class XtensionObserverCompanion[A](val `_`: Observer.type)
      extends AnyVal {
    def fromOutputStream(
        out: OutputStream,
        logger: LoggerSupport
    ): Observer.Sync[ByteBuffer] = {
      new Observer.Sync[ByteBuffer] {
        private[this] var isClosed: Boolean = false
        override def onNext(elem: ByteBuffer): Ack = {
          if (isClosed) Ack.Stop
          else {
            try {
              while (elem.hasRemaining) out.write(elem.get())
              out.flush()
              Ack.Continue
            } catch {
              case _: IOException =>
                logger.error("OutputStream closed!")
                isClosed = true
                Ack.Stop
            }
          }
        }
        override def onError(ex: Throwable): Unit = ()
        override def onComplete(): Unit = out.close()
      }
    }
  }

} 
Example 14
Source File: InputOutput.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import java.io.InputStream
import java.io.OutputStream
import monix.execution.Cancelable


final class InputOutput(val in: InputStream, val out: OutputStream)
    extends Cancelable {
  override def cancel(): Unit = {
    Cancelable.cancelAll(
      List(
        Cancelable(() => in.close()),
        Cancelable(() => out.close())
      )
    )
  }
} 
Example 15
Source File: Connection.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import monix.execution.Cancelable
import monix.execution.CancelableFuture
import monix.execution.Scheduler
import scribe.Logger
import scribe.LoggerSupport


final case class Connection(
    client: LanguageClient,
    server: CancelableFuture[Unit]
) extends Cancelable {
  override def cancel(): Unit = server.cancel()
}

object Connection {

  def simple(io: InputOutput, name: String)(
      f: LanguageClient => Services
  )(implicit s: Scheduler): Connection =
    Connection(
      io,
      Logger(s"$name-server"),
      Logger(s"$name-client")
    )(f)

  def apply(
      io: InputOutput,
      serverLogger: LoggerSupport,
      clientLogger: LoggerSupport
  )(
      f: LanguageClient => Services
  )(implicit s: Scheduler): Connection = {
    val messages =
      BaseProtocolMessage.fromInputStream(io.in, serverLogger)
    val client =
      LanguageClient.fromOutputStream(io.out, clientLogger)
    val server =
      new LanguageServer(messages, client, f(client), s, serverLogger)
    Connection(client, server.startTask.executeAsync.runAsync)
  }

} 
Example 16
Source File: Monix.scala    From arrows   with Apache License 2.0 5 votes vote down vote up
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 17
Source File: OutwatchSpec.scala    From outwatch   with Apache License 2.0 5 votes vote down vote up
package outwatch

import scala.concurrent.Future
import cats.effect.ContextShift
import cats.effect.IO
import monix.execution.Ack.Continue
import monix.execution.ExecutionModel.SynchronousExecution
import monix.execution.schedulers.TrampolineScheduler
import monix.execution.{Cancelable, Scheduler}
import monix.reactive.Observable
import org.scalajs.dom.{document, window}
import org.scalatest.BeforeAndAfterEach
import org.scalatest._
import outwatch.Deprecated.IgnoreWarnings.initEvent
import org.scalatest.flatspec.{ AnyFlatSpec, AsyncFlatSpec }
import org.scalatest.matchers.should.Matchers

trait EasySubscribe {

  implicit class Subscriber[T](obs: Observable[T]) {
    def apply(next: T => Unit)(implicit s: Scheduler): Cancelable = obs.subscribe { t =>
      next(t)
      Continue
    }
  }
}

// TODO: We need this mock until localStorage is implemented in jsdom (https://github.com/tmpvar/jsdom/pull/2076)
trait LocalStorageMock {
  import scala.collection.mutable
  import scala.scalajs.js


  if (js.isUndefined(window.localStorage)) {
    val storageObject = new js.Object {
      private val map = new mutable.HashMap[String, String]

      def getItem(key: String): String = map.getOrElse(key, null)

      def setItem(key: String, value: String): Unit = {
        map += key -> value
      }

      def removeItem(key: String): Unit = {
        map -= key
      }

      def clear(): Unit = map.clear()
    }

    js.Dynamic.global.window.updateDynamic("localStorage")(storageObject)
  }

  def dispatchStorageEvent(key: String, newValue: String, oldValue: String): Unit = {
    if (key == null) window.localStorage.clear()
    else window.localStorage.setItem(key, newValue)

    val event = document.createEvent("Events")
    initEvent(event)("storage", canBubbleArg = true, cancelableArg = false)
    event.asInstanceOf[js.Dynamic].key = key
    event.asInstanceOf[js.Dynamic].newValue = newValue
    event.asInstanceOf[js.Dynamic].oldValue = oldValue
    event.asInstanceOf[js.Dynamic].storageArea = window.localStorage
    window.dispatchEvent(event)
    ()
  }
}

trait OutwatchSpec extends Matchers with BeforeAndAfterEach with EasySubscribe with LocalStorageMock { self: Suite =>

  implicit val scheduler: TrampolineScheduler = TrampolineScheduler(Scheduler.global, SynchronousExecution)
  implicit val cs: ContextShift[IO] = IO.contextShift(scheduler)

  override def beforeEach(): Unit = {

    document.body.innerHTML = ""

    window.localStorage.clear()

    // prepare body with <div id="app"></div>
    val root = document.createElement("div")
    root.id = "app"
    document.body.appendChild(root)
    ()
  }

}

abstract class JSDomSpec extends AnyFlatSpec with OutwatchSpec {
  implicit def executionContext = scheduler
}
abstract class JSDomAsyncSpec extends AsyncFlatSpec with OutwatchSpec {
  override def executionContext = scheduler

  implicit def ioAssertionToFutureAssertion(io: IO[Assertion]): Future[Assertion] = io.unsafeToFuture()
} 
Example 18
Source File: KerberosContext.scala    From pulse   with Apache License 2.0 5 votes vote down vote up
package io.phdata.pulse.logcollector

import java.security.PrivilegedAction
import java.util.concurrent.TimeUnit

import com.typesafe.scalalogging.LazyLogging
import javax.security.auth.Subject
import javax.security.auth.login.LoginContext
import monix.execution.Cancelable
import monix.execution.Scheduler.{ global => scheduler }

object KerberosContext extends LazyLogging {

  lazy private val loginContext = new LoginContext("Client")
  private var useKerberos       = false

  def scheduleKerberosLogin(initialDelay: Long, delay: Long, timeUnit: TimeUnit): Cancelable = {
    useKerberos = true
    val runnableLogin = new Runnable {
      def run(): Unit =
        login()
    }
    scheduler.scheduleWithFixedDelay(initialDelay, delay, timeUnit, runnableLogin)
  }

  def runPrivileged[W](work: => W): W =
    if (useKerberos) {
      Subject.doAs(
        loginContext.getSubject,
        new PrivilegedAction[W]() {
          override def run: W = {
            logger.debug("Privileged block started")
            val result = work
            logger.debug("Privileged block complete")
            result
          }
        }
      )
    } else {
      logger.debug("Kerberos disabled. To enable kerberos call the `scheduleKerberosLogin` method.")
      work
    }

  private def login(): Unit = {
    loginContext.login()
    logger.info(s"Logged in with kerberos configuration:\n$getSubject")
  }

  private def getSubject: String =
    if (loginContext.getSubject == null) {
      throw new Exception("Subject for LoginContext is null")
    } else {
      loginContext.getSubject.toString
    }
} 
Example 19
Source File: MonadlessTaskSpec.scala    From monadless   with Apache License 2.0 5 votes vote down vote up
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 20
Source File: Implicits.scala    From matcher   with MIT License 5 votes vote down vote up
package com.wavesplatform.dex.util

import monix.execution.{Ack, Cancelable}
import monix.reactive.observers.Subscriber
import monix.reactive.subjects.Subject

import scala.concurrent.Future

object Implicits {

  final implicit class SubjectOps(val self: Subject.type) extends AnyVal {
    def empty[T]: Subject[T, T] = new Subject[T, T] {
      override def size: Int                                                = 0
      override def unsafeSubscribeFn(subscriber: Subscriber[T]): Cancelable = Cancelable.empty
      override def onNext(elem: T): Future[Ack]                             = Future.successful(Ack.Stop)
      override def onError(ex: Throwable): Unit                             = {}
      override def onComplete(): Unit                                       = {}
    }
  }
} 
Example 21
Source File: RaidFinder.scala    From gbf-raidfinder   with MIT License 5 votes vote down vote up
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 22
Source File: ObservablesPartitioner.scala    From gbf-raidfinder   with MIT License 5 votes vote down vote up
package walfie.gbf.raidfinder.util

import akka.agent.Agent
import monix.execution.{Ack, Cancelable, Scheduler}
import monix.reactive._
import monix.reactive.observables.GroupedObservable
import monix.reactive.observers.Subscriber
import monix.reactive.subjects.PublishSubject
import scala.concurrent.{ExecutionContext, Future}

trait ObservablesPartitioner[K, V] {
  def getObservable(key: K): Observable[V]
}

object CachedObservablesPartitioner {
  def fromUngroupedObservable[K, InputV, OutputV](
    observable:      Observable[InputV],
    cacheSizePerKey: Int,
    keySelector:     InputV => K,
    mappingFunction: InputV => OutputV
  )(implicit scheduler: Scheduler): (CachedObservablesPartitioner[K, InputV, OutputV], Cancelable) = {
    val partitioner = new CachedObservablesPartitioner[K, InputV, OutputV](cacheSizePerKey, mappingFunction)
    val cancelable = observable.groupBy(keySelector).subscribe(partitioner)
    (partitioner, cancelable)
  }
}

class CachedObservablesPartitioner[K, InputV, OutputV](
  cacheSizePerKey: Int, mappingFunction: InputV => OutputV
)(implicit ec: ExecutionContext)
  extends Observer[GroupedObservable[K, InputV]] with ObservablesPartitioner[K, OutputV] {

  private val observablesByKey = Agent[Map[K, Observable[OutputV]]](Map.empty)
  private val incomingKeys = PublishSubject[K]()

  def onComplete(): Unit = {
    incomingKeys.onComplete()
  }

  def onError(e: Throwable): Unit = {
    System.err.println(e) // TODO: Better logging?
    incomingKeys.onError(e)
  }

  
  def getObservable(key: K): Observable[OutputV] = {
    observablesByKey.get.getOrElse(
      key,
      incomingKeys.findF(_ == key).flatMap(_ => getObservable(key))
    )
  }
} 
Example 23
Source File: KnownBossesMap.scala    From gbf-raidfinder   with MIT License 3 votes vote down vote up
package walfie.gbf.raidfinder

import akka.agent.Agent
import java.util.Date
import monix.execution.{Ack, Cancelable, Scheduler}
import monix.reactive._
import monix.reactive.subjects.ConcurrentSubject
import scala.concurrent.{ExecutionContext, Future}
import walfie.gbf.raidfinder.domain._

trait KnownBossesMap {
  def get(): Map[BossName, RaidBoss]
  def newBossObservable(): Observable[RaidBoss]

  
class KnownBossesObserver(
  initialBosses: Seq[RaidBoss]
)(implicit scheduler: Scheduler) extends Observer[RaidInfo] with KnownBossesMap {
  private val agent = Agent[Map[BossName, RaidBoss]](
    initialBosses.map(boss => boss.name -> boss)(scala.collection.breakOut)
  )

  // TODO: Write test for this
  private val subject = ConcurrentSubject.publish[RaidBoss]
  val newBossObservable: Observable[RaidBoss] = subject

  def onComplete(): Unit = ()
  def onError(e: Throwable): Unit = ()
  def onNext(elem: RaidInfo): Future[Ack] = {
    val name = elem.tweet.bossName
    val raidBoss = elem.boss
    if (!agent.get.isDefinedAt(name)) {
      subject.onNext(raidBoss)
    }
    agent.alter(_.updated(name, raidBoss)).flatMap(_ => Ack.Continue)
  }

  def get(): Map[BossName, RaidBoss] = agent.get()
  def purgeOldBosses(
    minDate:        Date,
    levelThreshold: Option[Int]
  ): Future[Map[BossName, RaidBoss]] = {
    agent.alter(_.filter {
      case (name, boss) => boss.lastSeen.after(minDate) || levelThreshold.exists(boss.level >= _)
    })
  }
}