Skip to content

Commit 66cbd77

Browse files
committed
Batch processing: simplify API and code cleanup
1 parent 642a084 commit 66cbd77

File tree

11 files changed

+234
-236
lines changed

11 files changed

+234
-236
lines changed

ReadMe.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ to parent size.
335335
### Batch Processing and Progress Dialog
336336

337337
Work in progress
338-
* Helper UI for running batch processing tasks, see `BatchRunnerProgressHelperDemoApp` for example of use
338+
* Helper UI for running batch processing tasks, see `BatchRunnerProgressDemoApp` for example of use
339339
* Component for display of progress of batch processing tasks, see `ProgressStatusDemoApp` for example of use
340340

341341

build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import scala.xml.{Node => XmlNode, NodeSeq => XmlNodeSeq, _}
99
// JAR_BUILT_BY - Name to be added to Jar metadata field "Built-By" (defaults to System.getProperty("user.name")
1010
//
1111

12-
val projectVersion = "0.9.0.5-SNAPSHOT"
12+
val projectVersion = "0.9.0.6-SNAPSHOT"
1313
val versionTagDir = if (projectVersion.endsWith("SNAPSHOT")) "master" else "v." + projectVersion
1414
val _scalaVersions = Seq("3.3.3", "2.13.14", "2.12.19")
1515
val _scalaVersion = _scalaVersions.head

scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/batch/BatchRunnerProgressHelperDemoApp.scala

-74
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2000-2023 Jarek Sacha. All Rights Reserved.
3+
* Author's e-mail: jpsacha at gmail.com
4+
*/
5+
6+
package org.scalafx.extras.batch
7+
8+
import org.scalafx.extras.BusyWorker
9+
import org.scalafx.extras.BusyWorker.SimpleTask
10+
import scalafx.application.JFXApp3
11+
import scalafx.application.JFXApp3.PrimaryStage
12+
import scalafx.geometry.Insets
13+
import scalafx.scene.Scene
14+
import scalafx.scene.control.{Button, Label}
15+
import scalafx.scene.layout.VBox
16+
import scalafx.stage.Window
17+
18+
import scala.util.Random
19+
20+
/**
21+
* Example of a task that for batch execution.
22+
*/
23+
private class MyTask(val i: Int) extends ItemTask[String] {
24+
25+
import MyTask.*
26+
27+
val name = s"Task #$i"
28+
29+
def run(): String =
30+
val t = minTime + new Random().nextInt(maxTime - minTime)
31+
Thread.sleep(t)
32+
if t % 6 != 0 then
33+
s"name t = $t"
34+
else
35+
throw new Exception(s"Do not like $t")
36+
}
37+
38+
object MyTask {
39+
val minTime = 500
40+
val maxTime = 1000
41+
}
42+
43+
/**
44+
* Demo of `BatchRunnerWithProgress` GUI
45+
* @author Jarek Sacha
46+
*/
47+
object BatchRunnerProgressDemoApp extends JFXApp3:
48+
49+
private lazy val busyWorker = new BusyWorker(Title, parentWindow)
50+
private val Title = "Batch Processing / Progress Dialog Demo"
51+
private val nTasks = 10
52+
53+
override def start(): Unit =
54+
stage = new PrimaryStage:
55+
title = Title
56+
scene = new Scene:
57+
content = new VBox:
58+
padding = Insets(21)
59+
spacing = 14
60+
children = Seq(
61+
new Label(
62+
s"""Press "Run x" to initiate processing.
63+
|Wait till processing finished or press "Abort".
64+
|There will be $nTasks processed.
65+
|Tasks will have randomly generated execution time,
66+
|between ${MyTask.minTime} and ${MyTask.maxTime} ms.
67+
|If task's time is divisible by 6, that task will fail.
68+
|""".stripMargin
69+
),
70+
new Button("Run as Sequence"):
71+
onAction = _ => onStart(false)
72+
prefWidth = 120
73+
,
74+
new Button("Run in Parallel"):
75+
onAction = _ => onStart(true)
76+
prefWidth = 120
77+
)
78+
79+
private def onStart(runInParallel: Boolean): Unit = busyWorker.doTask("Start") { () =>
80+
type ResultType = String
81+
val helper =
82+
new BatchRunnerWithProgress[ResultType]("Sample batch processing", Option(stage), runInParallel):
83+
def createTasks(): Seq[ItemTask[ResultType]] = (1 to nTasks).map { i => new MyTask(i) }
84+
85+
helper.run()
86+
}
87+
88+
private def parentWindow: Option[Window] = Option(stage)
89+
90+
end BatchRunnerProgressDemoApp

scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/batch/ParallelBatchRunnerDemo.scala

+21-13
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@ package org.scalafx.extras.batch
2929

3030
import scala.util.{Failure, Success}
3131

32+
import scala.util.{Failure, Success, Try}
3233

