You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.3 KiB
77 lines
2.3 KiB
package outwatchapp.util.reactive
|
|
|
|
import io.circe.Decoder
|
|
import io.circe.Encoder
|
|
import io.circe.Printer
|
|
import io.circe.parser._
|
|
import io.circe.syntax._
|
|
import monix.execution.Ack
|
|
import monix.execution.Cancelable
|
|
import monix.execution.cancelables.SingleAssignCancelable
|
|
import monix.reactive.Observable
|
|
import monix.reactive.Observer
|
|
import monix.reactive.OverflowStrategy
|
|
import org.scalajs.dom.raw.MessageEvent
|
|
import org.scalajs.dom.webworkers.DedicatedWorkerGlobalScope
|
|
import scala.concurrent.Future
|
|
import outwatchapp.util.reactive.Exceptions.WrongTypeException
|
|
// @js.native
|
|
// @JSGlobalScope
|
|
// object WorkerGlobal extends DedicatedWorkerGlobalScope
|
|
|
|
// class DedicatedWorkerImpl[T: Encoder: Decoder](wg: DedicatedWorkerGlobalScope) {
|
|
// def run = Task.deferAction(implicit s =>
|
|
// for {
|
|
// _ <- Task.unit
|
|
// sub <- Task(ConcurrentSubject.publish[T])
|
|
// } yield ()
|
|
// )
|
|
// }
|
|
|
|
object DedicatedWorker {
|
|
def source[T: Decoder](wg: DedicatedWorkerGlobalScope) =
|
|
Observable.create[T](OverflowStrategy.DropOld(50)) { sub =>
|
|
val c = SingleAssignCancelable()
|
|
def onmessageFn(event: MessageEvent): Unit = {
|
|
event.data match {
|
|
case s: String =>
|
|
decode[T](s)
|
|
.map { res =>
|
|
if (sub.onNext(res) == Ack.Stop) c.cancel()
|
|
res
|
|
}
|
|
.left
|
|
.foreach(err =>
|
|
sub.onError(
|
|
new Exception(s"Failed to decode $s. Error was $err")
|
|
)
|
|
)
|
|
case other =>
|
|
sub.onError(WrongTypeException(s"Received wrong type: $other"))
|
|
}
|
|
}
|
|
wg.onmessage = onmessageFn _
|
|
|
|
c := Cancelable(() => wg.onmessage = _ => ())
|
|
}
|
|
|
|
def sink[T: Encoder](wg: DedicatedWorkerGlobalScope) =
|
|
new Observer[T] {
|
|
val printer = Printer.noSpaces
|
|
|
|
override def onNext(elem: T): Future[Ack] = {
|
|
// wg.onoffline
|
|
wg.postMessage(printer.print(elem.asJson))
|
|
Ack.Continue
|
|
}
|
|
|
|
override def onError(ex: Throwable): Unit = ex.printStackTrace()
|
|
|
|
override def onComplete(): Unit = println("Worker observer completed")
|
|
|
|
}
|
|
|
|
def apply[T: Encoder: Decoder](
|
|
wg: DedicatedWorkerGlobalScope
|
|
): DedicatedWorker[T] = MonixProSubject.from(sink(wg), source(wg))
|
|
}
|