-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce some architecture and dependency injection for status-histo…
…ry. (#47)
- Loading branch information
1 parent
d913a08
commit 4068198
Showing
33 changed files
with
1,278 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
plugins { | ||
id("net.twisterrob.blt.convention") | ||
id("org.jetbrains.kotlin.multiplatform") | ||
id("com.google.devtools.ksp") | ||
} | ||
|
||
kotlin { | ||
jvm() | ||
sourceSets { | ||
commonMain { | ||
dependencies { | ||
api(libs.kotlin.datetime) | ||
api(libs.kotlin.serialization) | ||
//implementation("io.github.oshai:kotlin-logging:6.0.1") | ||
} | ||
} | ||
commonTest { | ||
dependencies { | ||
implementation(libs.kotlin.test) | ||
implementation(libs.test.mockative) | ||
} | ||
} | ||
} | ||
} | ||
|
||
configurations | ||
.matching { Configuration it -> it.name.startsWith("ksp") && it.name.endsWith("Test") } | ||
.configureEach { Configuration it -> | ||
project.dependencies.add(it.name, libs.test.mockative.processor) | ||
} |
44 changes: 44 additions & 0 deletions
44
.../src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/DomainHistoryUseCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
import net.twisterrob.travel.domain.london.status.api.FeedParser | ||
import net.twisterrob.travel.domain.london.status.api.HistoryUseCase | ||
import net.twisterrob.travel.domain.london.status.api.ParsedStatusItem | ||
import net.twisterrob.travel.domain.london.status.api.StatusHistoryRepository | ||
import net.twisterrob.travel.domain.london.status.api.StatusInteractor | ||
|
||
class DomainHistoryUseCase( | ||
private val statusHistoryRepository: StatusHistoryRepository, | ||
private val statusInteractor: StatusInteractor, | ||
private val feedParser: FeedParser, | ||
) : HistoryUseCase { | ||
|
||
/** | ||
* @param max maximum number of items to return, current is not included in the count. | ||
* @param includeCurrent whether to include the current status in the result. | ||
*/ | ||
override fun history(feed: Feed, max: Int, includeCurrent: Boolean): List<ParsedStatusItem> { | ||
val result = mutableListOf<StatusItem>() | ||
if (includeCurrent) { | ||
result.add(statusInteractor.getCurrent(feed)) | ||
} | ||
val history = statusHistoryRepository.getAll(feed, max) | ||
result.addAll(history) | ||
return result.map { it.parse() } | ||
} | ||
|
||
private fun StatusItem.parse(): ParsedStatusItem = | ||
when (this) { | ||
is StatusItem.SuccessfulStatusItem -> { | ||
try { | ||
val feedContents = feedParser.parse(this.feed, this.content) | ||
ParsedStatusItem.ParsedFeed(this, feedContents) | ||
} catch (ex: Exception) { | ||
ParsedStatusItem.ParseFailed(this, Stacktrace(ex.stackTraceToString())) | ||
} | ||
} | ||
|
||
is StatusItem.FailedStatusItem -> { | ||
ParsedStatusItem.AlreadyFailed(this) | ||
} | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
.../src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/DomainRefreshUseCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
import net.twisterrob.travel.domain.london.status.api.RefreshResult | ||
import net.twisterrob.travel.domain.london.status.api.RefreshUseCase | ||
import net.twisterrob.travel.domain.london.status.api.StatusHistoryRepository | ||
import net.twisterrob.travel.domain.london.status.api.StatusInteractor | ||
|
||
class DomainRefreshUseCase( | ||
private val statusHistoryRepository: StatusHistoryRepository, | ||
private val statusInteractor: StatusInteractor, | ||
) : RefreshUseCase { | ||
|
||
override fun refreshLatest(feed: Feed): RefreshResult { | ||
val current = statusInteractor.getCurrent(feed) | ||
val latest = statusHistoryRepository.getAll(feed, 1).singleOrNull() | ||
|
||
return when { | ||
latest == null -> { | ||
statusHistoryRepository.add(current) | ||
RefreshResult.Created(current) | ||
} | ||
|
||
sameContent(latest, current) -> { | ||
RefreshResult.NoChange(current, latest) | ||
} | ||
|
||
sameError(latest, current) -> { | ||
RefreshResult.NoChange(current, latest) | ||
} | ||
|
||
else -> { | ||
statusHistoryRepository.add(current) | ||
RefreshResult.Refreshed(current, latest) | ||
} | ||
} | ||
} | ||
|
||
private fun sameContent(latest: StatusItem, current: StatusItem): Boolean = | ||
if (latest is StatusItem.SuccessfulStatusItem && current is StatusItem.SuccessfulStatusItem) { | ||
latest.content == current.content | ||
} else { | ||
false | ||
} | ||
|
||
private fun sameError(latest: StatusItem, current: StatusItem): Boolean = | ||
if (latest is StatusItem.FailedStatusItem && current is StatusItem.FailedStatusItem) { | ||
latest.error == current.error | ||
} else { | ||
false | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
domain/status/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/Feed.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
enum class Feed { | ||
TubeDepartureBoardsLineStatus, | ||
TubeDepartureBoardsLineStatusIncidents, | ||
} |
5 changes: 5 additions & 0 deletions
5
domain/status/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/Stacktrace.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
data class Stacktrace( | ||
val stacktrace: String, | ||
) |
5 changes: 5 additions & 0 deletions
5
.../status/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/StatusContent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
data class StatusContent( | ||
val content: String, | ||
) |
21 changes: 21 additions & 0 deletions
21
domain/status/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/StatusItem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package net.twisterrob.travel.domain.london.status | ||
|
||
import kotlinx.datetime.Instant | ||
|
||
sealed class StatusItem { | ||
|
||
abstract val retrievedDate: Instant | ||
abstract val feed: Feed | ||
|
||
data class SuccessfulStatusItem( | ||
override val feed: Feed, | ||
val content: StatusContent, | ||
override val retrievedDate: Instant, | ||
) : StatusItem() | ||
|
||
data class FailedStatusItem( | ||
override val feed: Feed, | ||
val error: Stacktrace, | ||
override val retrievedDate: Instant, | ||
) : StatusItem() | ||
} |
10 changes: 10 additions & 0 deletions
10
...status/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/api/FeedParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package net.twisterrob.travel.domain.london.status.api | ||
|
||
import net.twisterrob.travel.domain.london.status.Feed | ||
import net.twisterrob.travel.domain.london.status.StatusContent | ||
|
||
interface FeedParser { | ||
|
||
@Throws(Exception::class) | ||
fun parse(feed: Feed, content: StatusContent): Any | ||
} |
29 changes: 29 additions & 0 deletions
29
...us/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/api/HistoryUseCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package net.twisterrob.travel.domain.london.status.api | ||
|
||
import net.twisterrob.travel.domain.london.status.Feed | ||
import net.twisterrob.travel.domain.london.status.Stacktrace | ||
import net.twisterrob.travel.domain.london.status.StatusItem | ||
|
||
interface HistoryUseCase { | ||
|
||
fun history(feed: Feed, max: Int, includeCurrent: Boolean): List<ParsedStatusItem> | ||
} | ||
|
||
sealed class ParsedStatusItem { | ||
|
||
abstract val item: StatusItem | ||
|
||
data class ParsedFeed( | ||
override val item: StatusItem.SuccessfulStatusItem, | ||
val content: Any, | ||
) : ParsedStatusItem() | ||
|
||
data class AlreadyFailed( | ||
override val item: StatusItem.FailedStatusItem, | ||
) : ParsedStatusItem() | ||
|
||
data class ParseFailed( | ||
override val item: StatusItem.SuccessfulStatusItem, | ||
val error: Stacktrace, | ||
) : ParsedStatusItem() | ||
} |
26 changes: 26 additions & 0 deletions
26
...us/src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/api/RefreshUseCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package net.twisterrob.travel.domain.london.status.api | ||
|
||
import net.twisterrob.travel.domain.london.status.Feed | ||
import net.twisterrob.travel.domain.london.status.StatusItem | ||
|
||
interface RefreshUseCase { | ||
|
||
fun refreshLatest(feed: Feed): RefreshResult | ||
} | ||
|
||
sealed class RefreshResult { | ||
|
||
data class Created( | ||
val current: StatusItem, | ||
) : RefreshResult() | ||
|
||
data class Refreshed( | ||
val current: StatusItem, | ||
val latest: StatusItem, | ||
) : RefreshResult() | ||
|
||
data class NoChange( | ||
val current: StatusItem, | ||
val latest: StatusItem, | ||
) : RefreshResult() | ||
} |
11 changes: 11 additions & 0 deletions
11
...mmonMain/kotlin/net/twisterrob/travel/domain/london/status/api/StatusHistoryRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package net.twisterrob.travel.domain.london.status.api | ||
|
||
import net.twisterrob.travel.domain.london.status.Feed | ||
import net.twisterrob.travel.domain.london.status.StatusItem | ||
|
||
interface StatusHistoryRepository { | ||
|
||
fun add(current: StatusItem) | ||
|
||
fun getAll(feed: Feed, max: Int): List<StatusItem> | ||
} |
9 changes: 9 additions & 0 deletions
9
.../src/commonMain/kotlin/net/twisterrob/travel/domain/london/status/api/StatusInteractor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package net.twisterrob.travel.domain.london.status.api | ||
|
||
import net.twisterrob.travel.domain.london.status.Feed | ||
import net.twisterrob.travel.domain.london.status.StatusItem | ||
|
||
interface StatusInteractor { | ||
|
||
fun getCurrent(feed: Feed): StatusItem | ||
} |
Oops, something went wrong.