Skip to content

Commit cdff745

Browse files
committed
Extract votes functionality
1 parent df8aa73 commit cdff745

File tree

17 files changed

+437
-0
lines changed

17 files changed

+437
-0
lines changed

.github/workflows/default.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Default
2+
3+
on:
4+
push:
5+
branches-ignore:
6+
- master
7+
8+
jobs:
9+
test:
10+
name: Test
11+
runs-on: ubuntu-20.04
12+
steps:
13+
- uses: actions/checkout@v2
14+
- uses: actions/setup-java@v1
15+
with:
16+
java-version: 11
17+
- uses: actions/cache@v2
18+
with:
19+
path: |
20+
~/.gradle/caches
21+
~/.gradle/wrapper
22+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
23+
restore-keys: |
24+
${{ runner.os }}-gradle-
25+
- run: ./gradlew clean test
26+
- uses: actions/upload-artifact@v2
27+
if: always()
28+
with:
29+
name: test-results
30+
path: |
31+
build/test-results
32+
build/reports
33+
- run: |
34+
rm -f ~/.gradle/caches/modules-2/modules-2.lock
35+
rm -f ~/.gradle/caches/modules-2/gc.properties
36+
db-test:
37+
name: DB test
38+
runs-on: ubuntu-20.04
39+
services:
40+
localstack:
41+
image: localstack/localstack
42+
env:
43+
SERVICES: dynamodb
44+
ports:
45+
- 4566:4566
46+
env:
47+
AWS_EC2_METADATA_DISABLED: true
48+
DYNAMODB_URL: http://localhost:4566
49+
AWS_DEFAULT_REGION: us-east-2
50+
AWS_ACCESS_KEY_ID: accessKey
51+
AWS_SECRET_ACCESS_KEY: secretKey
52+
steps:
53+
- uses: actions/checkout@v2
54+
- uses: actions/setup-java@v1
55+
with:
56+
java-version: 11
57+
- uses: actions/cache@v2
58+
with:
59+
path: |
60+
~/.gradle/caches
61+
~/.gradle/wrapper
62+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
63+
restore-keys: |
64+
${{ runner.os }}-gradle-
65+
- run: votes/dynamodb/src/test/resources/seed.sh
66+
- run: ./gradlew clean dbTest
67+
- uses: actions/upload-artifact@v2
68+
if: always()
69+
with:
70+
name: test-results
71+
path: |
72+
build/test-results
73+
build/reports
74+
- run: |
75+
rm -f ~/.gradle/caches/modules-2/modules-2.lock
76+
rm -f ~/.gradle/caches/modules-2/gc.properties
77+
test-publish:
78+
name: Publish test results
79+
runs-on: ubuntu-20.04
80+
needs:
81+
- test
82+
- db-test
83+
if: always()
84+
steps:
85+
- uses: actions/download-artifact@v2
86+
with:
87+
name: test-results
88+
- run: ls -laR
89+
- uses: mikepenz/action-junit-report@v2
90+
with:
91+
report_paths: 'test-results/**/TEST-*.xml'
92+
github_token: ${{ secrets.GITHUB_TOKEN }}

build.gradle.kts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
3+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
4+
15
plugins {
26
kotlin("jvm").version("1.4.32").apply(false)
37
id("com.github.johnrengelman.shadow").version("6.1.0").apply(false)
@@ -7,4 +11,25 @@ subprojects {
711
repositories {
812
mavenCentral()
913
}
14+
15+
tasks {
16+
withType<KotlinCompile> {
17+
kotlinOptions.jvmTarget = "11"
18+
}
19+
withType<Jar> {
20+
// Workaround for https://stackoverflow.com/q/42174572/750510
21+
archiveBaseName.set(rootProject.name + "-" + this.project.path.removePrefix(":").replace(":", "-"))
22+
}
23+
withType<Test> {
24+
useJUnitPlatform {
25+
excludeTags("db")
26+
}
27+
testLogging {
28+
showStandardStreams = true
29+
}
30+
}
31+
withType<ShadowJar> {
32+
transform(Log4j2PluginsCacheFileTransformer::class.java)
33+
}
34+
}
1035
}

core/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
plugins {
2+
kotlin("jvm")
3+
}

gradle/libs.versions.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
[versions]
2+
coroutines = "1.4.3"
3+
24
aws-lambda-java-events = "3.8.0"
35
aws-lambda-java-core = "1.2.1"
46
aws-lambda-java-log4j2 = "1.2.0"
7+
awssdk = "2.16.43"
58

69
jackson = "2.12.3"
710

811
tgbotapi = "0.33.3"
912

1013
log4j = "2.14.1"
1114

15+
junit5 = "5.7.1"
16+
aws-junit5 = "6.0.1"
17+
1218
[libraries]
19+
kotlinx-coroutines-jdk8 = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-jdk8", version.ref = "coroutines" }
20+
1321
aws-lambda-java-events = { group = "com.amazonaws", name = "aws-lambda-java-events", version.ref = "aws-lambda-java-events" }
1422
aws-lambda-java-core = { group = "com.amazonaws", name = "aws-lambda-java-core", version.ref = "aws-lambda-java-core" }
1523
aws-lambda-java-log4j2 = { group = "com.amazonaws", name = "aws-lambda-java-log4j2", version.ref = "aws-lambda-java-log4j2" }
24+
dynamodb = { group = "software.amazon.awssdk", name = "dynamodb", version.ref = "awssdk" }
1625

1726
jackson-databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version.ref = "jackson" }
1827

