-
Notifications
You must be signed in to change notification settings - Fork 503
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
feature request: idempotentcy guards #2308
Comments
This would definitely be useful, although I wonder what the syntax and implementation would look like. One slightly weird idea which wouldn't require any new syntax would be to allow returning a specific exit code to indicate that further recipe lines should not run: foo:
test -f a.out && exit 200
cc main.c Here, returning 200 would indicate that the rest of the recipe should not run, but the recipe should still be considered to have run successfully. This is nice because the implementation is extremely simple and there's no new syntax. However, if a recipe line ever returns 200 as a bona-fide exit code, |
One possibility would be to put this behind a setting:
So the user is opting into this behavior, and will make sure none of their commands return 200 in the case of a bona-fide error. However, this would still be error prone, since in reality, users have no idea what status codes their commands return for errors. |
Syntax wise I think its just a different way of combining dependent recipes. I think the error code is a step backwards of what I'm currently doing. Let me share a snippet of a mostly real example of how I wire up/layer to do aws centric tasks just using the dependency tree.
I can keep building up the recipe tree making these mostly reusable recipes. The main thing is the user doesn't know the difference between dependent recipes and recipes I'm actually just using as guards. Its a clutter that can make that top of my Justfiles very long, and without some kind of visualization or syntax a reader has a hard time piecing it back together. Also I dont think I can dynamically adjust arguments to dependent tasks in this form, whereas a guard I'd expect it to get access to the recipes arguments and be able to adjust downstream recipes from there. Readability and dynamicism make me want the separate syntax of chef's guards. I'll also mention like Just recipes, chef's guards allowed multiple interpreters: https://docs.chef.io/resource_common/#guard-interpreters I'll also link for reference elixir's guards as they're a different, but similarly syntactically delightful form of dependent execution. |
Those examples are pretty complicated. Can you provide a simpler example, perhaps that just tests if a file exists or not, and the syntax you would propose for guards? |
Alright. so this might be the kind of issue that i just close, because I went through all the syntax again that already exists and I can see theres very few elegant ways of doing it.
I would imagine there are symmetrical |
This syntax:
Is ambiguous, since it is currently already a valid justfile, with recipes |
I appreciate your time looking at this. |
I actually think this should be left open. I'm not sure what the right syntax or implementation would be, but I think it's useful. |
Not sure I'm completely understanding this feature request, but might one possibility be something like this? -
Similarly, Advantage: flexibility. It automatically allows more than one condition check. And these condition checks can be inserted anywhere in the dependencies list, so some dependencies could run prior to a condition check if desired. Or the condition check could be in the list of subsequent dependencies, if it's gating whether something should run after the main recipe. Disadvantage: this type of condition wouldn't be able to alter queued recipes' parameters on the fly -
Although that might have workarounds (e.g. the condition recipe could write something to a file for queued recipes to read). Potential catch: With the way
Or maybe the fact this concern is even coming up indicates this syntax is a terrible idea in |
Yah, having that kind of subtle relationship between what a dependency does and what the parent recipe does is probably tricky, especially as it relates to ordering. Also, I think guards can probably always be written like so:
I think the main motivation of guards would be to avoid putting the whole recipe inside of a conditional. So I actually think that syntax like this would be nice:
Where a But, you can always switch to a shebang recipe to allow early, non-failing return:
Which is nearly as good, so maybe there really isn't much of a hole to fill. |
➡️ #2544 |
one of the handiest things in executing a dependency graph of tasks would be explicit idempotency guards.
I'm pretty sure rake had them, but Chef might have the best explanation: https://docs.chef.io/resource_common/#guards
basically they're declarations of
only_if
ornot_if
and then some chunk of executable code. If the guard passes, task runs.Very often my tasks are dominated by code that checks if they're still valid. Things like: ensuring that keys/tokens are valid and not expired before doing expensive operations to swap them out.
With guard functionality, it would be an explicit place where we could technically re-implement Makes "if this list of input files has not changed and we have an output file on disk, dont re-compile." Which would make Just finally the complete better implementation needed to put Make to rest, RIP.
The text was updated successfully, but these errors were encountered: