-
-
Notifications
You must be signed in to change notification settings - Fork 636
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
[Plugin API] Add type CurrentGoals
to allow rules to find out the current running goals.
#17674
Conversation
…ut the current goal.
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'm concerned that this will break in the presence of #10542, which doesn't have many other blockers left.
Could #17671 (comment) use a flag on the request type instead?
Good point. I'll have another look with that in mind.
Ah, I'd like that, but as the linting goal would also trigger fetching all dependencies, it would still reach the visibility backend the regular way. One thing I tried (and failed, but maybe that could be fixed) was to introduce a "context value" in the rule graph, akin to how React does. Conceptual example: @rule
def context_value() -> MyContextValue:
return MyContextValue(defaultValue)
@rule
def validate_visibility_dependency_rules(ctx_value: MyContextValue, request: ...) -> ValidatedDependencies:
...
# ---
# Here I may not understand masked_types properly, my thoughts where to "replace" any previous value with a new one
@goal_rule(_masked_types=[MyContextValue])
async def visibility_linter_goal(...):
# The provided MyContextValue here is the key - I want it to replace any previous source for it with this new one.
await Get(ValidatedDependencies, {request: RequestType, ctx_value: MyContextValue})
... |
aaa50d6
to
f5274fc
Compare
@stuhood I've adjusted to implement most of the goal rule identification on the rust side of the engine, hopefully that'll work also when running goals in parallel. |
CurrentExecutingGoal
to allow rules to find out the current goal.CurrentGoals
to allow rules to find out the current running goals.
src/python/pants/engine/goal.py
Outdated
@final | ||
@classmethod | ||
def is_goal(cls) -> bool: | ||
return True |
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 should probably use is_subclass
instead rather than a new property.
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.
Agree, I can take another look at that. I tried that first and failed, but I've learned so much each day, so I may be able to pull it off this time. Perhaps :P
@@ -75,6 +75,13 @@ | |||
Workunit = Dict[str, Any] | |||
|
|||
|
|||
@dataclass(frozen=True) | |||
class CurrentGoals: | |||
"""The currently running goals.""" |
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.
"""The currently running goals.""" | |
"""The currently running goals if any.""" |
It's possible for no goals to be running: probably the intrinsic @rule
should fail in that case.
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.
Why fail? The .rule_names
could be empty in that case, is that not a valid scenario..?
class CurrentGoals: | ||
"""The currently running goals.""" | ||
|
||
rule_names: tuple[str, ...] |
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.
Should this be rule names, or the Goal.subsystem.name
?
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'd prefer the Goal.subsystem.name
but failed to figure out how to get that :P
Then again, I realized this may be more robust, or too rigid I suppose, depending on the use case. Maybe it would be nice to capture both?
src/rust/engine/src/nodes.rs
Outdated
async fn run_node(self, context: Context, workunit: &mut RunningWorkunit) -> NodeResult<Value> { | ||
let gil = Python::acquire_gil(); | ||
let py = gil.python(); | ||
let names = workunit.get_current_goals(); |
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.
Rather than doing this via workunits, you should probably make it a mutable property of the Session
, similar to the SessionValues
:
pants/src/rust/engine/src/session.rs
Lines 86 to 87 in 7f364f8
// Per-Session values that have been set for this session. | |
session_values: Mutex<PyObject>, |
Then, in run_goal_rules, you would try-finally setting and clearing the CurrentGoals
value.
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.
Ahh.. ok. Interesting. Yea, going via workunits has been a source of much headache and fiddling to tie the pieces together.
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.
But wait.. if we have that in try/finally
in the python world, that's pretty close to what I had originally only applied at a different spot, right?
Where I stored it in SessionValues
directly rather than as a property of the session, though.
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.
Hmm. Yea, it is.
I think that I was confused by the mutation in that case... I think that you could store this directly in the SessionValues
, which we already support setting? Then you don't need to mutate the CurrentGoals
type, and can get it in a normal rule from the SessionValues
via session_values[CurrentGoals]
:
options_bootstrapper = session_values[OptionsBootstrapper] |
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.
Uhm, just coming back to this again--and in my initial version I stored the CurrentExecutingGoal
type in the session values as you suggest. But I made it mutatable as my understanding is that I can't change the session values once the session has been created..?
pants/src/python/pants/bin/local_pants_runner.py
Lines 100 to 106 in aaa50d6
session_values=SessionValues( | |
{ | |
OptionsBootstrapper: options_bootstrapper, | |
CompleteEnvironmentVars: env, | |
CurrentExecutingGoal: CurrentExecutingGoal(), | |
} | |
), |
goal_param_types: ClassVar[tuple[type, ...]] = ( | ||
Specs, | ||
Console, | ||
Workspace, | ||
EnvironmentName, | ||
CurrentExecutingGoal, | ||
) |
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.
@stuhood I found this spot for it. Feels so much more appropriate than in session values! ;)
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.
Unfortunately, this will cause anything that consumes the CurrentExecutingGoal
to get a new "identity" for each goal. So if you consumed this field below a graph calculation (for example), you would end up with two copies of the graph in memory.
Happy to have a video call to talk through this if need be.
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.
Ugh. OK. Let's do that, can sync on slack.
params = Params( | ||
specs, self.console, workspace, env_name, CurrentExecutingGoal(goal, goal_product) | ||
) |
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.
regarding #10542 I think that we must still be able to provide goal specific Params
even when running multiple goals in parallel and as such this "should" be OK, no? (as it is flagged as uncachable)
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.
Yes, this is safe from a #10542 perspective. But it has the other problem I mentioned above: #17674 (comment) ... =(
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.
As discussed offline, I'm fine with this as long as it is well labeled with the caveat that any @rule
consuming the CurrentGoals
will need to re-run for different input goals.
Turns out this is a bigger caveat than I want us to swallow. Looking for alternative venues. |
Superseded by #18788 |
Example:
This is for #17671 (comment)