Skip to content

Commit 51266ee

Browse files
authored
Use a PluginContext class to extract plugin helper functions (#20)
1 parent 27b24b3 commit 51266ee

File tree

2 files changed

+157
-131
lines changed

2 files changed

+157
-131
lines changed

src/main/kotlin/com/ebay/plugins/metrics/develocity/MetricsForDevelocityPlugin.kt

Lines changed: 140 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -125,86 +125,15 @@ internal class MetricsForDevelocityPlugin @Inject constructor(
125125
}
126126
}
127127

128-
/*
129-
* Function to register an hourly gather task. This function must be re-entrant and allow for
130-
* the same task to be registered multiple times without error.
131-
*/
132-
val registerHourly: (timeSpec: String) -> TaskProvider<GatherHourlyTask> = { timeSpec ->
133-
val taskName = "$TASK_PREFIX-$timeSpec"
134-
if (project.tasks.names.contains(taskName)) {
135-
// task already exists. Return its TaskProvider.
136-
project.tasks.named(taskName, GatherHourlyTask::class.java)
137-
} else {
138-
// Task does not exist, so we need to create it.
139-
project.tasks.register(taskName, GatherHourlyTask::class.java)
140-
.also { gatherTaskProvider ->
141-
gatherTaskProvider.configure { task ->
142-
with(task) {
143-
// Never cache the current hour so that we get up-to-date data:
144-
val currentDayWithHour = currentDayWithHourProvider.get()
145-
if (timeSpec == currentDayWithHour) {
146-
with(outputs) {
147-
cacheIf("The current hour is never cached to ensure we have all data") { false }
148-
upToDateWhen { false }
149-
}
150-
}
151-
152-
val start = dateHelper.fromHourlyString(timeSpec)
153-
startProperty.set(start.toEpochMilli())
154-
endExclusiveProperty.set(
155-
start.plus(1, ChronoUnit.HOURS).toEpochMilli()
156-
)
157-
zoneIdProperty.set(ext.zoneId)
158-
queryProperty.set(ext.develocityQueryFilter)
159-
summarizersProperty.set(ext.summarizers)
160-
develocityServiceProperty.set(buildServiceProvider)
161-
outputDirectoryProperty.set(PathUtil.hourlyOutputDir(project.layout, timeSpec))
162-
usesService(buildServiceProvider)
163-
}
164-
}
165-
}
166-
}
167-
}
168-
169-
/*
170-
* Function to register an daily aggregation task. This function must be re-entrant and allow for
171-
* the same task to be registered multiple times without error.
172-
*/
173-
val registerDaily: (dateString: String) -> TaskProvider<GatherAggregateTask> = { dateString ->
174-
val taskName = "$TASK_PREFIX-$dateString"
175-
if (project.tasks.names.contains(taskName)) {
176-
// task already exists. Return its TaskProvider.
177-
project.tasks.named(taskName, GatherAggregateTask::class.java)
178-
} else {
179-
// Task does not exist, so we need to create it.
180-
project.tasks.register(taskName, GatherAggregateTask::class.java).also { taskProvider ->
181-
taskProvider.configure { task ->
182-
with(task) {
183-
val currentDayWithHour = currentDayWithHourProvider.get()
184-
val day = dateHelper.fromDailyString(dateString)
185-
for (interval in 0 until 24) {
186-
val hourInstant = day.plus(interval.toLong(), ChronoUnit.HOURS)
187-
val timeSpec = dateHelper.toHourlyString(hourInstant)
188128

189-
dependsOn(project.provider {
190-
registerHourly(timeSpec).also { hourlyProvider ->
191-
sourceOutputDirectories.from(hourlyProvider.flatMap { it.outputDirectoryProperty })
192-
}.name
193-
})
194-
195-
if (timeSpec == currentDayWithHour) {
196-
// We are processing the current day and have reached the current hour. Stop here.
197-
break
198-
}
199-
}
200-
zoneOffset.set(ext.zoneId)
201-
summarizersProperty.set(ext.summarizers)
202-
outputDirectoryProperty.set(PathUtil.dailyOutputDir(project.layout, dateString))
203-
}
204-
}
205-
}
206-
}
207-
}
129+
// Helper to allow all of this data to be easily passed into helper functions
130+
val pluginContext = PluginContext(
131+
project,
132+
buildServiceProvider,
133+
currentDayWithHourProvider,
134+
dateHelper,
135+
ext,
136+
)
208137