34+
/**
35+
* Example of using `ParallelBatchRunner` and `ItemTask`.
36+
* Results are printed to standard output.
37+
*
38+
* @author Jarek Sacha
39+
*/
3340
object ParallelBatchRunnerDemo {
34-
class DemoTaskItem(n: Int) extends ItemTask[Int] {
41+
private class DemoTaskItem(n: Int) extends ItemTask[Int] {
3542
val name = s"Demo TaskItem $n"
3643

3744
def run(): Int = {
@@ -46,13 +53,12 @@ object ParallelBatchRunnerDemo {
4653
}
4754
}
4855

49-
5056
def main(args: Array[String]): Unit = {
5157
val items: Seq[DemoTaskItem] = Range(0, 10).map { i => new DemoTaskItem(i) }
5258

5359
val batchHelper = new ParallelBatchRunner(items, progressUpdate, useParallelProcessing = true)
5460

55-
val results = batchHelper.execute()
61+
val results: Seq[(String, Try[Option[Int]])] = batchHelper.execute()
5662

5763
println()
5864
println("Summarize processing")
@@ -62,19 +68,21 @@ object ParallelBatchRunnerDemo {
6268
}
6369
}
6470

65-
def progressUpdate(running : Long,
66-
successful: Long,
67-
failed : Long,
68-
canceled : Long,
69-
executed : Long,
70-
total : Long,
71-
isCanceled : Boolean,
72-
perc : Double,
73-
message : String) : Unit = {
71+
@FunctionalInterface
72+
private def progressUpdate(
73+
running: Long,
74+
successful: Long,
75+
failed: Long,
76+
canceled: Long,
77+
executed: Long,
78+
total: Long,
79+
isCanceled: Boolean,
80+
perc: Double,
81+
message: String
82+
): Unit = {
7483
val m =
7584
f"R:$running%2d, S:$successful%2d, F:$failed%2d, E:$executed%2d, C:$canceled, T:$total%d, " +
7685
f"C:$isCanceled, perc:${perc.toInt}%3d, $message"
7786
println(m)
7887
}
79-
8088
}

scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/progress_dialog/ProgressStatusDemoApp.scala scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/progress_dialog/ProgressStatusDialogDemoApp.scala

+17-24
Original file line numberDiff line numberDiff line change
@@ -32,51 +32,44 @@ import org.scalafx.extras.{initFX, offFX, onFX, onFXAndWait}
3232
import scalafx.application.Platform
3333

3434
/**
35-
* Example showing use of ProgressStatusDialog
36-
*/
37-
object ProgressStatusDemoApp {
35+
* Example showing use of ProgressStatusDialog
36+
*/
37+
object ProgressStatusDialogDemoApp:
3838

3939
// TODO implement simulated processing using batch processing backend
4040

41-
def main(args: Array[String]): Unit = {
41+
def main(args: Array[String]): Unit =
4242

4343
initFX()
4444
Platform.implicitExit = true
4545

46-
val progressStatusDialog = onFXAndWait {
47-
new ProgressStatusDialog("Processing sample tasks", None)
48-
}
46+
val progressStatusDialog = onFXAndWait:
47+
new ProgressStatusDialog("Progress Status Dialog Demo", None)
4948

5049
progressStatusDialog.abortFlag.onChange { (_, _, newValue) =>
51-
if newValue then {
50+
if newValue then
5251
// Do not block UI, but wait till shutdown completed
53-
offFX {
54-
// Simulate delay due to shut down
52+
offFX:
53+
// Simulate delay due to shutdown
5554
Thread.sleep(3000)
56-
onFX {
55+
onFX:
5756
progressStatusDialog.close()
58-
}
59-
}
60-
}
6157
}
6258

63-
onFXAndWait {
59+
onFXAndWait:
6460
progressStatusDialog.show()
65-
}
61+
6662
val n = 500
67-
for i <- 1 to n if !progressStatusDialog.abortFlag.value do {
68-
onFX {
63+
for i <- 1 to n if !progressStatusDialog.abortFlag.value do
64+
onFX:
6965
progressStatusDialog.statusText.value = s"Processing item $i / $n"
7066
progressStatusDialog.progress.value = i / n.toDouble
71-
}
67+
7268
Thread.sleep(250)
73-
}
7469

7570
// In case of abort leave to abort handler o close the dialog when shutdown actions are complete
7671
if !progressStatusDialog.abortFlag.value then
77-
onFX {
72+
onFX:
7873
progressStatusDialog.close()
79-
}
80-
}
8174

82-
}
75+
end ProgressStatusDialogDemoApp

scalafx-extras/src/main/scala-3/org/scalafx/extras/batch/BatchRunner.scala

+5-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
package org.scalafx.extras.batch
2929

30-
object BatchRunner {
30+
object BatchRunner:
3131

3232
@FunctionalInterface
3333
trait ProgressUpdater:
@@ -42,14 +42,13 @@ object BatchRunner {
4242
perc: Double,
4343
message: String
4444
): Unit
45-
}
46-
trait BatchRunner[T, I <: ItemTask[T]] {
4745

48-
import BatchRunner.ProgressUpdater
46+
trait BatchRunner[T, I <: ItemTask[T]]:
47+
48+
// TODO Is BatchRunner trait needed? It is not used on its own?
4949

50-
// TODO: Is this trait needed
50+
import BatchRunner.ProgressUpdater
5151

5252
protected def itemTasks: Seq[I]
5353

5454
protected def progressUpdater: ProgressUpdater
55-
}

0 commit comments

Comments
 (0)