Make QueryComponentSupliers independent from test classes#16275
Make QueryComponentSupliers independent from test classes#16275rohangarg merged 26 commits intoapache:masterfrom
Conversation
There was a problem hiding this comment.
Thanks a lot for the changes @kgyrtkirk 👍
Looks good overall to me, have left some comments.
Please let me know your thoughts on them
| public boolean skipVectorize = false; | ||
|
|
||
| private QueryComponentSupplier baseComponentSupplier; | ||
| public PlannerComponentSupplier basePlannerComponentSupplier = new StandardPlannerComponentSupplier(); |
There was a problem hiding this comment.
doubt : I don't understand how we removed implementing PlannerComponentSupplier interface, but still have this field in the base calcite class. How would a test class (either in open source implementations or custom forks) implement a custom planner component supplier now?
There was a problem hiding this comment.
there was a separate PR to change this; however I've came to the conclusion that whatever this PlannerComponentSupplier wanted to be - it never really started getting used.
its not used in the current master ; providing the default implementation like this is enough.
but...if it needs to be used somewhere - maybe the QueryComponentSupplier could just have a new interface method which returns the PlannerComponentSupplier stuff
There was a problem hiding this comment.
made the following changes:
- added a
QueryComponentSupplier#getPlannerComponentSuppliermethod StandardComponentSupplier#buildPlannerComponentSupplierto enable implementation to only build it onceStandardComponentSupplierSqlTestFramework#plannerFixturedoesn't anymore needPlannerComponentSupplierto be passed separetly (as its defined implicitly by theQueryComponentSupplier
I think this may make it possible to retain control over these things - custom implementation could move their custom PlannerComponentSupplier into their custom QueryComponentSupplier
| } | ||
|
|
||
|
|
||
| public File newTempFolder() |
There was a problem hiding this comment.
do we really need these? or could we just expose the temporaryFolder itself via a method?
There was a problem hiding this comment.
unfortunately yes - its kinda against the rules rules to use rules from other rules....
I feel like breaking such a thing for temporary folders is not worth it...if it would be some bigger more expensive and configurable object I would possibly try to work on it more.
we could have it in a utility class or something - maybe it could be moved into the ProjectPathUtils the other patch introduces...not sure
There was a problem hiding this comment.
altered how this is being handled by:
- replaced
temporaryFolderwithTempFolderProducer - inlined these method to invoke
tempFolderProducer.newTempFolder
| protected File createTempFolder(String prefix) | ||
| { | ||
| File tempDir = FileUtils.createTempDir(prefix); | ||
| Runtime.getRuntime().addShutdownHook(new Thread() |
There was a problem hiding this comment.
do we really need this? can this be replaced via a temporary folder or deleteOnExit?
There was a problem hiding this comment.
unfortunately deleteOnExit is kinda equiv to an unlink call - so its not recursive
https://stackoverflow.com/questions/11165253/deleting-a-directory-on-exit-in-java
| public void beforeAll(ExtensionContext context) throws Exception | ||
| { | ||
| Class<?> testClass = context.getTestClass().get(); | ||
| SqlTestFramework.SqlTestFrameWorkModule moduleAnnotation = getModuleAnnotationFor(testClass); |
There was a problem hiding this comment.
doubt : could there be a way in future to build the test framework without annotations as well? because while it does work very cleanly till now, I'm not sure how manageable it will be if more things keep getting added to the config.
Maybe annotations is the only way to deal with this, but I'm not sure.
There was a problem hiding this comment.
note: this SqlTestFramework.SqlTestFrameWorkModule annotation class will be removed in 2 patches - but it was necessary to make this patch a standalone change
in a followup the QueryComponentSupplier will be part of the SqlTestFrameWorkConfig and around the same time there will be new ways to do it as well: most importantly it will be possible to specify it in the URI as well - so quidem tests could decide which one they want to use
imply-cheddar
left a comment
There was a problem hiding this comment.
I think it overall looks generally good. But I'm scared about the lifecycle management of the Temporary folders. Lifecycle management is one of those things that comes back and bites hard in interesting ways, so I think I'd feel a lot more comfortable if we addressed that first. After that, I'm good to approve.
| import com.fasterxml.jackson.databind.SerializationFeature; | ||
| import com.google.common.collect.ImmutableList; | ||
| import com.google.inject.Injector; | ||
| import org.apache.druid.compressedbigdecimal.CompressedBigDecimalSqlAggregatorTestBase.CompressedBigDecimalComponentSupplier; |
There was a problem hiding this comment.
This is mostly just a curiousity, but isn't this importing a sub-class from this same file? That doesn't seem like it should require an import?
There was a problem hiding this comment.
yes - its an inner class; I think at some point it there could be classes share between multiple test classes
adding such imports was more-or-less just the consequence of some mechanical work needed to be done to add all these annotations
there will be a followup later which will merge this module annotation into the SqlTestFrameworkConfig ; I could try to remove them at that point.
| private TempDirProducer() | ||
| { | ||
| tempDir = FileUtils.createTempDir("druid-tempdir"); | ||
| Runtime.getRuntime().addShutdownHook(new Thread() |
There was a problem hiding this comment.
Doing the cleanup via a shutdown hook means that, unfortunate usage of this class in a JVM that's running all tests for the entire test suite could end up generating tons and tons and tons of little directory turds that don't really get cleaned up as they go along.
Also, registering an object with a shutdown hook in the constructor is kinda a sad pattern. It would be much nicer if the test framework could perhaps instantiate one of these and then clean it up as part of its own lifecycle instead of relying on an singleton instance and a shutdown hook for cleanup.
Is there a reason that we cannot create one of these and close it more cleanly than a shutdown hook?
There was a problem hiding this comment.
forgot to left a comment for this: we've discussed that there is no real need to retain this class as a singleton:
- every Supplier can have its own directory
- adding
Closeablemakes it possible to move the cleanup toclose - Suppliers can be closeable too
these changes were done :)
rohangarg
left a comment
There was a problem hiding this comment.
Thanks for the fixups @kgyrtkirk - the changes LGTM! 👍
Approving the change, will wait sometime for Eric's approval as well before merge.
imply-cheddar
left a comment
There was a problem hiding this comment.
Approving.
One Philosophical soap-box comment. The TempDirProducer class follows a lifecycle of
- Constructor does some things that require closing
- Object gets closed
Generally speaking, this pattern of getting resources in the constructor can lead to problems sometimes when you want one bit of code to create objects and another bit of code to actually use them. The lifecycle of
- Object is constructor
- Object is started
- Object is closed
Is a cleaner lifecycle. For the TempDirProducer it's not really a big deal, which is why I'm leaving this as a passing comment on the approval PR, but if this was a true business logic object, it would be better to have 3 steps.
If it is common to want to constructor AND start the object at the same time, a
public static ObjectToConstructAndStart makeAndStart(Object ...)
style static method that calls .start() before returning the object can preserve call-site simplicity.
implements QueryComponentSupplier, PlannerComponentSupplierfromBaseCalciteQueryTest- and make those methods override methods of a descendant ofStandardQueryComponentSupplierSqlFrameworkConfigfrom an annotationthis fixes the tangled dependency between the testclass and the create frameworks - as after this the framework can be created without the testclass.
I would recommend to turn on
ignore whitespaceto see the real changes - because the new inner classes have added an extra level of indentation