Skip to content

Commit 134f8b9

Browse files
committed
Support for usernames in TimeZone model
1 parent 48b5678 commit 134f8b9

File tree

8 files changed

+104
-0
lines changed

8 files changed

+104
-0
lines changed

.deploy/lambda/lib/JProfByBotStack.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ export class JProfByBotStack extends cdk.Stack {
7373
partitionKey: {name: 'userId', type: dynamodb.AttributeType.NUMBER},
7474
projectionType: dynamodb.ProjectionType.ALL,
7575
});
76+
timezonesTable.addGlobalSecondaryIndex({
77+
indexName: 'username',
78+
partitionKey: {name: 'username', type: dynamodb.AttributeType.STRING},
79+
sortKey: {name: 'chat', type: dynamodb.AttributeType.NUMBER},
80+
projectionType: dynamodb.ProjectionType.ALL,
81+
});
7682

7783
const lambdaUnpin = new lambda.Function(this, 'jprof-by-bot-lambda-unpin', {
7884
functionName: 'jprof-by-bot-lambda-unpin',

times/timezones/dynamodb/src/main/kotlin/by/jprof/telegram/bot/times/timezones/dynamodb/dao/TimeZoneDAO.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,30 @@ class TimeZoneDAO(
3636
}.await()?.item()?.takeUnless { it.isEmpty() }?.toTimeZone()
3737
}
3838
}
39+
40+
override suspend fun getByUsername(username: String, chat: Long): TimeZone? {
41+
return withContext(Dispatchers.IO) {
42+
dynamoDb.query {
43+
it.tableName(table)
44+
it.indexName("username")
45+
it.keyConditionExpression("username = :username AND chat = :chat")
46+
it.expressionAttributeValues(
47+
mapOf(
48+
":username" to username.toAttributeValue(),
49+
":chat" to chat.toAttributeValue(),
50+
)
51+
)
52+
}.await()?.items()?.firstOrNull()?.toTimeZone()
53+
}
54+
}
3955
}
4056

