-
-
Notifications
You must be signed in to change notification settings - Fork 638
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 option for specifying environment variable with concurrency slot #10297
Conversation
1550a95
to
de18cc7
Compare
Interesting... is there a link to an explanation of how it's used in django? I'm not quite understanding. Also, I'm curious how this might relate to #9964 ... in that case the variable would be a hint to the process about how parallel it should try to be. |
The Django |
Note that this doesn't make tests aware of the amount of concurrency those tests are being run with, since they still know nothing about how many slots there are (although that would be easy to add purely in Python, I think). And that's fine for now! |
If we need this we could add another option to expose it under another named environment variable, in a similar way to how |
fd78926
to
5ba504f
Compare
@gshuflin : This probably shouldn't be a global toggle... rather, a setting on the |
That makes sense, but then there would need to be some way to tell tests to turn on this setting on |
Could make it an argument to the |
Or an option on Pytest? I'm not sure if you need to set this value many times, or only once gloablly. I agree with Stu's intuition to try to limit the scope to not be a global option. |
I think in practice pants users are going to want to set this once, and write their own tests with the one variable in mind. So that to me suggests that putting this as a |
Hmm, yes, setting this on every process is overkill, so an option on |
5ba504f
to
b131879
Compare
Updated this to pass the option scoped under |
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.
Thanks!
jdk_home: None, | ||
target_platform, | ||
is_nailgunnable, | ||
..original_req |
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.
Oh snap. I frequently forget that this syntax is a thing: thanks!
let mut req = Process::new(owned_string_vec(&["/bin/echo", "meoooow"])); | ||
req.timeout = one_second(); | ||
req.description = "unleash a roaring meow".to_string(); |
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 had started to add the builder pattern to Process for this usecase but... what you're doing here is probably just as easy?
pants/src/rust/engine/process_execution/src/lib.rs
Lines 263 to 271 in 3d79217
/// | |
/// Constructs a Process with default values for most fields, after which the builder pattern can | |
/// be used to set values. | |
/// | |
/// We use the more ergonomic (but possibly slightly slower) "move self for each builder method" | |
/// pattern, so this method is only enabled for test usage: production usage should construct the | |
/// Process struct wholesale. We can reconsider this if we end up with more production callsites | |
/// that require partial options. | |
/// |
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 had started to add the builder pattern to Process for this usecase but... what you're doing here is probably just as easy?
pants/src/rust/engine/process_execution/src/lib.rs
Lines 263 to 271 in 3d79217
/// /// Constructs a Process with default values for most fields, after which the builder pattern can /// be used to set values. /// /// We use the more ergonomic (but possibly slightly slower) "move self for each builder method" /// pattern, so this method is only enabled for test usage: production usage should construct the /// Process struct wholesale. We can reconsider this if we end up with more production callsites /// that require partial options. ///
It looks like there's a half-complete builder pattern in the codebase currently. It would be nice to either extend that to every option we care about, or get rid of it and just mutate member variables on Process
directly, but either way, it's out of the scope of this PR.
type=str, | ||
default="", | ||
advanced=True, | ||
help="If a non-empty string, the process execution slot id (an integer) will be exposed to tests under this environment variable 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.
Would be a bit cleaner for this to default to None
(Optional[str]
) here and in the Process
constructor, even if inside of Process
it gets converted into the empty string.
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.
Does the options type
kwarg know how to interpret modern Python typing
type annotations?
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.
No. You keep type=str
and set default=None
. The type will end up being Optional[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.
(I only looked at Python code)
type=str, | ||
default="", | ||
advanced=True, | ||
help="If a non-empty string, the process execution slot id (an integer) will be exposed to tests under this environment variable 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.
Nit: I think this might be longer than 100 characters. Appreciated if you can split this up into multiple lines. I like the style of wrapping in parentheses:
help=(
"blah blah"
"blah"
)
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.
Wouldn't this be caught by the linter if it was?
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.
Nope. We turned off the check for Flake8 because it doesn't work well with Black. Black is careful when formatting strings and doesn't touch them generally.
src/python/pants/engine/process.py
Outdated
@@ -48,6 +49,7 @@ def __init__( | |||
timeout_seconds: Optional[Union[int, float]] = None, | |||
jdk_home: Optional[str] = None, | |||
is_nailgunnable: bool = False, | |||
execution_slot_variable: 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.
Better to make this Optional[str]
. It expresses intent better. See jdk_home
as an example.
Problem
In some scenarios, pants users might want their tests to be aware of the amount of concurrency those tests are being run with. For instance, database-heavy Django tests might want to be able to reuse a limited number of databases, instead of spawning and destroying a new test database instance for every single concurrent test, which is resource-intensive.
Solution
This PR introduces the ability to optionally create a variable in the environment of a
Process
that has a numerical ID corresponding to the "slot" that thisProcess
is run under by theBoundedCommandRunner
system. The name of this environment variable is controlled by a new pants option--process-execution-slot-environment-variable
, and will not be present if this option is the empty string.The ID presented to processes via this variable comes from the
BoundedCommandRunner
, and will always be a small numerical value greater than 0 and less than or equal to the maximum amount of concurrency allowed by thatBoundedCommandRunner
instance (which in turn is set by the--process-execution-{local,remote}-parallelism
options).