209138
/*
210139
* Rule to register a task for a specific date and optionally hour.
@@ -222,56 +151,10 @@ internal class MetricsForDevelocityPlugin @Inject constructor(
222151

223152
if (hour == null ) {
224153
// Daily task
225-
registerDaily(date)
154+
pluginContext.registerDaily(date)
226155
} else {
227156
// Hourly task
228-
registerHourly(timeSpec)
229-
}
230-
}
231-
232-
/*
233-
* Function to register an duration aggregation task. This function must be re-entrant and allow for
234-
* the same task to be registered multiple times without error.
235-
*/
236-
val registerDurationAggregation: (durationStr: String) -> TaskProvider<GatherAggregateTask> = { durationStr ->
237-
val duration = Duration.parse(durationStr)
238-
val currentDayWithHour = currentDayWithHourProvider.get()
239-
val endTime = dateHelper.fromHourlyString(currentDayWithHour)
240-
val startTime = endTime.minus(duration).truncatedTo(ChronoUnit.HOURS)
241-
val inputTaskProviders = generateTimeSequence(ext.zoneId.get(), startTime, endTime).map { (isHourly, dateTime) ->
242-
val dateStr = dateHelper.toDailyString(dateTime.toInstant())
243-
if (isHourly) {
244-
val timeSpec = dateHelper.toHourlyString(dateTime.toInstant())
245-
registerHourly(timeSpec)
246-
} else {
247-
registerDaily(dateStr)
248-
}
249-
}.toList()
250-
251-
val taskName = "$TASK_PREFIX-last-$durationStr"
252-
if (project.tasks.names.contains(taskName)) {
253-
// task already exists. Return its TaskProvider.
254-
project.tasks.named(taskName, GatherAggregateTask::class.java)
255-
} else {
256-
// Task does not exist, so we need to create it.
257-
project.tasks.register(taskName, GatherAggregateTask::class.java).also { taskProvider ->
258-
taskProvider.configure { task ->
259-
with(task) {
260-
inputTaskProviders.forEach { taskProvider ->
261-
sourceOutputDirectories.from(taskProvider.flatMap {
262-
if (it is MetricsIntermediateTask) {
263-
it.outputDirectoryProperty
264-
} else {
265-
throw IllegalStateException("Unexpected task type: ${it::class.java}")
266-
}
267-
})
268-
}
269-
zoneOffset.set(ext.zoneId)
270-
summarizersProperty.set(ext.summarizers)
271-
outputDirectoryProperty.set(PathUtil.durationOutputDir(project.layout, durationStr))
272-
}
273-
}
274-
}
157+
pluginContext.registerHourly(timeSpec)
275158
}
276159
}
277160

@@ -287,18 +170,144 @@ internal class MetricsForDevelocityPlugin @Inject constructor(
287170
if (!matcher.matches()) return@addRule
288171

289172
val durationStr: String = matcher.group(1)
290-
registerDurationAggregation(durationStr)
173+
pluginContext.registerDurationAggregation(durationStr)
291174
}
292175

293176
ext.extensions.create(
294177
INTERNAL_EXTENSION_NAME,
295178
MetricsForDevelocityInternalExtension::class.java,
296-
registerHourly,
297-
registerDaily,
298-
registerDurationAggregation,
179+
{ timeSpec: String -> pluginContext.registerHourly(timeSpec) },
180+
{ dateStr: String -> pluginContext.registerDaily(dateStr) },
181+
{ durationStr: String -> pluginContext.registerDurationAggregation(durationStr) },
299182
)
300183
}
301184