4157
@OptIn(ExperimentalStdlibApi::class)
4258
fun TimeZone.toAttributes(): Map<String, AttributeValue> = buildMap {
4359
put("user", this@toAttributes.user.toAttributeValue())
60+
this@toAttributes.username?.let {
61+
put("username", it.toAttributeValue())
62+
}
4463
put("chat", this@toAttributes.chat.toAttributeValue())
4564
this@toAttributes.zoneId?.let {
4665
put("zoneId", it.toAttributeValue())
@@ -52,6 +71,7 @@ fun TimeZone.toAttributes(): Map<String, AttributeValue> = buildMap {
5271

5372
fun Map<String, AttributeValue>.toTimeZone(): TimeZone = TimeZone(
5473
user = this["user"].toLong("user"),
74+
username = this["username"]?.s(),
5575
chat = this["chat"].toLong("chat"),
5676
zoneId = this["zoneId"]?.s(),
5777
offset = this["offset"]?.n()?.toInt()

times/timezones/dynamodb/src/test/kotlin/by/jprof/telegram/bot/times/timezones/dynamodb/dao/TimeZoneDAOTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,21 @@ internal class TimeZoneDAOTest {
3737
assertEquals(timeZone, sut.get(1, 1))
3838
}
3939

40+
@Test
41+
fun getByUsername() = runBlocking {
42+
assertEquals(timeZone.copy(chat = 3), sut.getByUsername("test", 3))
43+
}
44+
4045
@Test
4146
fun getUnexisting() = runBlocking {
4247
assertNull(sut.get(-1, -2))
48+
assertNull(sut.getByUsername("unexisting", -2))
4349
}
4450

4551
private val timeZone
4652
get() = TimeZone(
4753
user = 1L,
54+
username = "test",
4855
chat = 1L,
4956
zoneId = "UTC",
5057
)

times/timezones/dynamodb/src/test/kotlin/by/jprof/telegram/bot/times/timezones/dynamodb/dao/TimeZoneTest.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ internal class TimeZoneTest {
1414
)
1515
}
1616

17+
@Test
18+
fun toAttributesNoUsername() {
19+
Assertions.assertEquals(
20+
attributes.toMutableMap().apply { this.remove("username") },
21+
timeZone.copy(username = null).toAttributes()
22+
)
23+
}
24+
1725
@Test
1826
fun toAttributesNoZoneId() {
1927
Assertions.assertEquals(
@@ -38,6 +46,14 @@ internal class TimeZoneTest {
3846
)
3947
}
4048

49+
@Test
50+
fun toTimeZoneNoUsername() {
51+
Assertions.assertEquals(
52+
timeZone.copy(username = null),
53+
attributes.toMutableMap().apply { this.remove("username") }.toTimeZone(),
54+
)
55+
}
56+
4157
@Test
4258
fun toTimeZoneNoZoneId() {
4359
Assertions.assertEquals(
@@ -57,13 +73,15 @@ internal class TimeZoneTest {
5773
private val timeZone
5874
get() = TimeZone(
5975
user = 1L,
76+
username = "test",
6077
chat = 2L,
6178
zoneId = "UTC",
6279
offset = 3600,
6380
)
6481
private val attributes
6582
get() = mapOf(
6683
"user" to AttributeValue.builder().n("1").build(),
84+
"username" to AttributeValue.builder().s("test").build(),
6785
"chat" to AttributeValue.builder().n("2").build(),
6886
"zoneId" to AttributeValue.builder().s("UTC").build(),
6987
"offset" to AttributeValue.builder().n("3600").build(),

times/timezones/dynamodb/src/test/resources/timezones.items.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
"user": {
77
"N": "1"
88
},
9+
"username": {
10+
"S": "test"
11+
},
912
"chat": {
1013
"N": "1"
1114
},
@@ -21,6 +24,9 @@
2124
"user": {
2225
"N": "1"
2326
},
27+
"username": {
28+
"S": "test"
29+
},
2430
"chat": {
2531
"N": "2"
2632
},
@@ -29,6 +35,24 @@
2935
}
3036
}
3137
}
38+
},
39+
{
40+
"PutRequest": {
41+
"Item": {
42+
"user": {
43+
"N": "1"
44+
},
45+
"username": {
46+
"S": "test"
47+
},
48+
"chat": {
49+
"N": "3"
50+
},
51+
"zoneId": {
52+
"S": "UTC"
53+
}
54+
}
55+
}
3256
}
3357
]
3458
}

times/timezones/dynamodb/src/test/resources/timezones.table.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
"AttributeName": "user",
66
"AttributeType": "N"
77
},
8+
{
9+
"AttributeName": "username",
10+
"AttributeType": "S"
11+
},
812
{
913
"AttributeName": "chat",
1014
"AttributeType": "N"
@@ -20,6 +24,28 @@
2024
"KeyType": "RANGE"
2125
}
2226
],
27+
"GlobalSecondaryIndexes": [
28+
{
29+
"IndexName": "username",
30+
"KeySchema": [
31+
{
32+
"AttributeName": "username",
33+
"KeyType": "HASH"
34+
},
35+
{
36+
"AttributeName": "chat",
37+
"KeyType": "RANGE"
38+
}
39+
],
40+
"Projection": {
41+
"ProjectionType": "ALL"
42+
},
43+
"ProvisionedThroughput": {
44+
"ReadCapacityUnits": 1,
45+
"WriteCapacityUnits": 1
46+
}
47+
}
48+
],
2349
"ProvisionedThroughput": {
2450
"ReadCapacityUnits": 1,
2551
"WriteCapacityUnits": 1

times/timezones/src/main/kotlin/by/jprof/telegram/bot/times/timezones/dao/TimeZoneDAO.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ interface TimeZoneDAO {
66
suspend fun save(timeZone: TimeZone)
77

88
suspend fun get(user: Long, chat: Long): TimeZone?
9+
10+
suspend fun getByUsername(username: String, chat: Long): TimeZone?
911
}

times/timezones/src/main/kotlin/by/jprof/telegram/bot/times/timezones/model/TimeZone.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package by.jprof.telegram.bot.times.timezones.model
22

33
data class TimeZone(
44
val user: Long,
5+
val username: String? = null,
56
val chat: Long,
67
val zoneId: String? = null,
78
val offset: Int? = null,

0 commit comments

Comments
 (0)