@@ -4,38 +4,28 @@ import groovy.transform.CompileStatic
4
4
import repo.build.ActionContext
5
5
import repo.build.ComponentDependencyGraph
6
6
import repo.build.Maven
7
- import repo.build.MavenFeature
8
7
import repo.build.RepoBuildException
9
8
10
- import java.util.concurrent.ForkJoinPool
11
- import java.util.concurrent.RecursiveTask
9
+ import java.util.concurrent.ConcurrentHashMap
10
+ import java.util.concurrent.ConcurrentMap
11
+ import java.util.concurrent.Executors
12
12
13
13
/**
14
14
* @author Markelov Ruslan markelov@jet.msk.su
15
15
*/
16
16
// @CompileStatic
17
17
class Build {
18
- Map<MavenArtifactRef , MavenComponent > componentMap
19
- Map<MavenArtifactRef , BuildTask > buildTaskMap
18
+ Collection<MavenComponent > components
20
19
ActionContext context
21
- Map<MavenArtifactRef , MavenComponent > moduleToComponentMap
22
20
23
- Build (ActionContext context , List <MavenComponent > components ) {
21
+ Build (ActionContext context , Collection <MavenComponent > components ) {
24
22
this . context = context
25
- this . componentMap = components. collectEntries {
26
- [new MavenArtifactRef (it), it]
27
- }
28
- this . moduleToComponentMap = ComponentDependencyGraph
29
- .getModuleToComponentMap(components)
30
-
31
- this . buildTaskMap = componentMap. collectEntries {
32
- [it. key, new BuildTask (it. value)]
33
- } as Map<MavenArtifactRef , BuildTask >
23
+ this . components = components
34
24
}
35
25
36
26
boolean execute (ActionContext context ) {
37
27
// check circular dependencies
38
- def graph = ComponentDependencyGraph . build(componentMap . values() )
28
+ def graph = ComponentDependencyGraph . build(components )
39
29
if (graph. hasCycles()) {
40
30
for (def entry : graph. cycleRefs) {
41
31
def component = entry. getKey()
@@ -44,62 +34,66 @@ class Build {
44
34
}
45
35
throw new RepoBuildException (" project has circular dependencies" )
46
36
}
47
- // do parallel build
48
- def pool = new ForkJoinPool (context. getParallel())
49
- return pool. invoke(new RecursiveTask<Boolean > () {
50
- @Override
51
- protected Boolean compute () {
52
- // execute all build tasks
53
- buildTaskMap. each { pool. execute(it. value) }
54
- // wait build for all components
55
- return ! componentMap
56
- .collect { buildTaskMap. get(it. key). join() }
57
- .any { it != BuildState . SUCCESS }
58
- }
59
- })
60
- }
61
-
62
- // @CompileStatic
63
- private class BuildTask extends RecursiveTask<BuildState > {
64
- MavenComponent component
65
- BuildState state
66
37
67
- BuildTask ( MavenComponent component ) {
68
- this . component = component
38
+ Map< MavenArtifactRef , MavenComponent > componentMap = components . collectEntries {
39
+ [ new MavenArtifactRef (it), it]
69
40
}
70
41
71
- protected BuildState compute () {
72
- println (" build component $component . path " )
73
- // wait build deps
74
- def isFail = component
75
- .getModules()
42
+ Map<MavenArtifactRef , BuildState > buildStates = componentMap. collectEntries {
43
+ [it. key, BuildState . NEW ]
44
+ } as Map<MavenArtifactRef , BuildState >
45
+
46
+ Map<MavenArtifactRef , MavenComponent > moduleToComponentMap =
47
+ ComponentDependencyGraph . getModuleToComponentMap(components)
48
+
49
+ ConcurrentMap<MavenArtifactRef , List<MavenArtifactRef > > buildDeps = new ConcurrentHashMap<> ()
50
+ buildStates. keySet(). forEach { MavenArtifactRef key ->
51
+ def depsTasks = componentMap. get(key). modules
76
52
.collectMany { it. dependencies }
77
53
.findAll { moduleToComponentMap. containsKey(it) }
78
54
.unique()
79
55
.collect { new MavenArtifactRef (moduleToComponentMap. get(it)) }
80
- .collect { buildTaskMap. get(it) }
81
- .findAll { it != this }
82
- .collect { println (" wait build $it . component . path " ); it. join() }
83
- .any { it != BuildState . SUCCESS }
84
- if (isFail) {
85
- state = BuildState . DEPS_ERROR
86
- context. setErrorFlag()
87
- context. addError(new RepoBuildException (" component ${ component.path} build $state " ))
88
- } else {
89
- // build component
90
- try {
91
- def pomFile = new File (component. basedir, ' pom.xml' )
92
- def p = new Properties ()
93
- Maven . execute(context, pomFile, [' clean' , ' install' ])
94
- state = BuildState . SUCCESS
95
- } catch (Exception e) {
96
- state = BuildState . ERROR
56
+ .findAll { ! key. equals(it) }
57
+ buildDeps. put(key, depsTasks)
58
+ return
59
+ }
60
+
61
+ Set<MavenArtifactRef > tasks = new HashSet<> (buildStates. keySet())
62
+
63
+ def pool = Executors . newFixedThreadPool(context. getParallel())
64
+ while (! tasks. isEmpty()) {
65
+ def iter = tasks. iterator()
66
+ while (iter. hasNext()) {
67
+ def key = iter. next()
68
+ def component = componentMap. get(key)
69
+ def deps = buildDeps. get(key)
70
+ if (! deps. any { buildStates. get(it) != BuildState . SUCCESS }) {
71
+ pool. execute {
72
+ // build component
73
+ try {
74
+ def pomFile = new File (component. basedir, ' pom.xml' )
75
+ Maven . execute(context, pomFile, [' clean' , ' install' ])
76
+ buildStates. put(key, BuildState . SUCCESS )
77
+ } catch (Exception e) {
78
+ buildStates. put(key, BuildState . ERROR )
79
+ context. setErrorFlag()
80
+ context. addError(new RepoBuildException (" component ${ component.path} build ERROR" , e))
81
+ }
82
+ }
83
+ iter. remove()
84
+ } else if (deps. any {
85
+ buildStates. get(it) == BuildState . DEPS_ERROR ||
86
+ buildStates. get(it) == BuildState . ERROR
87
+ }) {
88
+ buildStates. put(key, BuildState . DEPS_ERROR )
97
89
context. setErrorFlag()
98
- context. addError(new RepoBuildException (" component ${ component.path} build $state " , e))
90
+ context. addError(new RepoBuildException (" component ${ component.path} build DEPS_ERROR" ))
91
+ iter. remove()
99
92
}
100
93
}
101
- return state
94
+ // throttle cpu
95
+ Thread . sleep(500L )
102
96
}
97
+ return ! context. getErrorFlag()
103
98
}
104
-
105
- }
99
+ }
0 commit comments