185+
/*
186+
* Function to register an hourly gather task. This function must be re-entrant and allow for
187+
* the same task to be registered multiple times without error.
188+
*/
189+
private fun PluginContext.registerHourly(timeSpec: String): TaskProvider<GatherHourlyTask> {
190+
val taskName = "$TASK_PREFIX-$timeSpec"
191+
return if (project.tasks.names.contains(taskName)) {
192+
// task already exists. Return its TaskProvider.
193+
project.tasks.named(taskName, GatherHourlyTask::class.java)
194+
} else {
195+
// Task does not exist, so we need to create it.
196+
project.tasks.register(taskName, GatherHourlyTask::class.java).also { gatherTaskProvider ->
197+
gatherTaskProvider.configure { task ->
198+
with(task) {
199+
// Never cache the current hour so that we get up-to-date data:
200+
val currentDayWithHour = currentDayWithHourProvider.get()
201+
if (timeSpec == currentDayWithHour) {
202+
with(outputs) {
203+
cacheIf("The current hour is never cached to ensure we have all data") { false }
204+
upToDateWhen { false }
205+
}
206+
}
207+
208+
val start = dateHelper.fromHourlyString(timeSpec)
209+
startProperty.set(start.toEpochMilli())
210+
endExclusiveProperty.set(
211+
start.plus(1, ChronoUnit.HOURS).toEpochMilli()
212+
)
213+
zoneIdProperty.set(ext.zoneId)
214+
queryProperty.set(ext.develocityQueryFilter)
215+
summarizersProperty.set(ext.summarizers)
216+
develocityServiceProperty.set(buildServiceProvider)
217+
outputDirectoryProperty.set(PathUtil.hourlyOutputDir(project.layout, timeSpec))
218+
usesService(buildServiceProvider)
219+
}
220+
}
221+
}
222+
}
223+
}
224+
225+
/*
226+
* Function to register an daily aggregation task. This function must be re-entrant and allow for
227+
* the same task to be registered multiple times without error.
228+
*/
229+
private fun PluginContext.registerDaily(dateString: String): TaskProvider<GatherAggregateTask> {
230+
val taskName = "$TASK_PREFIX-$dateString"
231+
return if (project.tasks.names.contains(taskName)) {
232+
// task already exists. Return its TaskProvider.
233+
project.tasks.named(taskName, GatherAggregateTask::class.java)
234+
} else {
235+
// Task does not exist, so we need to create it.
236+
project.tasks.register(taskName, GatherAggregateTask::class.java).also { taskProvider ->
237+
taskProvider.configure { task ->
238+
with(task) {
239+
val currentDayWithHour = currentDayWithHourProvider.get()
240+
val day = dateHelper.fromDailyString(dateString)
241+
for (interval in 0 until 24) {
242+
val hourInstant = day.plus(interval.toLong(), java.time.temporal.ChronoUnit.HOURS)
243+
val timeSpec = dateHelper.toHourlyString(hourInstant)
244+
245+
dependsOn(project.provider {
246+
registerHourly(timeSpec).also { hourlyProvider ->
247+
sourceOutputDirectories.from(hourlyProvider.flatMap { it.outputDirectoryProperty })
248+
}.name
249+
})
250+
251+
if (timeSpec == currentDayWithHour) {
252+
// We are processing the current day and have reached the current hour. Stop here.
253+
break
254+
}
255+
}
256+
zoneOffset.set(ext.zoneId)
257+
summarizersProperty.set(ext.summarizers)
258+
outputDirectoryProperty.set(PathUtil.dailyOutputDir(project.layout, dateString))
259+
}
260+
}
261+
}
262+
}
263+
}
264+
265+
/*
266+
* Function to register an duration aggregation task. This function must be re-entrant and allow for
267+
* the same task to be registered multiple times without error.
268+
*/
269+
private fun PluginContext.registerDurationAggregation(durationStr: String): TaskProvider<GatherAggregateTask> {
270+
val duration = Duration.parse(durationStr)
271+
val currentDayWithHour = currentDayWithHourProvider.get()
272+
val endTime = dateHelper.fromHourlyString(currentDayWithHour)
273+
val startTime = endTime.minus(duration).truncatedTo(ChronoUnit.HOURS)
274+
val inputTaskProviders = generateTimeSequence(ext.zoneId.get(), startTime, endTime).map { (isHourly, dateTime) ->
275+
val dateStr = dateHelper.toDailyString(dateTime.toInstant())
276+
if (isHourly) {
277+
val timeSpec = dateHelper.toHourlyString(dateTime.toInstant())
278+
registerHourly(timeSpec)
279+
} else {
280+
registerDaily(dateStr)
281+
}
282+
}.toList()
283+
284+
val taskName = "$TASK_PREFIX-last-$durationStr"
285+
return if (project.tasks.names.contains(taskName)) {
286+
// task already exists. Return its TaskProvider.
287+
project.tasks.named(taskName, GatherAggregateTask::class.java)
288+
} else {
289+
// Task does not exist, so we need to create it.
290+
project.tasks.register(taskName, GatherAggregateTask::class.java).also { taskProvider ->
291+
taskProvider.configure { task ->
292+
with(task) {
293+
inputTaskProviders.forEach { taskProvider ->
294+
sourceOutputDirectories.from(taskProvider.flatMap {
295+
if (it is MetricsIntermediateTask) {
296+
it.outputDirectoryProperty
297+
} else {
298+
throw IllegalStateException("Unexpected task type: ${it::class.java}")
299+
}
300+
})
301+
}
302+
zoneOffset.set(ext.zoneId)
303+
summarizersProperty.set(ext.summarizers)
304+
outputDirectoryProperty.set(PathUtil.durationOutputDir(project.layout, durationStr))
305+
}
306+
}
307+
}
308+
}
309+
}
310+
302311
/**
303312
* Generates a sequence of date time instances between the start and end times.
304313
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.ebay.plugins.metrics.develocity
2+
3+
import com.ebay.plugins.metrics.develocity.service.DevelocityBuildService
4+
import org.gradle.api.Project
5+
import org.gradle.api.provider.Provider
6+
7+
/**
8+
* Helper class to made it easier for the plugin to pass these individual items all at once, as parameters,
9+
* into internal function calls.
10+
*/
11+
internal data class PluginContext(
12+
val project: Project,
13+
val buildServiceProvider: Provider<DevelocityBuildService>,
14+
val currentDayWithHourProvider: Provider<String>,
15+
val dateHelper: DateHelper,
16+
val ext: MetricsForDevelocityExtension,
17+
)

0 commit comments

Comments
 (0)