Skip to content

Commit e4a01f3

Browse files
authored
Perform follow-up refactoring for ArisaMain.kt changes (#730)
1 parent e6c0902 commit e4a01f3

7 files changed

Lines changed: 56 additions & 40 deletions

File tree

src/main/kotlin/io/github/mojira/arisa/ArisaMain.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ lateinit var jiraClient: JiraClient
1717

1818
fun main() {
1919
val configService = ConfigService()
20-
val webhookService = WebhookService(configService.config)
21-
val connectionService = JiraConnectionService(configService.config)
22-
val executionService = ExecutionService(configService.config, connectionService)
2320

21+
val webhookService = WebhookService(configService.config)
2422
webhookService.setLoggerWebhooks()
2523

24+
val connectionService = JiraConnectionService(configService.config)
2625
connectionService.connect()
2726

27+
val executionService = ExecutionService(configService.config, connectionService)
28+
2829
while (true) {
2930
val secondsToSleep = executionService.runExecutionCycle()
3031
TimeUnit.SECONDS.sleep(secondsToSleep)

src/main/kotlin/io/github/mojira/arisa/ExecutionTimeframe.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ class ExecutionTimeframe(
1313
private val openEnded: Boolean
1414
) {
1515
companion object {
16-
const val MAX_TIMEFRAME_DURATION_IN_MINUTES = 10L
16+
// Visible for testing
17+
internal const val MAX_TIMEFRAME_DURATION_IN_MINUTES = 10L
1718

1819
/**
1920
* @return An [ExecutionTimeframe] beginning at [LastRun], either until right now,
2021
* or until [MAX_TIMEFRAME_DURATION_IN_MINUTES] after [LastRun].
2122
*/
2223
fun getTimeframeFromLastRun(lastRun: LastRun): ExecutionTimeframe {
23-
// Save time before run, so nothing happening during the run is missed
2424
val currentTime = Instant.now().truncatedTo(ChronoUnit.MILLIS)
2525
val endOfMaxTimeframe = lastRun.time.plus(MAX_TIMEFRAME_DURATION_IN_MINUTES, ChronoUnit.MINUTES)
2626

@@ -39,14 +39,29 @@ class ExecutionTimeframe(
3939
}
4040
}
4141

42-
fun duration(): Duration = Duration.between(lastRunTime, currentRunTime).abs()
42+
/**
43+
* Creates a JQL query for freshly updated issues.
44+
*/
45+
fun getFreshlyUpdatedJql() =
46+
"updated > ${lastRunTime.toEpochMilli()}${capIfNotOpenEnded()}"
47+
48+
/**
49+
* Creates a JQL query for issues which have been updated in the execution timeframe, shifted to the past
50+
* by [offset].
51+
*/
52+
fun getDelayedUpdatedJql(offset: Duration): String {
53+
require(!offset.isNegative)
54+
val checkStart = lastRunTime.minus(offset)
55+
val checkEnd = currentRunTime.minus(offset)
56+
return "updated > ${checkStart.toEpochMilli()} AND updated <= ${checkEnd.toEpochMilli()}"
57+
}
4358

4459
/**
4560
* Adds a cap to a JQL query if this time frame is not open.
4661
*
4762
* @return If open ended: empty string. Otherwise: ` AND updated <= [currentRunTime]`
4863
*/
49-
fun capIfNotOpenEnded(): String =
64+
private fun capIfNotOpenEnded(): String =
5065
if (openEnded) "" else " AND updated <= ${ currentRunTime.toEpochMilli() }"
5166

5267
override fun toString(): String {

src/main/kotlin/io/github/mojira/arisa/JiraConnectionService.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ class JiraConnectionService(
6868
return if (secondsSinceLastSuccessfulConnection > MAX_SECONDS_SINCE_LAST_SUCCESSFUL_CONNECTION) {
6969
log.info("Trying to relog")
7070

71-
val exception = establishConnection() ?: run {
72-
notifyOfSuccessfulConnection()
73-
return@tryRelog RelogResult.SuccessfulRelog()
74-
}
71+
val exception = establishConnection() ?: return RelogResult.SuccessfulRelog()
7572

7673
val relogResult = RelogResult.UnsucessfulRelog()
7774
log.error(

src/main/kotlin/io/github/mojira/arisa/registry/DelayedModuleRegistry.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@ import com.uchuhimo.konf.Config
44
import io.github.mojira.arisa.ExecutionTimeframe
55
import io.github.mojira.arisa.infrastructure.config.Arisa
66
import io.github.mojira.arisa.modules.DuplicateMessageModule
7-
import java.time.temporal.ChronoUnit
7+
import java.time.Duration
88

99
/**
1010
* This class is the registry for modules that get executed `commentDelayMinutes` after the ticket has been updated.
1111
*/
1212
class DelayedModuleRegistry(config: Config) : ModuleRegistry(config) {
13-
override fun getJql(timeframe: ExecutionTimeframe): String {
14-
val checkStart = timeframe.lastRunTime
15-
.minus(config[Arisa.Modules.DuplicateMessage.commentDelayMinutes], ChronoUnit.MINUTES)
16-
val checkEnd = timeframe.currentRunTime
17-
.minus(config[Arisa.Modules.DuplicateMessage.commentDelayMinutes], ChronoUnit.MINUTES)
13+
private val delayOffset = Duration.ofMinutes(config[Arisa.Modules.DuplicateMessage.commentDelayMinutes])
1814

19-
return "updated > ${checkStart.toEpochMilli()} AND updated <= ${checkEnd.toEpochMilli()}"
15+
override fun getJql(timeframe: ExecutionTimeframe): String {
16+
return timeframe.getDelayedUpdatedJql(delayOffset)
2017
}
2118

2219
init {

src/main/kotlin/io/github/mojira/arisa/registry/InstantModuleRegistry.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import io.github.mojira.arisa.modules.TransferVersionsModule
3838
*/
3939
class InstantModuleRegistry(config: Config) : ModuleRegistry(config) {
4040
override fun getJql(timeframe: ExecutionTimeframe): String {
41-
return "updated > ${ timeframe.lastRunTime.toEpochMilli() }${ timeframe.capIfNotOpenEnded() }"
41+
return timeframe.getFreshlyUpdatedJql()
4242
}
4343

4444
init {

src/main/kotlin/io/github/mojira/arisa/registry/LinkedModuleRegistry.kt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,19 @@ import com.uchuhimo.konf.Config
44
import io.github.mojira.arisa.ExecutionTimeframe
55
import io.github.mojira.arisa.infrastructure.config.Arisa
66
import io.github.mojira.arisa.modules.UpdateLinkedModule
7-
import java.time.temporal.ChronoUnit
7+
import java.time.Duration
88

99
/**
1010
* This class is the registry for the UpdateLinkedModule.
1111
* It only updates the linked field once if it's not set, and otherwise only updates it at most once per day.
1212
* This is done in order to avoid spam.
1313
*/
1414
class LinkedModuleRegistry(config: Config) : ModuleRegistry(config) {
15-
override fun getJql(timeframe: ExecutionTimeframe): String {
16-
val freshlyUpdatedJql = "updated > ${ timeframe.lastRunTime.toEpochMilli() }${ timeframe.capIfNotOpenEnded() }"
15+
private val delayOffset = Duration.ofHours(config[Arisa.Modules.UpdateLinked.updateIntervalHours])
1716

18-
val intervalEnd = timeframe.currentRunTime.minus(
19-
config[Arisa.Modules.UpdateLinked.updateIntervalHours], ChronoUnit.HOURS
20-
)
21-
val intervalStart = intervalEnd.minus(timeframe.duration())
22-
val delayedJql = "updated > ${ intervalStart.toEpochMilli() } AND updated <= ${ intervalEnd.toEpochMilli() }"
17+
override fun getJql(timeframe: ExecutionTimeframe): String {
18+
val freshlyUpdatedJql = timeframe.getFreshlyUpdatedJql()
19+
val delayedJql = timeframe.getDelayedUpdatedJql(delayOffset)
2320

2421
return "($freshlyUpdatedJql) OR ($delayedJql)"
2522
}

src/test/kotlin/io/github/mojira/arisa/ExecutionTimeframeTest.kt

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package io.github.mojira.arisa
22

33
import io.kotest.core.spec.style.StringSpec
44
import io.kotest.matchers.shouldBe
5+
import io.kotest.matchers.string.shouldNotContain
56
import java.time.Duration
67
import java.time.Instant
8+
import java.time.LocalDateTime
9+
import java.time.ZoneOffset
710
import java.time.temporal.ChronoUnit
811

912
class ExecutionTimeframeTest : StringSpec({
@@ -19,20 +22,26 @@ class ExecutionTimeframeTest : StringSpec({
1922

2023
val timeframe = ExecutionTimeframe.getTimeframeFromLastRun(lastRun)
2124

22-
val timeframeEnd = Instant.now().truncatedTo(ChronoUnit.MILLIS)
23-
2425
timeframe.lastRunTime shouldBe lastRunTime
25-
timeframe.currentRunTime.isAfter(timeframeEnd) shouldBe false
26-
timeframe.capIfNotOpenEnded() shouldBe ""
27-
timeframe.duration() shouldBe Duration.between(lastRunTime, timeframeEnd).abs()
26+
timeframe.currentRunTime.isAfter(Instant.now()) shouldBe false
27+
// Should not be capped
28+
timeframe.getFreshlyUpdatedJql() shouldNotContain " AND updated <= "
29+
30+
val delayedStart = LocalDateTime.of(2021, 1, 1, 12, 0, 0)
31+
.atZone(ZoneOffset.UTC)
32+
.toInstant()
33+
val delayedEnd = delayedStart.plus(Duration.between(timeframe.lastRunTime, timeframe.currentRunTime))
34+
val offset = Duration.between(delayedStart, timeframe.lastRunTime)
35+
// Shift timeframe to start at `offsetBaseInstant`
36+
// Note: Cannot hardcode `delayedEnd` value in string because it depends on how fast
37+
// `ExecutionTimeframe.getTimeframeFromLastRun` executes
38+
timeframe.getDelayedUpdatedJql(offset) shouldBe "updated > 1609502400000 AND updated <= ${delayedEnd.toEpochMilli()}"
2839
}
2940

3041
"getTimeframeFromLastRun should return the correct timeframe if last run was a while ago" {
31-
val offsetInMinutes = 20L
32-
33-
val lastRunTime = Instant.now()
34-
.minus(offsetInMinutes, ChronoUnit.MINUTES)
35-
.truncatedTo(ChronoUnit.MILLIS)
42+
val lastRunTime = LocalDateTime.of(2021, 1, 1, 12, 0, 0)
43+
.atZone(ZoneOffset.UTC)
44+
.toInstant()
3645

3746
val timeframeEnd = lastRunTime
3847
.plus(ExecutionTimeframe.MAX_TIMEFRAME_DURATION_IN_MINUTES, ChronoUnit.MINUTES)
@@ -46,8 +55,8 @@ class ExecutionTimeframeTest : StringSpec({
4655
val timeframe = ExecutionTimeframe.getTimeframeFromLastRun(lastRun)
4756

4857
timeframe.lastRunTime shouldBe lastRunTime
49-
timeframe.currentRunTime.isAfter(timeframeEnd) shouldBe false
50-
timeframe.capIfNotOpenEnded() shouldBe " AND updated <= ${ timeframeEnd.toEpochMilli() }"
51-
timeframe.duration() shouldBe Duration.between(lastRunTime, timeframeEnd).abs()
58+
timeframe.currentRunTime shouldBe timeframeEnd
59+
timeframe.getFreshlyUpdatedJql() shouldBe "updated > 1609502400000 AND updated <= 1609503000000"
60+
timeframe.getDelayedUpdatedJql(Duration.ofHours(1)) shouldBe "updated > 1609498800000 AND updated <= 1609499400000"
5261
}
5362
})

0 commit comments

Comments
 (0)