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)) }