Skip to content

Commit 3f520ef

Browse files
authored
Create Migration guide from v1 to v2 (#117)
1 parent d6d979a commit 3f520ef

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@ For AWS SDK 2.x:
495495
implementation "app.cash.tempest:tempest2:1.6.2"
496496
```
497497
498+
## Migrating From Tempest 1 to Tempest 2
499+
500+
Please follow the [Migration Guide](docs/guide/v2_upgrade_guide.md) that has been set up to upgrade from Tempest 1 (AWS SDK 1.x) to Tempest 2 (AWS SDK 2.x)
501+
498502
## License
499503
500504
Copyright 2020 Square, Inc.

docs/guide/v2_upgrade_guide.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# Migration Guide from Tempest v1 to Tempest v2
2+
3+
This guide will explain some items that need to be changed when upgrading from Tempest 1 to Tempest 2
4+
5+
## Dependencies
6+
7+
The first change is to swap the dependency from v1 to v2.
8+
9+
### Depenencies.kt
10+
```diff
11+
- val tempest = "app.cash.tempest:tempest:{dependencies.tempestVersion}"
12+
+ val tempest2 = "app.cash.tempest:tempest2:{dependencies.tempestVersion}"
13+
```
14+
15+
### build.gradle.kts
16+
```diff
17+
- implementation(Dependencies.tempest)
18+
+ implementation(Dependencies.tempest2)
19+
```
20+
21+
## Import Changes
22+
23+
Many of the classes and objects imported from a `tempest` or `aws` package will likely be found by just adding a **2** to the import path.
24+
25+
```diff
26+
- import app.cash.tempest.BeginsWith
27+
+ import app.cash.tempest2.BeginsWith
28+
```
29+
30+
Though some of your imports may have moved into Amazons new package structure
31+
32+
```diff
33+
- import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException
34+
+ import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException
35+
```
36+
37+
## Logical DB Upgrades
38+
39+
One of the largest changes will be to your `LogicalDB` and the class used as your `LogicalTable<T>` type.
40+
41+
### TableName Annotation
42+
43+
In Tempest v1 your table would likely have been annotated with an `@DynamoDBTable` annotation. This is no longer on the table definition class, but has been moved to an annotation on the member variable inside the LogicalDb interface.
44+
45+
Additionally, that annotation needs to be replaced with an `DynamoDbBean` annotation.
46+
47+
#### Old
48+
```kotlin
49+
interface DyDatabase : LogicalDb {
50+
val table: DyTable
51+
}
52+
53+
interface DyTable : LogicalTable<DyItem> {
54+
// View and Index member variables
55+
}
56+
57+
@DynamoDBTable(tableName = TABLE_NAME)
58+
class DyItem {
59+
// Attribute Definitions
60+
}
61+
```
62+
63+
#### New
64+
```kotlin
65+
interface DyDatabase : LogicalDb {
66+
@TableName(TABLE_NAME)
67+
val table: DyTable
68+
}
69+
70+
interface DyTable : LogicalTable<DyItem> {
71+
// View and Index member variables
72+
}
73+
74+
@DynamoDbBean
75+
class DyItem {
76+
// Attribute Definitions
77+
}
78+
```
79+
80+
### Hash Key Annotation
81+
82+
`@DynamoDBHashKey` has been replaced by `@get:DynamoDbPartitionKey`
83+
84+
```diff
85+
- @DynamoDBHashKey
86+
+ @get:DynamoDbPartitionKey
87+
var partition_key: String? = null
88+
```
89+
90+
### Range Key Annotation
91+
92+
`@DynamoDBRangeKey` has been replaced by `@get:DynamoDbSortKey`
93+
94+
```diff
95+
- @DynamoDBRangeKey
96+
+ @get:DynamoDbSortKey
97+
var sort_key: String? = null
98+
```
99+
100+
### DynamoDBAttribute Annotation
101+
102+
The `@DynamoDBAttribute` is no longer needed on class member variables
103+
104+
```diff
105+
- @DynamoDBAttribute
106+
var description: String? = null
107+
```
108+
109+
### Index on Hash Keys
110+
111+
`@DynamoDBIndexHashKey` has been replaced by `@get:DynamoDbSecondaryPartitionKey`
112+
113+
```diff
114+
- @DynamoDBIndexHashKey(globalSecondaryIndexName = ENTITY_TYPE_INDEX)
115+
+ @get:DynamoDbSecondaryPartitionKey(indexNames = [ENTITY_TYPE_INDEX])
116+
var gsi_pk: String? = null
117+
```
118+
119+
### Index on Range Keys
120+
121+
`@DynamoDBIndexRangeKey` has been replaced by `@get:DynamoDbSecondarySortKey`
122+
123+
```diff
124+
- @DynamoDBIndexRangeKey(globalSecondaryIndexName = ENTITY_TYPE_INDEX)
125+
+ @get:DynamoDbSecondarySortKey(indexNames = [ENTITY_TYPE_INDEX])
126+
var gsi_sk: String? = null
127+
```
128+
129+
### Version Attribute
130+
131+
`@DynamoDBVersionAttribute` has been replaced by `@get:DynamoDbVersionAttribute`
132+
133+
```diff
134+
- @DynamoDBVersionAttribute
135+
+ @get:DynamoDbVersionAttribute
136+
var version: Long? = null
137+
```
138+
139+
### Type Conversion Annotation
140+
141+
`@DynamoDBTypeConverted` has been replaced by `@get:DynamoDbConvertedBy`
142+
143+
```diff
144+
- @DynamoDBTypeConverted(converter = InstantTypeConverter::class)
145+
+ @get:DynamoDbConvertedBy(InstantAttributeConverter::class)
146+
var expires_at: Instant? = null
147+
```
148+
149+
### Type Conversion Interface
150+
151+
The `DynamoDBTypeConverter<DBType, Mine>` interface has been replaced by an `AttributeConverter<Mine>` interface.
152+
153+
Instead of having two methods
154+
* `fun convert(mine: Mine): DBType`
155+
* `fun unconvert(dbType: DbType): Mine`
156+
157+
There are now four methods
158+
* `fun transformFrom(mine: Mine): AttributeValue`
159+
* essentially the same as convert
160+
* `fun transformTo(input: AttributeValue): Mine`
161+
* essentiall the same as unconvert
162+
* `fun type(): EnhancedType<Mine>`
163+
* Allows the Enhanced Dynamo SDK to avoid Type Erasure
164+
* `fun attributeValueType(): AttributeValueType`
165+
* Tells the SDK which value to expect from `transformFrom`
166+
167+
---
168+
169+
Included below is an example of the transformation from a `DynamoDBTypeConverter<Long, Instant>` to `AttributeConverter<Instant>`
170+
171+
#### Old
172+
173+
```kotlin
174+
internal class InstantTypeEpochConverter : DynamoDBTypeConverter<Long, Instant> {
175+
override fun unconvert(epochSeconds: Long): Instant {
176+
return Instant.ofEpochSecond(epochSeconds)
177+
}
178+
179+
override fun convert(instant: Instant): Long {
180+
return instant.epochSecond
181+
}
182+
}
183+
```
184+
185+
#### New
186+
187+
```kotlin
188+
internal class InstantTypeEpochConverter : AttributeConverter<Instant> {
189+
override fun transformFrom(input: Instant): AttributeValue {
190+
val timeLongAsString = input.epochSecond.toString()
191+
return AttributeValue.builder()
192+
.n(timeLongAsString)
193+
.build()
194+
}
195+
196+
override fun transformTo(input: AttributeValue): Instant {
197+
val timeLong = input.n().toLong()
198+
return Instant.ofEpochSecond(timeLong)
199+
}
200+
201+
override fun type(): EnhancedType<Instant> {
202+
return EnhancedType.of(Instant::class.java)
203+
}
204+
205+
override fun attributeValueType(): AttributeValueType {
206+
return AttributeValueType.N
207+
}
208+
}
209+
```
210+
211+
## Creating your LogicalDb
212+
213+
Previously you could create your `LogicalDb` object using an `AmazonDynamoDB` object. However, the new `LogicalDb` objects require `DynamoDbEnhancedClient` objects, which themselves can be created using the new base `DynamoDbClient` object.
214+
215+
### New Creation Semantics
216+
```kotlin
217+
fun createClient(
218+
awsRegionName: String,
219+
awsCredentialsProvider: AwsCredentialsProvider,
220+
) : DynamoDbClient =
221+
DynamoDbClient.builder()
222+
.region(Region.of(awsRegionName))
223+
.credentialsProvider(awsCredentialsProvider)
224+
.build()
225+
226+
fun createEnhancedClient(dynamoDbClient: DynamoDbClient): DynamoDbEnhancedClient =
227+
DynamoDbEnhancedClient.builder()
228+
.dynamoDbClient(dynamoDbClient)
229+
.build()
230+
231+
fun createLogicalDb(dynamoDbEnhancedClient: DynamoDbEnhancedClient): DyDatabase =
232+
LogicalDb<DyDatabase>(dynamoDbEnhancedClient)
233+
```
234+
235+
## API Type changes
236+
237+
### Consistent Read Enum
238+
239+
When doing a `load` from an `InlineView` object in Tempest 1 the consistent read was specified via an enum. In Tempest 2 the option is now a boolean specifying to use consistent reads or not.
240+
241+
```diff
242+
val key = ...
243+
val entity = dyDatabase.dyTable.dyEntitiy.load(
244+
key = key,
245+
- consistentReads = DynamoDBMapperConfig.ConsistentReads.CONSISTENT
246+
+ consistentReads = true
247+
)
248+
```

0 commit comments

Comments
 (0)