-
-
Notifications
You must be signed in to change notification settings - Fork 346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to watch T.input
s and interp.watchValue
s
#2489
Conversation
T.input
s and interp.watchValue
sT.input
s and interp.watchValue
s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to see the Watched
removed. But I don't get the recalc
thing yet.
@@ -43,7 +43,7 @@ trait VisualizeModule extends mill.define.TaskModule { | |||
) | |||
val visualizeThread = new java.lang.Thread(() => | |||
while (true) { | |||
val res = Result.create { | |||
val res = Result.Success{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This version does not catch exceptions and converts them into Failing
. Is this on purpose?
main/api/src/mill/api/Result.scala
Outdated
@@ -27,11 +27,14 @@ object Result { | |||
* @param value The value computed by the task. | |||
* @tparam T The result type of the computed task. | |||
*/ | |||
case class Success[+T](value: T) extends Result[T] { | |||
def map[V](f: T => V): Success[V] = Result.Success(f(value)) | |||
case class Success[+T](value: T, recalc: () => T) extends Result[T] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on the purpose of recalc
and add some API doc?
I only have a fuzzy idea how I should fill the recalc
arg of a newly created Success
.
Yeah this is still pretty rough, not totally happy with it yet
…On Tue, 2 May 2023 at 2:53 AM, Tobias Roeser ***@***.***> wrote:
***@***.**** commented on this pull request.
Happy to see the Watched removed. But I don't get the recalc thing yet.
------------------------------
In main/src/mill/main/VisualizeModule.scala
<#2489 (comment)>:
> @@ -43,7 +43,7 @@ trait VisualizeModule extends mill.define.TaskModule {
)
val visualizeThread = new java.lang.Thread(() =>
while (true) {
- val res = Result.create {
+ val res = Result.Success{
This version does not catch exceptions and converts them into Failing. Is
this on purpose?
------------------------------
In main/api/src/mill/api/Result.scala
<#2489 (comment)>:
> @@ -27,11 +27,14 @@ object Result {
* @param value The value computed by the task.
* @tparam T The result type of the computed task.
*/
- case class Success[+T](value: T) extends Result[T] {
- def map[V](f: T => V): Success[V] = Result.Success(f(value))
+ case class Success[+T](value: T, recalc: () => T) extends Result[T] {
Can you elaborate on the purpose of recalc and add some API doc?
I only have a fuzzy idea how I should fill the recalc arg of a newly
created Success.
—
Reply to this email directly, view it on GitHub
<#2489 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AE5HBDDLYKXZSKQDBPST6Z3XEABCLANCNFSM6AAAAAAXR5UAAM>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
@@ -38,8 +38,8 @@ object HelloNativeWorldTests extends TestSuite { | |||
extends Cross.ToSegments[ReleaseMode](v => List(v.toString)) | |||
|
|||
val matrix = for { | |||
scala <- Seq("3.2.1", "3.1.3", scala213, "2.12.13", "2.11.12") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this version no longer supported?
@@ -28,8 +28,8 @@ object HelloJSWorldTests extends TestSuite { | |||
} | |||
|
|||
object HelloJSWorld extends TestUtil.BaseModule { | |||
val scalaVersions = Seq("2.13.3", "3.0.0-RC1", "2.12.12", "2.11.12") | |||
val scalaJSVersions = Seq("1.8.0", "1.3.1", "1.0.1") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these versions no longer supported? AFAIK, those partly changed/extended their API, and those tests make sure we can still build against them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we could kill them, but I'll revert this and leave it for another PR
@lefou this should be ready for another round of review I think, CI is finally green |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making Evaluator even more complex will probably hit use later (at least me, as complex code tends to see less (necessary) changes), but I also think that T.input
and in general a more robust watch implementation is a very nice thing.
I was hoping, that we somehow could track watchable values directly from Evaluator and keep it in some context, as the current infrastructure you build up in MainModule
to support show
and showNamed
still looks a bit fragile and specific. I wonder whether each evaluator target needs to deal with this kind of handling at some point?
I think, this change is OK to merge.
Yeah |
T.input
s and interp.watchValue
sT.input
s and interp.watchValue
s
Fixes #838 and also fixes #909
We add the ability to re-run
T.input{...}
blocks during the polling loop, just like we re-stat theos.Paths
reported byT.source
andT.sources
. This involves some complexity, sinceT.input{...}
blocks are not just a single lambda but instead a wrapper for a part of theTask
graph that feeds into it. We capture the body ofevaluateGroup
in a lambda so we can call it laterMajor Changes
Modify
Evaluator.Results#results
from aMap[Task, Result]
toMap[Task, TaskResult]
, whereTaskResult[T]
is a wrapper ofResult[T]
that also contains arecalcOpt: Option[() => Result[T]]
callbackWrap the bulk of
Evaluator#evaluateGroup
in a function, that we evaluate once to populateTaskResult#result
and store in a callback to populateTaskResult#recalcOpt
Update
RunScript.evaluateNamed
to handleInputImpl
s, in addition to the current handling ofSourceImpl
s andSourcesImpl
s, and translate therecalcOpt
callback into aWatchable.Value
The
Watchable.Value
is then propagated toMillBuildBootstrap.evaluateWithWatches
, which ends up feeding it intoWatching.scala
where it is processed the same way as theWatchable.Value
s we get frominterp.watchValue
Overhauled the implementation of
show
; rather than returning aWatched
wrapper, we now call back tointerp.evalWatch0
to register the things we need to watch. I also consolidated the common code inshow
andshowNamed
into one shared helper.I wrapped most of the
Any
s or_
s inEvaluator
with a newcase class Val(value: Any)
wrapper. This should considerably increase type safety: e.g. you can no longer pass anOption[Val]
where aVal
was expected, unless you manually wrap it inVal(...)
which is hard to do accidentally. This makes it much easier to ensure the various data structures insideEvaluator
are passed around correctly and not mis-usedMinor Changes
Cleaned up
RunScripts
considerably, now there's only two methods left and no copy-pasty codeRemoved some
T.input
s fromMillBuildRootModule
:def unmanagedClasspath
can be aT.sources
, anddef parseBuildFiles
is now a normal target that depends onallBuildFiles
which is aT.sources
. That should improve the--watch
status message in the terminal and reduce the amount of work that needs to be done every 100ms while polling for changesTesting
Tested manually with the following
build.sc
; verified with-w bar
thatbar
re-runs every 2s, and the script re-evaluates every 10sAlso added
integration/feature/watch-source-input/
suite that starts up a--watch
in a background thread, makes changes to the files on disk, and ensures thebuild.sc
and tasks within it re-evaluate as expected.Notes
I'm not sure if the new way
show
registers watches is better than the old one. The old way withWatched
can be made to work even in failure cases if we pass it as the optional second parameter toResult.Failure
The
Val
change is not strictly necessary, and is pretty invasive. But it was very hard to make the necessary changes toEvaluator
without it due to bugs passing the wrongAny
s around. So I think it's a reasonable time to introduceVal
to support future work insideEvaluator
with increased compiler support and type safetyThe
recalc
logic would be a lot simpler ifinput
s couldn't have upstream tasks, since we could just re-run the block rather than re-evaluating the task group. I had some thoughts about restrictingT.input
s to allow this, but couldn't convince myself that was the right thing to do, so left theT.input
semantics in place and just made it work by capturing a callback that can evaluate the entire task group