I have an existing task called myTask
, whose implementation I don't control.
I want to redefine it in this way:
myTask := {
val x = prepare()
try
myTask.value
finally
cleanup(x)
}
As you probably know, this code wouldn't work, as we don't control when myTask.value
is executed.
prepare
can be called with Def.sequential()
, and cleanup
with the andFinally
construct. The only problem is how cleanup
can get the return value of prepare()
.
Def.sequential{
Def.task{
prepare()
},
myTask
}.andFinally(cleanup(???))
One workaround is to use global variables, but this is a dirty hack.
Any ideas?
I've come to the following solution that doesn't require to use any kind of the global state.
val initializer = taskKey[Int]("an initializer that makes something and returns some data")
val tryFinallyTask = taskKey[Unit]("a task that requires initializing and finalizer based on init results")
val myTask = taskKey[Unit]("your main task that can fail")
myTask := {
if(scala.util.Random.nextBoolean()) throw new Exception()
}
initializer := { scala.util.Random.nextInt() }
// the task you would like to execute in a try-finally fashion
myTask := {
if(scala.util.Random.nextBoolean) throw new Exception()
}
initializer := {
// some logic here
scala.util.Random.nextInt()
}
def finalizer(initValue: Int): Unit = {
println(s"init result is $initValue")
}
tryFinallyTask := Def.taskDyn {
Def.sequential(
initializer,
myTask.andFinally {
val initRes = initializer.value
finalizer(initRes)
}
)
}.value
tryFinallyTask
executes initializer
and then myTask
. In case if initializer
succeeds, i.e. myTask
starts execution, finalizer
logic will be executed in any case.
Some notes to the code:
Def.taskDyn
expects a Def.Initializer
of SBT task. This is the returning type of Def.sequential
as well as andFinally
.initializer.value
inside of Def.taskDyn
and pass it into the finalizer
function. Accessing the value in finalizer
will not work, since you can't use .value
outside of SBT macros.andFinally
clause, although the execution order of these tasks is not guaranteed.