3 Commits

Author SHA1 Message Date
  Rohan Sircar 02c4e2f2f3 Converted Main class to Task/Resource 7 months ago
  Rohan Sircar 1c2e3fb19f odin slf4j bridge catch all for asynchttpclient 7 months ago
  Rohan Sircar af065a7589 Wrapped login screen code in Task 7 months ago
3 changed files with 190 additions and 197 deletions
Split View
  1. +119
    -172
      src/main/scala/nova/monadic_sfx/Main.scala
  2. +69
    -24
      src/main/scala/nova/monadic_sfx/pages/LoginPage.scala
  3. +2
    -1
      src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala

+ 119
- 172
src/main/scala/nova/monadic_sfx/Main.scala View File

@ -30,193 +30,140 @@ import io.odin.syntax._
// import io.odin._
import io.odin.monix._
import nova.monadic_sfx.pages.HomePage
import monix.execution.Callback
import monix.eval.TaskApp
import cats.effect.ExitCode
import scalafx.scene.layout.HBox
import scalafx.scene.Scene
import cats.implicits._
import cats.effect.Clock
import cats.effect.Sync
object Main extends JFXApp with MainModule {
object Main extends TaskApp {
val logger = consoleLogger().withAsyncUnsafe()
// lazy val schedulers: Schedulers = new Schedulers()
// override implicit def scheduler: Scheduler = schedulers.fx
override def run(args: List[String]): Task[ExitCode] = {
// val logger = consoleLogger().withAsyncUnsafe()
lazy val schedulers: Schedulers = new Schedulers()
// lazy val backendTask = AsyncHttpClientMonixBackend()
// lazy val actorSystemTask = Task {
// classic.ActorSystem(
// name = "FXActorSystem"
// )
// }
implicit lazy val defaultScheduler: Scheduler = schedulers.fx
// implicit lazy val FSync = Sync[Task]
// implicit lazy val FClock = Clock[Task]
// val startTime = Task.clock
// .monotonic(scala.concurrent.duration.MILLISECONDS)
// .map(Duration.fromNanos(_))
lazy val appResource = for {
// clock <- Resource.liftF(Task(Task.clock))
logger <- consoleLogger().withAsync()
backend <- AsyncHttpClientMonixBackend.resource()
actorSystem <-
Resource.make(logger.info("Creating Actor System") >> Task {
classic.ActorSystem(
name = "FXActorSystem"
)
})(sys =>
logger.info("Shutting down actor system") >> Task.fromFuture(
sys.terminate()
) >> logger.info("Actor System terminated")
)
// _ <- Resource.liftF(logger.info(Thread.currentThread().getName()))
fxApp <- Resource.make(logger.info("Creating FX Application") >> Task {
// val appStage = makePrimaryStage(backend, actorSystem)
// stage = appStage
// val stage2 = new PrimaryStage {
// scene = new Scene(new HBox())
// }
val app: JFXApp = new JFXApp {
lazy val schedulers: Schedulers = new Schedulers()
lazy val backendTask = AsyncHttpClientMonixBackend()
lazy val actorSystemTask = Task {
classic.ActorSystem(
name = "FXActorSystem"
)
}
implicit lazy val defaultScheduler: Scheduler = schedulers.fx
lazy val application = for {
_ <- logger.info("Starting application..")
backend <- backendTask
actorSystem <- actorSystemTask
// to spawn child actors
// _ <- Task { actorSystem.spawn() }
appStage <- Task { makePrimaryStage(backend, actorSystem) }
// splash screen
_ <- Task {
// this stage refers to implicit jfx stage
// makes this impure, but I can't think of a better way right now
stage = appStage
}
// wait 2 seconds before showing home screen
d <- deps
fib1 <- d.send().start
_ <- Task.sleep(2.seconds)
_ <- Task {
// appStage.maximized = true
appStage.height = 800
appStage.width = 800
appStage
.scene()
.setRoot(
LoginPage(appStage, backend, actorSystem)
)
}
// _ <- fib1.join
} yield ()
application.timed.runToFuture
.onComplete(res =>
res match {
case Failure(exception) => {
println("Application start failed. Reason -")
exception.printStackTrace()
}
case Success((duration, _)) =>
println(
s"Application started successfully in ${duration.toSeconds} seconds"
val application =
for {
appStage <- logger.info("Inside JFX application stage") >> Task(
makePrimaryStage(backend, actorSystem)
)
_ <- Task { stage = appStage }
_ <- Task.sleep(2.seconds)
loginScene <- LoginPage(appStage, backend, actorSystem)
_ <- Task {
// appStage.maximized = true
appStage.height = 800
appStage.width = 800
appStage
.scene()
.setRoot(
loginScene
)
}
} yield ()
application.timed.runAsync(
new Callback[Throwable, (FiniteDuration, Unit)] {
override def onSuccess(value: (FiniteDuration, Unit)): Unit = {
val (duration, _) = value
println(
s"Application started successfully in ${duration.toSeconds} seconds"
)
}
override def onError(e: Throwable): Unit = {
println("Application start failed. Reason -")
e.printStackTrace()
}
}
)
}
)
// Task
// .suspend {
// val program = Task {
// stage = new PrimaryStage {
// // initStyle(StageStyle.Unified)
// title = "ScalaFX Hello World"
// scene = defaultUI.scene
// }
// }
// val backendResource = AsyncHttpClientMonixBackend
// .resource()
// .use { implicit backend =>
// Task
// .suspend(
// (for {
// req <-
// basicRequest
// .get(uri"https://httpbin.org/get")
// .response(asJson[HttpBinResponse])
// .send()
// } yield println(req)) >>
// Task(println(Thread.currentThread().getName()))
// )
// // .delayExecution(1.second)
// }
// .executeOn(Scheduler.global)
// val akkaResource = Resource
// .make(Task {
// classic.ActorSystem(
// name = "FXActorSystem"
// )
// })(sys => Task(println("Shutting down actor system")) >> Task(sys.terminate()))
// .use { implicit system =>
// // system.spa
// // system.typed
// // val javaFxActor = system.actorOf(
// // Props[JavaFxActor]().withDispatcher("javafx-dispatcher"),
// // "javaFxActor"
// // )
// // val swingActor = system.actorOf(
// // Props[SwingActor]().withDispatcher("swing-dispatcher"),
// // "swingActor"
// // )
// Task.unit
// }
// .delayExecution(1.second)
// backendResource.start >> akkaResource.start >>
// program.to[Task].asyncBoundary >>
// Task(println(Thread.currentThread().getName()))
// .executeOn(Scheduler.global)
// Task.parZip3(
// program.to[Task].executeOn(defaultScheduler),
// // backendResource,
// // dummyRequester.send(),
// // akkaResource,
// Task(println(Thread.currentThread().getName()))
// .executeOn(schedulers.cpu)
// )
// }
// .runToFuture
// .onComplete(res =>
// res match {
// case Failure(exception) => {
// println("Application start failed. Reason -")
// exception.printStackTrace()
// }
// case Success(value) => println("Application started Successfully")
// }
// )
// new TaskApp {
// override protected def scheduler: Scheduler =
// JFXExecutionContexts.javaFxScheduler
// override def run(args: List[String]): Task[ExitCode] =
// Task.suspend {
// Task {
// AsyncHttpClientMonixBackend().flatMap(implicit backend => {
// val req = RequestPayload("").asJson
// basicRequest.get(uri"").body(req).send()
// })
// } >>
// program.to[Task].executeOn(JFXExecutionContexts.javaFxScheduler) >>
// Task(println(Thread.currentThread().getName()))
// .executeOn(Scheduler.global) >>
// // Task.unit.asyncBoundary >>
// Task.pure(ExitCode.Success)
// }
// }
// }
// Task.sleep(3.seconds).flatMap { _ =>
//
// (for {
// req <-
// basicRequest
// .get(uri"https://httpbin.org/get")
// .response(asJson[HttpBinResponse])
// .send()
// } yield println(req)) >> Task(
// println(Thread.currentThread().getName())
// ) >>
// backend.close()
// }
//
def test(stage: Stage) = {
stage.scene().setRoot(new FlowPane())
override def stopApp() = {
Platform.exit()
// System.exit(0)
}
}
app
})(app => logger.info("Stopping FX Application") >> Task(app.stopApp()))
// _ <- Resource.liftF(Task.unit.executeOn(defaultScheduler))
_ <- Resource.liftF(logger.info(Thread.currentThread().getName()))
} yield (fxApp)
// >> logger.info("test")
appResource
.use(fxApp => Task(fxApp.main(args.toArray)))
.as(ExitCode.Success)
}
def makePrimaryStage(
backend: AppTypes.HttpBackend,
actorSystem: classic.ActorSystem
) = {
new PrimaryStage {
scene = new DefaultUI().scene
onCloseRequest = () => {
val f2 = actorSystem.terminate()
val f1 = backend.close().runToFuture
println("Closing backend")
Await.result(f1, 3.seconds)
println("Closing actor system")
println(Thread.currentThread().getName())
Await.result(f2, 3.seconds)
println("Actor system closed")
Platform.exit()
System.exit(0)
}
// onCloseRequest = () => {
// val f2 = actorSystem.terminate()
// val f1 = backend.close().runToFuture
// println("Closing backend")
// Await.result(f1, 3.seconds)
// println("Closing actor system")
// println(Thread.currentThread().getName())
// Await.result(f2, 3.seconds)
// println("Actor system closed")
// Platform.exit()
// System.exit(0)
// }
}
}
}
// class MyFxApp extends javafx.application.Application {
// override def start(stage: javafx.stage.Stage): Unit = {
// stage.show()
// }
// }

+ 69
- 24
src/main/scala/nova/monadic_sfx/pages/LoginPage.scala View File

@ -7,6 +7,9 @@ import scalafx.scene.Node
import scalafx.Includes._
import scalafx.scene.Parent
import scalafx.application.JFXApp.PrimaryStage
import nova.monadic_sfx.http.requests.DummyRequest
import monix.eval.Task
import monix.execution.Scheduler
// import io.odin.syntax._
// import _root_.monix.eval.Task
// import io.odin.monix._
@ -18,33 +21,75 @@ class LoginPage(
system: akka.actor.ActorSystem
) {
val dummyRequester = new DummyRequest(backend)
//pure function callbacks, but with side effects still
private def onLogout(stage: PrimaryStage) = {
println("logging out")
stage.scene().setRoot(render)
}
private def onLogin(stage: PrimaryStage) = {
println("logging in")
stage
.scene()
.setRoot(HomePage(backend, system, () => onLogout(appStage)))
}
private lazy val root = new VBox {
children = Seq(
new TextField {
text = "username"
editable = true
},
new TextField {
text = "password"
},
new Button {
text = "Login"
onAction = () => onLogin(appStage)
private def onLogout(stage: PrimaryStage) =
for {
_ <- Task { println("logging out") }
root <- render
_ <- Task(stage.scene().setRoot(root))
} yield ()
private def onLogin(stage: PrimaryStage) =
Task.deferAction { implicit Scheduler =>
for {
_ <- Task(println("logging in"))
root <- Task {
stage
.scene()
.setRoot(
HomePage(
backend,
system,
() => runFxTask(onLogout(appStage))
)
)
}
} yield ()
}
private lazy val root = Task.deferAction(implicit scheduler =>
Task {
new VBox {
children = Seq(
new Label {
text = "username"
},
new TextField(),
new Label {
text = "password"
},
new TextField(),
new Button {
text = "Login"
onAction = () =>
runFxTask {
Task
.parZip2(
dummyRequester
.send(),
// .executeOn(Scheduler.global)
onLogin(appStage)
)
}
}
)
}
)
}
)
def render: Task[Parent] = root
/**
* Implicitly runs monix task as fire and forget. \
* For use in ScalaFX callbacks.
*
* @param task
* @param s
*/
def runFxTask[T](task: => Task[T])(implicit s: Scheduler) = {
task.runAsyncAndForget
}
def render: Parent = root
}

+ 2
- 1
src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala View File

@ -20,7 +20,8 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
val loggers: PartialFunction[String, Logger[IO]] = {
case "some.external.package.SpecificClass" =>
consoleLogger[IO](minLevel = Level.Warn) //disable noisy external logs
case "org.asynchttpclient.netty.channel.DefaultChannelPool" =>
case asyncHttpClient
if asyncHttpClient.startsWith("org.asynchttpclient.netty") =>
consoleLogger[IO](minLevel = Level.Warn)
case _ => //if wildcard case isn't provided, default logger is no-op
consoleLogger[IO]()

Loading…
Cancel
Save