Hey,

Yeah, exactly: ideally we want module-b to be resolved in different ways within 
the same reactor. I noticed that this kind of already happens (albeit in a 
simpler way): In my reproducer testing if you play with the test timeouts to 
dictate the module build order then with the same modules in the reactor you 
can get different resolution behaviour:
* If "app" builds before "module-b" has started compiling then "app" will 
resolve "module-b" from the local repo
* If "app" builds after "module-b" has compiled but before "module-b" has 
packaged then "app" will resolve the "module-b" class directory (this is the 
out-of-the-box scenario the reproducer produces)
* If "app" builds after "module-b" has packaged then "app" will resolve the 
"module-b" jar from the "module-b" target directory

So within this logic to perform different types of resolves, it would be neat 
if the reactor could perform an initial check first:
* if the dependency being resolved is within the same 'sub-build graph' of the 
module requesting the resolve then look within the reactor (current behaviour)
* otherwise, only resolve from the local repository

I don't know whether the code architecture means this is quite easy to do or 
very difficult. But to be fair, I think this extra parallelism opportunity is a 
bit of niche edge case and it probably isn't worth it if this is very complex 
to achieve (or considered a smell generally by the community!)

On 2024/02/08 Tamás Cservenák wrote
> Howdy,
> 
> Well, sadly, Maven currently has no means to make one module "this and that" 
> at the same time.
> It is either in the reactor or is out of it.
> To me, it sounds like you want one reactor, but where module-b is "out" and 
> 'in", at the same time (within same session)
> 
> 
> T
> 
> On Thu, Feb 8, 2024 at 1:27 PM Joseph Leonard < 
> joseph.leon...@alfasystems.com> wrote:
> 
> > Hey,
> > We don't need the module-b jar built in the reactor to be included in 
> > the war if the changes made in module-b won't affect the war. Instead, 
> > in this scenario, we're fine with using a jar resolved from the local 
> > repository.
> > The requisites for this scenario are:
> >
> >   *   Any change made to module-b is only in its test tree
> >   *   The only changes made to the direct and transitive dependencies of
> > module-b are to its test scoped dependencies So basically module-b is 
> > only in the reactor for verification purposes rather than ‘src 
> > packaging’ purposes.
> > Thanks,
> > Joe
> >
> > On 2024/02/08 12:12:03 Tamás Cservenák wrote:
> > > Hej,
> > >
> > > yes, basically the "hack" is well described by you:
> > > - it retains "full' reactor project
> > > - introduces "needs build" on project
> > > - when it comes to building, it skips the project if flag set
> > >
> > > This results that module-b -> app link is not lost.
> > > And as for your parallelization request: the truth is that there IS 
> > > and edge between app and module-b (via module-a), so despite 
> > > module-a is "done", its transitive module-b is not done, hence you 
> > > cannot build these two in parallel, as you do have an edge between app 
> > > and module-b.
> > >
> > > Or to invert the question: what module-b JAR you want to have 
> > > included in app WAR, when building? The one built, or the one from 
> > > the local repository? If the latter, why are you building it in the first 
> > > place?
> > >
> > > On Thu, Feb 8, 2024 at 12:06 PM Joseph Leonard < 
> > > joseph.leon...@alfasystems.com> wrote:
> > >
> > > > Hi Tamás,
> > > > Thank you for hacking around this so rapidly. I am not familiar 
> > > > with
> > the
> > > > maven code base, so let me know if I have misinterpreted the 
> > > > change: Is your hack to:
> > > >
> > > >   1.  Retain the full multi-module build dependency graph such 
> > > > that the build graph always remains consistent regardless of whether a 
> > > > “-pl”
> > arg has
> > > > been provided
> > > >   2.  Introduce a skip build option to satisfy the functionality 
> > > > of the “-pl” arg: The reactor will report the module has been 
> > > > built but the
> > build
> > > > is basically a no-op
> > > > If so, this does resolve the issue but at the cost of losing the 
> > > > opportunity to gain extra parallelism in the build.
> > > > What I was wondering may be possible (without any idea of how 
> > > > feasible
> > it
> > > > would be to implement) would be the opportunity to recognise in 
> > > > the multi-build distinct build graphs and then keep isolation in 
> > > > the
> > reactor
> > > > between these graphs. To elaborate, in the reproducer scenario 
> > > > there
> > would
> > > > be two distinct graphs:
> > > >
> > > >   *   "testsupport-module-1" followed by "app"
> > > >   *   "testsupport-module-2" followed by "module-b"
> > > > Ideally these two graphs build in parallel to each other and even 
> > > > if ultimately there is a dependency between them they NEVER 
> > > > resolve that dependency from within reactor they instead always 
> > > > resolve from the external Maven cache. The key statement here is 
> > > > that if a user
> > presents a
> > > > list of modules to be built then they really need to be sure that 
> > > > the DIRECT dependencies between these modules truly represent the 
> > > > build
> > > > graph(s) they want. For tools like gitflow-incremental-builder 
> > > > which
> > are
> > > > designed to carefully work out change sets and what needs to build 
> > > > this offers a really powerful opportunity to optimise builds. I 
> > > > appreciate
> > this
> > > > functionality could also be seen as a gotcha (although tbf this 
> > > > already exists).
> > > > Thanks,
> > > > Joe
> > > >
> > > >
> > > > On 2024/02/08 10:09:31 Tamás Cservenák wrote:
> > > > > Seems we are on track with this. To prove my last-night theory I
> > created
> > > > a
> > > > > "hack" (is really just that) and guess what?
> > > > > It makes reproducer behave "as expected":
> > > > > https://github.com/apache/maven/pull/1406
> > > > >
> > > > > T
> > > > >
> > > > > On Wed, Feb 7, 2024 at 10:05 PM Tamás Cservenák 
> > > > > <ta...@cservenak.net
> > >
> > > > wrote:
> > > > >
> > > > > > Howdy,
> > > > > >
> > > > > > Thank you very much, the reproducer works. Did not dig thru it
> > fully,
> > > > but
> > > > > > here are some related issues:
> > > > > >
> > > > > > https://issues.apache.org/jira/browse/MNG-8028 (funny thing, I
> > created
> > > > > > this few weeks ago)
> > > > > > https://issues.apache.org/jira/browse/MNG-6300
> > > > > >
> > > > > > Will report back tomorrow (EU TZ) T
> > > > > >
> > > > > >
> > > > > > On Wed, Feb 7, 2024 at 7:48 PM Joseph Leonard <
> > > > > > joseph.leon...@alfasystems.com> wrote:
> > > > > >
> > > > > >> Hi Tamás,
> > > > > >> I have created a simple example here:
> > > > > >> https://github.com/josple/mvn-multibuild-issue
> > > > > >> Hopefully the README is clear enough – let me know if I can
> > clarify
> > > > > >> anything.
> > > > > >> Thanks,
> > > > > >> Joe
> > > > > >>
> > > > > >> On 2024/02/07 17:33:08 Tamás Cservenák wrote:
> > > > > >> > Howdy,
> > > > > >> >
> > > > > >> > In that case, there is something fishy with the project, my
> > blind
> > > > guess
> > > > > >> > would be some "hidden" inter-module dependency maybe?
> > > > > >> >
> > > > > >> > Can you provide access to source, or, if not feasible, could you
> > > > provide
> > > > > >> > some reproducer and publish it on Github/Gitlab/whatever (maybe
> > even
> > > > > >> just
> > > > > >> > send it privately as ML strips off attachments and images) for
> > us
> > > > to see
> > > > > >> > this in action?
> > > > > >> >
> > > > > >> > Thanks
> > > > > >> > T
> > > > > >> >
> > > > > >> > On Wed, Feb 7, 2024 at 6:29 PM Joseph Leonard <
> > > > > >> > joseph.leon...@alfasystems.com> wrote:
> > > > > >> >
> > > > > >> > > Hi Tamás,
> > > > > >> > > We have previously played around a bit with mvnd but not
> > takari
> > > > > >> directly –
> > > > > >> > > I will have a play with it. With regards to this issue, using
> > the
> > > > > >> takari
> > > > > >> > > smart builder unfortunately doesn’t resolve the issue.
> > > > > >> > > Joe
> > > > > >> > >
> > > > > >> > > On 2024/02/07 11:41:22 Tamás Cservenák wrote:
> > > > > >> > > > Can you please try smart builder instead?
> > > > > >> > > > https://github.com/takari/takari-smart-builder
> > > > > >> > > >
> > > > > >> > > > (note: smart builder is used by mvnd as well)
> > > > > >> > > >
> > > > > >> > > > The difference between the two can be seen here:
> > > > > >> > > >
> > http://takari.io/book/30-team-maven.html#takari-smart-builder
> > > > > >> > > >
> > > > > >> > > > On Wed, Feb 7, 2024 at 11:50 AM Joseph Leonard <
> > > > > >> > > > joseph.leon...@alfasystems.com> wrote:
> > > > > >> > > >
> > > > > >> > > > > Hi Tamás,
> > > > > >> > > > > Yeah, this was unexpected to me initially as well. From
> > what I
> > > > > >> can tell
> > > > > >> > > > > the Maven reactor only considers direct dependencies
> > (i.e. not
> > > > > >> > > transitive
> > > > > >> > > > > dependencies) between the modules in the reactor when
> > working
> > > > out
> > > > > >> the
> > > > > >> > > build
> > > > > >> > > > > graph. For example if you have a simple linear dependency
> > > > chain
> > > > > >> of:
> > > > > >> > > > > One --> Two --> Three --> Four --> Five
> > > > > >> > > > > Then invoking “mvn clean verify -pl One,Two,Four,Five -T 2
> > > > will
> > > > > >> result
> > > > > >> > > in
> > > > > >> > > > > two ‘graphs’ being built in parallel ([One,Two] and
> > > > [Four,Five]).
> > > > > >> I
> > > > > >> > > assume
> > > > > >> > > > > this is as designed because it actually offers quite
> > powerful
> > > > > >> > > functionality
> > > > > >> > > > > to improve the parallelism in your build. An example of
> > where
> > > > > >> this is
> > > > > >> > > legit
> > > > > >> > > > > is when:
> > > > > >> > > > >
> > > > > >> > > > >   *   “Four” has a test scope dependency on “Five”
> > > > > >> > > > >   *   “One” has a test scoped dependency on “Two”
> > > > > >> > > > > If you made a src code change to “Five” and “Two” then it
> > > > would be
> > > > > >> > > safe to
> > > > > >> > > > > build [One,Two] and [Four,Five] in parallel because you
> > know
> > > > the
> > > > > >> > > changes
> > > > > >> > > > > within these graphs cannot impact each other.
> > > > > >> > > > > Joe
> > > > > >> > > > >
> > > > > >> > > > > On 2024/02/06 21:37:42 Tamás Cservenák wrote:
> > > > > >> > > > > > Howdy,
> > > > > >> > > > > >
> > > > > >> > > > > > To me this looks like Maven is not aware that the App
> > > > depends on
> > > > > >> > > > > ModuleB...
> > > > > >> > > > > > Are they "plain dependency" linked? Or what kind of
> > > > dependency
> > > > > >> we
> > > > > >> > > talk
> > > > > >> > > > > > about here?
> > > > > >> > > > > > In short: why would App start while ModuleB (upstream
> > dep)
> > > > is
> > > > > >> not
> > > > > >> > > done?
> > > > > >> > > > > > Something is fishy here.
> > > > > >> > > > > >
> > > > > >> > > > > > T
> > > > > >> > > > > >
> > > > > >> > > > > >
> > > > > >> > > > > > On Tue, Feb 6, 2024 at 11:40 AM Joseph Leonard <
> > > > > >> > > > > > joseph.leon...@alfasystems.com> wrote:
> > > > > >> > > > > >
> > > > > >> > > > > > > Hi all,
> > > > > >> > > > > > >
> > > > > >> > > > > > > It would be great to get any thoughts on whether the
> > > > > >> following is a
> > > > > >> > > > > defect:
> > > > > >> > > > > > >
> > > > > >> > > > > > >
> > > > > >> > > > > > > Issue details:
> > > > > >> > > > > > > tl;dr
> > > > > >> > > > > > >
> > > > > >> > > > > > > Maven can resolve dependencies either from:
> > > > > >> > > > > > >
> > > > > >> > > > > > >   *   an external repo
> > > > > >> > > > > > >   *   a class directory of a module being built
> > within the
> > > > > >> reactor
> > > > > >> > > > > > >   *   a packaged jar of a module being built within
> > the
> > > > > >> reactor
> > > > > >> > > > > > >
> > > > > >> > > > > > > If you run a concurrent multi-module build it is
> > possible
> > > > to
> > > > > >> get a
> > > > > >> > > race
> > > > > >> > > > > > > condition whereby the build of module Foo may resolve
> > > > module
> > > > > >> Bar
> > > > > >> > > from
> > > > > >> > > > > > > either of the three resolution channels. This
> > > > inconsistency
> > > > > >> can
> > > > > >> > > result
> > > > > >> > > > > in
> > > > > >> > > > > > > the Maven war plugin sometimes failing to build a
> > > > functional
> > > > > >> war
> > > > > >> > > file.
> > > > > >> > > > > I
> > > > > >> > > > > > > would expect a consistent resolution would always take
> > > > place.
> > > > > >> > > > > > >
> > > > > >> > > > > > > Full details
> > > > > >> > > > > > > Scenario
> > > > > >> > > > > > >
> > > > > >> > > > > > > Consider you have a repo with the following structure:
> > > > > >> > > > > > >
> > > > > >> > > > > > >                        App
> > > > > >> > > > > > >
> > > > > >> > > > > > >                      /     \
> > > > > >> > > > > > >
> > > > > >> > > > > > >                     /       \
> > > > > >> > > > > > >
> > > > > >> > > > > > >        (compile scope)      (test scope)
> > > > > >> > > > > > >
> > > > > >> > > > > > >                   /           \
> > > > > >> > > > > > >
> > > > > >> > > > > > >                 \/_           _\/
> > > > > >> > > > > > >
> > > > > >> > > > > > >              ModuleA      TestSupportModule1
> > > > > >> > > > > > >
> > > > > >> > > > > > >                 /
> > > > > >> > > > > > >
> > > > > >> > > > > > >                /
> > > > > >> > > > > > >
> > > > > >> > > > > > >     (compile scope)
> > > > > >> > > > > > >
> > > > > >> > > > > > >              /
> > > > > >> > > > > > >
> > > > > >> > > > > > >            \/_
> > > > > >> > > > > > >
> > > > > >> > > > > > >         ModuleB
> > > > > >> > > > > > >
> > > > > >> > > > > > >            /
> > > > > >> > > > > > >
> > > > > >> > > > > > >           /
> > > > > >> > > > > > >
> > > > > >> > > > > > >     (test scope)
> > > > > >> > > > > > >
> > > > > >> > > > > > >         /
> > > > > >> > > > > > >
> > > > > >> > > > > > >       \/_
> > > > > >> > > > > > >
> > > > > >> > > > > > > TestSupportModule2
> > > > > >> > > > > > >
> > > > > >> > > > > > > If you were to make a src code change to the following
> > > > test
> > > > > >> support
> > > > > >> > > > > > > modules:
> > > > > >> > > > > > >
> > > > > >> > > > > > >   *   TestSupportModule1
> > > > > >> > > > > > >   *   TestSupportModule2
> > > > > >> > > > > > >
> > > > > >> > > > > > > Then the minimum number of modules we need to build to
> > > > verify
> > > > > >> the
> > > > > >> > > > > change
> > > > > >> > > > > > > set is OK is:
> > > > > >> > > > > > >
> > > > > >> > > > > > >   *   TestSupportModule1
> > > > > >> > > > > > >   *   TestSupportModule2
> > > > > >> > > > > > >   *   ModuleB
> > > > > >> > > > > > >   *   App
> > > > > >> > > > > > >
> > > > > >> > > > > > > i.e. there is no requirement to build ModuleA because
> > we
> > > > know
> > > > > >> that
> > > > > >> > > > > none of
> > > > > >> > > > > > > the src code changes could impact the classpaths used
> > in
> > > > its
> > > > > >> maven
> > > > > >> > > > > build.
> > > > > >> > > > > > >
> > > > > >> > > > > > > We know that despite 'App' depending (transitively) on
> > > > ModuleB
> > > > > >> > > there
> > > > > >> > > > > is no
> > > > > >> > > > > > > need for the 'App' build to wait for ModuleB to
> > complete
> > > > its
> > > > > >> build
> > > > > >> > > > > because
> > > > > >> > > > > > > the src code change to TestSupportModule2 will not
> > impact
> > > > any
> > > > > >> of
> > > > > >> > > the
> > > > > >> > > > > > > classpaths used in the App maven build. Therefore to
> > get
> > > > the
> > > > > >> most
> > > > > >> > > > > efficient
> > > > > >> > > > > > > build possible we ideally would invoke Maven to run
> > with 2
> > > > > >> threads
> > > > > >> > > and
> > > > > >> > > > > with
> > > > > >> > > > > > > instruction to build two distinct 'dependency graphs':
> > > > > >> > > > > > >
> > > > > >> > > > > > >   *   TestSupportModule1 followed by ModuleB
> > > > > >> > > > > > >   *   TestSupportModule1 followed by App
> > > > > >> > > > > > >
> > > > > >> > > > > > > The following Maven command achieves exactly what we
> > want
> > > > > >> because
> > > > > >> > > the
> > > > > >> > > > > > > reactor build order is based only on the direct (i.e.
> > > > > >> > > non-transitive)
> > > > > >> > > > > > > dependencies of the modules provided to the reactor
> > in the
> > > > > >> build
> > > > > >> > > > > command.
> > > > > >> > > > > > > Therefore the absence of ModuleA results in two
> > distinct
> > > > > >> > > 'dependency
> > > > > >> > > > > > > graphs':
> > > > > >> > > > > > >
> > > > > >> > > > > > > mvn clean verify -pl
> > > > > >> > > TestSupportModule1,TestSupportModule2,ModuleB,App
> > > > > >> > > > > -T 2
> > > > > >> > > > > > >
> > > > > >> > > > > > > Note: In reality the code base I maintain has a very
> > large
> > > > > >> > > monobuild
> > > > > >> > > > > with
> > > > > >> > > > > > > 100s of modules and this type of build optimisation
> > makes
> > > > a
> > > > > >> > > significant
> > > > > >> > > > > > > difference to the speed of our monobuild (we use
> > > > > >> > > > > > >
> > > > > >> > > > >
> > > > > >> > >
> > > > > >>
> > > >
> > https://github.com/gitflow-incremental-builder/gitflow-incremental-builder
> > > > > >> > > > > > > to automate the logic of determining which modules to
> > > > include
> > > > > >> in
> > > > > >> > > the
> > > > > >> > > > > > > reactor based on our change set).
> > > > > >> > > > > > >
> > > > > >> > > > > > > Issue
> > > > > >> > > > > > >
> > > > > >> > > > > > > We have encountered an issue in the above scenario
> > > > because the
> > > > > >> > > 'App'
> > > > > >> > > > > build
> > > > > >> > > > > > > has a race condition with the ModuleB build which will
> > > > result
> > > > > >> in
> > > > > >> > > one
> > > > > >> > > > > of the
> > > > > >> > > > > > > following three outcomes:
> > > > > >> > > > > > >
> > > > > >> > > > > > >   *   If the 'App' build starts before the ModuleB
> > build
> > > > has
> > > > > >> > > compiled
> > > > > >> > > > > its
> > > > > >> > > > > > > src classes then the 'App' build will resolve ModuleB
> > > > from the
> > > > > >> > > external
> > > > > >> > > > > > > repo (i.e. equivalent to ModuleB not being in the
> > reactor
> > > > at
> > > > > >> all)
> > > > > >> > > > > > >   *   If the 'App' build starts after ModuleB has
> > compiled
> > > > > >> its src
> > > > > >> > > > > classes
> > > > > >> > > > > > > but before it has packaged these classes into a jar
> > then
> > > > the
> > > > > >> 'App'
> > > > > >> > > > > build
> > > > > >> > > > > > > will resolve ModuleB's target/classes directory
> > > > > >> > > > > > >   *   If the 'App' build starts after ModuleB has
> > packaged
> > > > > >> its jar
> > > > > >> > > file
> > > > > >> > > > > > > then the 'App' build will resolve ModuleB's
> > > > target/ModuleB.jar
> > > > > >> > > file.
> > > > > >> > > > > > >
> > > > > >> > > > > > > In many scenarios this dependency resolution
> > inconsistency
> > > > > >> doesn't
> > > > > >> > > > > > > represent a challenge. However, it does cause an
> > issue in
> > > > our
> > > > > >> case
> > > > > >> > > > > because
> > > > > >> > > > > > > the 'App' POM has its Maven packaging stanza
> > configured to
> > > > > >> war and
> > > > > >> > > in
> > > > > >> > > > > the
> > > > > >> > > > > > > scenario where ModuleB's target/classes directory is
> > > > resolved
> > > > > >> by
> > > > > >> > > the
> > > > > >> > > > > 'App'
> > > > > >> > > > > > > then this results in the resultant 'App' war file
> > being
> > > > > >> packaged
> > > > > >> > > with a
> > > > > >> > > > > > > completely empty ModuleB.jar file.
> > > > > >> > > > > > >
> > > > > >> > > > > > > Proposed solution
> > > > > >> > > > > > >
> > > > > >> > > > > > > Ideally we would like the Maven reactor to retain
> > > > isolation
> > > > > >> > > between the
> > > > > >> > > > > > > two distinct 'dependency graphs' it constructs at
> > > > > >> instantiation
> > > > > >> > > > > throughout
> > > > > >> > > > > > > the entire Maven build. This would mean, in the simple
> > > > example
> > > > > >> > > above,
> > > > > >> > > > > that
> > > > > >> > > > > > > the 'App' would always resolves ModuleB from the
> > external
> > > > repo
> > > > > >> > > > > (regardless
> > >
> > [message truncated...]
> >

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@maven.apache.org
For additional commands, e-mail: users-h...@maven.apache.org

Reply via email to