Skip to content

Commit 666de2c

Browse files
authored
Merge pull request #106 from Cognifide/await-improvements
Await improvements
2 parents 01d2b94 + bd65d83 commit 666de2c

6 files changed

Lines changed: 124 additions & 30 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group 'com.cognifide.gradle'
9-
version '2.0.18'
9+
version '2.0.19'
1010
description = 'Gradle AEM Plugin'
1111
defaultTasks = ['clean', 'publishToMavenLocal']
1212

src/main/kotlin/com/cognifide/gradle/aem/base/api/AemConfig.kt

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.cognifide.gradle.aem.base.api
22

3-
import com.cognifide.gradle.aem.instance.Instance
4-
import com.cognifide.gradle.aem.instance.InstancePlugin
5-
import com.cognifide.gradle.aem.instance.LocalInstance
6-
import com.cognifide.gradle.aem.instance.RemoteInstance
3+
import com.cognifide.gradle.aem.instance.*
74
import com.cognifide.gradle.aem.pkg.ComposeTask
85
import com.cognifide.gradle.aem.pkg.PackagePlugin
96
import com.fasterxml.jackson.annotation.JsonIgnore
@@ -253,6 +250,25 @@ open class AemConfig(project: Project) : Serializable {
253250
@Input
254251
var awaitTimes: Long = 60 * 5
255252

253+
/**
254+
* If there is still some unstable instance left, then fail build except just logging warning.
255+
*/
256+
@Input
257+
var awaitFail: Boolean = true
258+
259+
/**
260+
* Number of intervals / additional instance stability checks to assure all stable instances.
261+
*/
262+
@Input
263+
var awaitAssurances: Long = 1
264+
265+
/**
266+
* Hook for customizing condition being an instance stability check.
267+
*/
268+
@Internal
269+
@get:JsonIgnore
270+
var awaitCondition: (InstanceState) -> Boolean = { it.stable }
271+
256272
/**
257273
* Satisfy is a lazy task, which means that it will not install package that is already installed.
258274
* By default, information about currently installed packages is being retrieved from AEM only once.
@@ -263,9 +279,12 @@ open class AemConfig(project: Project) : Serializable {
263279
@Input
264280
var satisfyRefreshing: Boolean = false
265281

282+
/**
283+
* @see <https://github.com/Cognifide/gradle-aem-plugin/issues/95>
284+
*/
266285
@Incubating
267286
@Input
268-
var testClasspathArchive: Boolean = true
287+
var testClasspathJarIncluded: Boolean = true
269288

270289
/**
271290
* Initialize defaults that depends on concrete type of project.

src/main/kotlin/com/cognifide/gradle/aem/instance/BundleState.kt

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.cognifide.gradle.aem.instance
22

33
import com.cognifide.gradle.aem.internal.Formats
4+
import com.cognifide.gradle.aem.internal.Patterns
45
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
56
import com.fasterxml.jackson.annotation.JsonProperty
67
import com.fasterxml.jackson.databind.ObjectMapper
@@ -34,7 +35,7 @@ class BundleState private constructor() {
3435
lateinit var stats: List<Int>
3536

3637
val stable: Boolean
37-
get() = status.endsWith("- all ${bundles.size} bundles active.")
38+
get() = !unknown && bundles.all { it.active }
3839

3940
val total: Int
4041
get() = stats[0]
@@ -51,12 +52,37 @@ class BundleState private constructor() {
5152
val installedBundles: Int
5253
get() = stats[4]
5354

55+
val unknown : Boolean
56+
get() = bundles.isEmpty()
57+
5458
val statsWithLabels
5559
get() = "[$total bt, $activeBundles ba, $activeFragments fa, $resolvedBundles br]"
5660

5761
val stablePercent: String
5862
get() = Formats.percent(total - (resolvedBundles + installedBundles), total)
5963

64+
/**
65+
* Checks if all bundles of matching symbolic name pattern are active.
66+
*/
67+
fun active(symbolicNames: List<String>): Boolean {
68+
return !unknown && bundles.filter { Patterns.wildcard(it.symbolicName, symbolicNames) }.all { it.active }
69+
}
70+
71+
fun active(symbolicName: String): Boolean {
72+
return active(listOf(symbolicName))
73+
}
74+
75+
/**
76+
* Checks if all bundles except these matching symbolic name pattern are active.
77+
*/
78+
fun activeIgnoring(symbolicNames: List<String>): Boolean {
79+
return !unknown && bundles.filter { !Patterns.wildcard(it.symbolicName, symbolicNames) }.all { it.active }
80+
}
81+
82+
fun activeIgnoring(symbolicName: String): Boolean {
83+
return activeIgnoring(listOf(symbolicName))
84+
}
85+
6086
override fun equals(other: Any?): Boolean {
6187
if (this === other) return true
6288
if (javaClass != other?.javaClass) return false
@@ -82,15 +108,21 @@ class BundleState private constructor() {
82108

83109
lateinit var name: String
84110

85-
lateinit var stateRaw: String
86-
87-
val state: Int
88-
get() = stateRaw.toInt()
111+
var stateRaw: Int = 0
89112

90113
lateinit var symbolicName: String
91114

92115
lateinit var version: String
93116

117+
var fragment: Boolean = false
118+
119+
val active: Boolean
120+
get() = if (fragment) {
121+
stateRaw == FRAGMENT_ACTIVE_STATE
122+
} else {
123+
stateRaw == BUNDLE_ACTIVE_STATE
124+
}
125+
94126
override fun equals(other: Any?): Boolean {
95127
if (this === other) return true
96128
if (javaClass != other?.javaClass) return false
@@ -115,6 +147,12 @@ class BundleState private constructor() {
115147
.append(version)
116148
.toHashCode()
117149
}
150+
151+
companion object {
152+
val FRAGMENT_ACTIVE_STATE = 4
153+
154+
val BUNDLE_ACTIVE_STATE = 32
155+
}
118156
}
119157

120158
}

src/main/kotlin/com/cognifide/gradle/aem/instance/Instance.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ interface Instance : Serializable {
4646
}
4747
3 -> {
4848
val (url, user, password) = parts
49-
RemoteInstance(url, user, password, ENVIRONMENT_CMD, InstanceType.byUrl(url).name)
49+
val type = InstanceType.byUrl(url).name.toLowerCase()
50+
RemoteInstance(url, user, password, ENVIRONMENT_CMD, type)
5051
}
5152
else -> {
5253
throw AemException("Cannot parse instance string: '$line'")

src/main/kotlin/com/cognifide/gradle/aem/instance/InstanceActions.kt

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class InstanceActions(val project: Project) {
1717

1818
progressLogger.started()
1919

20+
// Check if delay is configured
2021
if (config.awaitDelay > 0) {
2122
logger.info("Delaying due to pending operations on instance(s).")
2223

@@ -31,7 +32,11 @@ class InstanceActions(val project: Project) {
3132
logger.info("Checking stability of instance(s).")
3233

3334
var lastInstanceStates = -1
35+
var sinceStableTicks = -1L
36+
var sinceStableElapsed = 0L
37+
3438
Behaviors.waitUntil(config.awaitInterval, { timer ->
39+
// Gather all instance states and update checksum on any particular state change
3540
val instanceStates = instances.map { InstanceState(project, it) }
3641
if (instanceStates.hashCode() != lastInstanceStates) {
3742
lastInstanceStates = instanceStates.hashCode()
@@ -40,14 +45,35 @@ class InstanceActions(val project: Project) {
4045

4146
progressLogger.progress(progressFor(instanceStates, config, timer))
4247

48+
// Detect timeout when same checksum is not being updated so long
4349
if (config.awaitTimes > 0 && timer.ticks > config.awaitTimes) {
44-
logger.warn("Instance(s) are not stable. Timeout reached after ${Formats.duration(timer.elapsed)}")
45-
return@waitUntil false
50+
val message = "Instance(s) are not stable. Timeout reached after ${Formats.duration(timer.elapsed)}."
51+
if (config.awaitFail) {
52+
throw InstanceException(message)
53+
} else {
54+
logger.warn(message)
55+
return@waitUntil false
56+
}
4657
}
4758

48-
if (instanceStates.all { it.stable }) {
49-
logger.info("Instance(s) are stable after ${Formats.duration(timer.elapsed)}")
50-
return@waitUntil false
59+
// Verify gathered instance states
60+
if (instanceStates.all(config.awaitCondition)) {
61+
// Assure that expected moment is not accidental, remember it
62+
if (config.awaitAssurances > 0 && sinceStableTicks == -1L) {
63+
logger.info("Instance(s) seems to be stable. Assuring.")
64+
sinceStableTicks = timer.ticks
65+
sinceStableElapsed = timer.elapsed
66+
}
67+
68+
// End if assurance is not configured or this moment remains a little longer
69+
if (config.awaitAssurances <= 0 || (sinceStableTicks >= 0 && (timer.ticks - sinceStableTicks) >= config.awaitAssurances)) {
70+
logger.info("Instance(s) are stable after ${Formats.duration(sinceStableElapsed)}.")
71+
return@waitUntil false
72+
}
73+
} else {
74+
// Reset assurance, because no longer verified
75+
sinceStableTicks = -1L
76+
sinceStableElapsed = 0L
5177
}
5278

5379
true
@@ -56,27 +82,37 @@ class InstanceActions(val project: Project) {
5682
progressLogger.completed()
5783
}
5884

59-
private fun progressFor(instanceStates: List<InstanceState>, timer: Behaviors.Timer) =
60-
instanceStates.joinToString(" | ") { progressFor(it, timer.ticks, 0) }
85+
private fun progressFor(states: List<InstanceState>, timer: Behaviors.Timer) =
86+
(progressTicks(timer.ticks, 0) + " " + states.joinToString(" | ") { progressFor(it, timer.ticks) }).trim()
6187

62-
private fun progressFor(instanceStates: List<InstanceState>, config: AemConfig, timer: Behaviors.Timer) =
63-
instanceStates.joinToString(" | ") { progressFor(it, timer.ticks, config.awaitTimes) }
88+
private fun progressFor(states: List<InstanceState>, config: AemConfig, timer: Behaviors.Timer) =
89+
(progressTicks(timer.ticks, config.awaitTimes) + " " + states.joinToString(" | ") { progressFor(it, timer.ticks) }).trim()
6490

65-
private fun progressFor(it: InstanceState, tick: Long, maxTicks: Long): String {
66-
return "${it.instance.name}: ${progressIndicator(it, tick, maxTicks)} ${it.bundleState.statsWithLabels} [${it.bundleState.stablePercent}]"
91+
private fun progressFor(state: InstanceState, tick: Long): String {
92+
return "${state.instance.name}: ${progressIndicator(state, tick)} ${state.bundleState.statsWithLabels} [${state.bundleState.stablePercent}]"
6793
}
6894

69-
private fun progressIndicator(state: InstanceState, tick: Long, maxTicks: Long): String {
70-
var indicator = if (state.stable || tick.rem(2) == 0L) {
71-
"*"
95+
private fun progressTicks(tick: Long, maxTicks: Long): String {
96+
return if (maxTicks > 0 && (tick.toDouble() / maxTicks.toDouble() > 0.1)) {
97+
"[$tick/$maxTicks tt]"
7298
} else {
73-
" "
99+
""
74100
}
101+
}
75102

76-
if (maxTicks > 0 && (tick.toDouble() / maxTicks.toDouble() > 0.1)) {
77-
indicator += " [$tick/$maxTicks tt]"
103+
private fun progressIndicator(state: InstanceState, tick: Long): String {
104+
var indicator = if (tick.rem(2) == 0L) {
105+
if (state.config.awaitCondition(state)) {
106+
"+"
107+
} else {
108+
"-"
109+
}
110+
} else {
111+
" "
78112
}
79113

114+
115+
80116
return indicator
81117
}
82118

src/main/kotlin/com/cognifide/gradle/aem/pkg/jar/UpdateManifestTask.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ open class UpdateManifestTask : AemDefaultTask() {
5454
}
5555

5656
private fun configureTest() {
57-
if (config.testClasspathArchive) {
57+
if (config.testClasspathJarIncluded) {
5858
test.classpath += project.files(jar.archivePath)
5959
}
6060
}

0 commit comments

Comments
 (0)