@@ -21,6 +30,11 @@ tgbotapi-core = { group = "dev.inmo", name = "tgbotapi.core", version.ref = "tgb
2130
log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" }
2231
log4j-slf4j-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j-impl", version.ref = "log4j" }
2332

33+
junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit5" }
34+
junit-jupiter-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit5" }
35+
junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit5" }
36+
aws-junit5-dynamo-v2 = { group = "me.madhead.aws-junit5", name = "dynamo-v2", version.ref = "aws-junit5" }
37+
2438
[bundles]
2539
tgbotapi = ["tgbotapi-core"]
2640
log4j = ["log4j-core", "log4j-slf4j-impl"]

settings.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ enableFeaturePreview("VERSION_CATALOGS")
22

33
rootProject.name = "jprof_by_bot"
44

5+
include(":utils:dynamodb")
6+
include(":votes")
7+
include(":votes:dynamodb")
58
include(":runners:lambda")

utils/dynamodb/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins {
2+
kotlin("jvm")
3+
}
4+
5+
dependencies {
6+
api(libs.dynamodb)
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package by.jprof.telegram.bot.utils.dynamodb
2+
3+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
4+
5+
fun String.toAttributeValue(): AttributeValue = AttributeValue.builder().s(this).build()
6+
7+
fun List<AttributeValue>.toAttributeValue() = AttributeValue.builder().l(this).build()
8+
9+
fun Map<String, AttributeValue>.toAttributeValue() = AttributeValue.builder().m(this).build()

votes/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
plugins {
2+
kotlin("jvm")
3+
}

votes/dynamodb/build.gradle.kts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
plugins {
2+
kotlin("jvm")
3+
}
4+
5+
dependencies {
6+
api(project(":votes"))
7+
api(libs.dynamodb)
8+
implementation(project(":utils:dynamodb"))
9+
implementation(libs.kotlinx.coroutines.jdk8)
10+
11+
testImplementation(libs.junit.jupiter.api)
12+
testImplementation(libs.junit.jupiter.params)
13+
testImplementation(libs.aws.junit5.dynamo.v2)
14+
testRuntimeOnly(libs.junit.jupiter.engine)
15+
}
16+
17+
tasks {
18+
val dbTest by registering(Test::class) {
19+
group = LifecycleBasePlugin.VERIFICATION_GROUP
20+
description = "Runs the DB tests."
21+
shouldRunAfter("test")
22+
outputs.upToDateWhen { false }
23+
useJUnitPlatform {
24+
includeTags("db")
25+
}
26+
}
27+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package by.jprof.telegram.bot.votes.dynamodb.dao
2+
3+
import by.jprof.telegram.bot.utils.dynamodb.toAttributeValue
4+
import by.jprof.telegram.bot.votes.dao.VotesDAO
5+
import by.jprof.telegram.bot.votes.model.Votes
6+
import kotlinx.coroutines.Dispatchers
7+
import kotlinx.coroutines.future.await
8+
import kotlinx.coroutines.withContext
9+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient
10+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
11+
12+
@Suppress("unused")
13+
class VotesDAO(
14+
private val dynamoDb: DynamoDbAsyncClient,
15+
private val table: String
16+
) : VotesDAO {
17+
override suspend fun save(votes: Votes) {
18+
withContext(Dispatchers.IO) {
19+
dynamoDb.putItem {
20+
it.tableName(table)
21+
it.item(votes.toAttributes())
22+
}.await()
23+
}
24+
}
25+
26+
override suspend fun get(id: String): Votes? {
27+
return withContext(Dispatchers.IO) {
28+
dynamoDb.getItem {
29+
it.tableName(table)
30+
it.key(mapOf("id" to id.toAttributeValue()))
31+
}.await()?.item()?.takeUnless { it.isEmpty() }?.toVotes()
32+
}
33+
}
34+
}
35+
36+
fun Votes.toAttributes(): Map<String, AttributeValue> = mapOf(
37+
"id" to this.id.toAttributeValue(),
38+
"options" to this.options.map { it.toAttributeValue() }.toAttributeValue(),
39+
"votes" to this.votes.mapValues { (_, value) -> value.toAttributeValue() }.toAttributeValue()
40+
)
41+
42+
fun Map<String, AttributeValue>.toVotes(): Votes = Votes(
43+
id = this["id"]?.s() ?: throw IllegalStateException("Missing id property"),
44+
options = this["options"]?.l()
45+
?.mapNotNull { it.s() }
46+
?: emptyList(),
47+
votes = this["votes"]?.m()
48+
?.mapValues { (_, value) -> value.s() ?: "" }
49+
?: emptyMap()
50+
)

0 commit comments

Comments
 (0)