-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Fix some additional build reproducibility issues in ArC #53088
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,9 @@ | ||
| package io.quarkus.arc.deployment; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.TreeMap; | ||
| import java.util.function.Consumer; | ||
| import java.util.function.Function; | ||
| import java.util.function.Supplier; | ||
|
|
@@ -38,14 +39,20 @@ public class SyntheticBeansProcessor { | |
| void initStatic(ArcRecorder recorder, List<SyntheticBeanBuildItem> syntheticBeans, | ||
| BeanRegistrationPhaseBuildItem beanRegistration, BuildProducer<BeanConfiguratorBuildItem> configurators) { | ||
|
|
||
| Map<String, Function<SyntheticCreationalContext<?>, ?>> creationFunctions = new HashMap<>(); | ||
| Map<String, Supplier<ActiveResult>> checkActiveSuppliers = new HashMap<>(); | ||
|
|
||
| TreeMap<String, SyntheticBeanBuildItem> sortedBeans = new TreeMap<>(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TBH I don't understand this change. The ordering follows the ordering of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The And when calling the recorders in random order, I had sometimes some changes in the ordering.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can probably find the diff back to help showing what I was trying to fix but it will require some archeology :)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Isn't it? I thought that build steps are guaranteed to be executed in the same order 🤔.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, they are not guaranteed to run in the same order because of parallelism. But that's not the problem here. What we guarantee is that their result will be contributed in the same order to the list of build steps. Which you would think would be enough in this case, except you can have the following in a build step: which happens, and then your order is not guaranteed. I thought it would be better to enforce the order at this level rather than going through all the possible code paths creating synthetic beans and enforcing strong ordering there. I'm not working on the simple project I was working until now, I'm iterating on all the quickstarts so you have all sorts of cases. Also, I often have 3-4, sometimes 8 reproducible builds until I have one that is different. Let me know if it makes more sense :).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Basically, a build step can produce the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I have to admit that I completely missed this sentence in the javadoc of |
||
| for (SyntheticBeanBuildItem bean : syntheticBeans) { | ||
| if (bean.hasRecorderInstance() && bean.isStaticInit()) { | ||
| configureSyntheticBean(recorder, creationFunctions, checkActiveSuppliers, beanRegistration, bean); | ||
| sortedBeans.put(createName(bean.configurator()), bean); | ||
| } | ||
| } | ||
|
|
||
| Map<String, Function<SyntheticCreationalContext<?>, ?>> creationFunctions = new LinkedHashMap<>(); | ||
| Map<String, Supplier<ActiveResult>> checkActiveSuppliers = new LinkedHashMap<>(); | ||
|
|
||
| for (Map.Entry<String, SyntheticBeanBuildItem> entry : sortedBeans.entrySet()) { | ||
| configureSyntheticBean(recorder, entry.getKey(), creationFunctions, checkActiveSuppliers, beanRegistration, | ||
| entry.getValue()); | ||
| } | ||
| // Init the map of bean instances | ||
| recorder.initStaticSupplierBeans(creationFunctions, checkActiveSuppliers); | ||
| } | ||
|
|
@@ -56,14 +63,20 @@ void initStatic(ArcRecorder recorder, List<SyntheticBeanBuildItem> syntheticBean | |
| ServiceStartBuildItem initRuntime(ArcRecorder recorder, List<SyntheticBeanBuildItem> syntheticBeans, | ||
| BeanRegistrationPhaseBuildItem beanRegistration, BuildProducer<BeanConfiguratorBuildItem> configurators) { | ||
|
|
||
| Map<String, Function<SyntheticCreationalContext<?>, ?>> creationFunctions = new HashMap<>(); | ||
| Map<String, Supplier<ActiveResult>> checkActiveSuppliers = new HashMap<>(); | ||
|
|
||
| TreeMap<String, SyntheticBeanBuildItem> sortedBeans = new TreeMap<>(); | ||
| for (SyntheticBeanBuildItem bean : syntheticBeans) { | ||
| if (bean.hasRecorderInstance() && !bean.isStaticInit()) { | ||
| configureSyntheticBean(recorder, creationFunctions, checkActiveSuppliers, beanRegistration, bean); | ||
| sortedBeans.put(createName(bean.configurator()), bean); | ||
| } | ||
| } | ||
|
|
||
| Map<String, Function<SyntheticCreationalContext<?>, ?>> creationFunctions = new LinkedHashMap<>(); | ||
| Map<String, Supplier<ActiveResult>> checkActiveSuppliers = new LinkedHashMap<>(); | ||
|
|
||
| for (Map.Entry<String, SyntheticBeanBuildItem> entry : sortedBeans.entrySet()) { | ||
| configureSyntheticBean(recorder, entry.getKey(), creationFunctions, checkActiveSuppliers, beanRegistration, | ||
| entry.getValue()); | ||
| } | ||
| recorder.initRuntimeSupplierBeans(creationFunctions, checkActiveSuppliers); | ||
| return new ServiceStartBuildItem("runtime-bean-init"); | ||
| } | ||
|
|
@@ -72,18 +85,22 @@ ServiceStartBuildItem initRuntime(ArcRecorder recorder, List<SyntheticBeanBuildI | |
| void initRegular(List<SyntheticBeanBuildItem> syntheticBeans, | ||
| BeanRegistrationPhaseBuildItem beanRegistration, BuildProducer<BeanConfiguratorBuildItem> configurators) { | ||
|
|
||
| TreeMap<String, SyntheticBeanBuildItem> sortedBeans = new TreeMap<>(); | ||
| for (SyntheticBeanBuildItem bean : syntheticBeans) { | ||
| if (!bean.hasRecorderInstance()) { | ||
| configureSyntheticBean(null, null, null, beanRegistration, bean); | ||
| sortedBeans.put(createName(bean.configurator()), bean); | ||
| } | ||
| } | ||
|
|
||
| for (Map.Entry<String, SyntheticBeanBuildItem> entry : sortedBeans.entrySet()) { | ||
| configureSyntheticBean(null, entry.getKey(), null, null, beanRegistration, entry.getValue()); | ||
| } | ||
| } | ||
|
|
||
| private void configureSyntheticBean(ArcRecorder recorder, | ||
| private void configureSyntheticBean(ArcRecorder recorder, String name, | ||
| Map<String, Function<SyntheticCreationalContext<?>, ?>> creationFunctions, | ||
| Map<String, Supplier<ActiveResult>> checkActiveSuppliers, BeanRegistrationPhaseBuildItem beanRegistration, | ||
| SyntheticBeanBuildItem bean) { | ||
| String name = createName(bean.configurator()); | ||
| if (bean.configurator().getRuntimeValue() != null) { | ||
| creationFunctions.put(name, recorder.createFunction(bean.configurator().getRuntimeValue())); | ||
| } else if (bean.configurator().getSupplier() != null) { | ||
|
|
||


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.
@gsmet Are you sure this helps? Because
Collectors.toSet()is an unordered collector...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.
+1, this itself is useless AFAICT
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.
So, it helped, I did numerous runs, but I agree it might have been by luck and I need to make the Set an ordered one.