Skip to content

Commit 001d495

Browse files
committed
Add support for S3
1 parent e01f5a1 commit 001d495

File tree

18 files changed

+1173
-26
lines changed

18 files changed

+1173
-26
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Test Object Storage Adapter
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
INT_TEST_JAVA_RUNTIME_VERSION:
7+
description: JDK version used to run the integration test
8+
type: choice
9+
required: false
10+
default: '8'
11+
options:
12+
- '8'
13+
- '11'
14+
- '17'
15+
- '21'
16+
INT_TEST_JAVA_RUNTIME_VENDOR:
17+
description: Vendor of the JDK used to run the integration test
18+
type: choice
19+
required: false
20+
default: 'temurin'
21+
options:
22+
- 'corretto'
23+
- 'microsoft'
24+
- 'oracle'
25+
- 'temurin'
26+
27+
env:
28+
TERM: dumb
29+
JAVA_VERSION: '8'
30+
JAVA_VENDOR: 'temurin'
31+
INT_TEST_JAVA_RUNTIME_VERSION: "${{ github.event_name != 'workflow_dispatch' && '8' || inputs.INT_TEST_JAVA_RUNTIME_VERSION }}"
32+
INT_TEST_JAVA_RUNTIME_VENDOR: "${{ github.event_name != 'workflow_dispatch' && 'temurin' || inputs.INT_TEST_JAVA_RUNTIME_VENDOR }}"
33+
# Gradle will parse 'ORG_GRADLE_PROJECT_<project_property_name>' environment variables as project properties.
34+
# The following variables configure the 'com.scalar.db.jdk-configuration' Gradle plugin.
35+
ORG_GRADLE_PROJECT_javaVersion: '8'
36+
ORG_GRADLE_PROJECT_javaVendor: 'temurin'
37+
ORG_GRADLE_PROJECT_integrationTestJavaRuntimeVersion: "${{ github.event_name != 'workflow_dispatch' && '8' || inputs.INT_TEST_JAVA_RUNTIME_VERSION }}"
38+
ORG_GRADLE_PROJECT_integrationTestJavaRuntimeVendor: "${{ github.event_name != 'workflow_dispatch' && 'temurin' || inputs.INT_TEST_JAVA_RUNTIME_VENDOR }}"
39+
# This variable evaluates to: if {!(Temurin JDK 8) && !(Oracle JDK)} then {true} else {false}
40+
# Oracle JDK that are linux compatible and publicly available through direct download exist for all LTS versions
41+
SET_UP_INT_TEST_RUNTIME_NON_ORACLE_JDK: "${{ (github.event_name == 'workflow_dispatch' && !(inputs.INT_TEST_JAVA_RUNTIME_VERSION == '8' && inputs.INT_TEST_JAVA_RUNTIME_VENDOR == 'temurin') && !(inputs.INT_TEST_JAVA_RUNTIME_VENDOR == 'oracle')) && 'true' || 'false' }}"
42+
INT_TEST_GRADLE_OPTIONS_FOR_GROUP_COMMIT: '"-Dscalardb.consensus_commit.coordinator.group_commit.enabled=true" "-Dscalardb.consensus_commit.coordinator.group_commit.old_group_abort_timeout_millis=15000" --tests "**.ConsensusCommit**"'
43+
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
44+
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
45+
S3_REGION: ap-northeast-1
46+
S3_BUCKET_NAME: scalardb-test-bucket
47+
48+
jobs:
49+
integration-test-s3:
50+
name: S3 integration test (${{ matrix.mode.label }})
51+
runs-on: ubuntu-latest
52+
53+
steps:
54+
- uses: actions/checkout@v5
55+
56+
- name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }})
57+
uses: actions/setup-java@v5
58+
with:
59+
java-version: ${{ env.JAVA_VERSION }}
60+
distribution: ${{ env.JAVA_VENDOR }}
61+
62+
- name: Set up JDK ${{ env.INT_TEST_JAVA_RUNTIME_VERSION }} (${{ env.INT_TEST_JAVA_RUNTIME_VENDOR }}) to run integration test
63+
uses: actions/setup-java@v5
64+
if: ${{ env.SET_UP_INT_TEST_RUNTIME_NON_ORACLE_JDK == 'true'}}
65+
with:
66+
java-version: ${{ env.INT_TEST_JAVA_RUNTIME_VERSION }}
67+
distribution: ${{ env.INT_TEST_JAVA_RUNTIME_VENDOR }}
68+
69+
- name: Login to Oracle container registry
70+
uses: docker/login-action@v3
71+
if: ${{ env.INT_TEST_JAVA_RUNTIME_VENDOR == 'oracle' }}
72+
with:
73+
registry: container-registry.oracle.com
74+
username: ${{ secrets.OCR_USERNAME }}
75+
password: ${{ secrets.OCR_TOKEN }}
76+
77+
- name: Set up JDK ${{ env.INT_TEST_JAVA_RUNTIME_VERSION }} (oracle) to run the integration test
78+
if: ${{ env.INT_TEST_JAVA_RUNTIME_VENDOR == 'oracle' }}
79+
run: |
80+
container_id=$(docker create "container-registry.oracle.com/java/jdk:${{ env.INT_TEST_JAVA_RUNTIME_VERSION }}")
81+
docker cp -L "$container_id:/usr/java/default" /usr/lib/jvm/oracle-jdk && docker rm "$container_id"
82+
- name: Setup Gradle
83+
uses: gradle/actions/setup-gradle@v5
84+
85+
- name: Execute Gradle 'integrationTestObjectStorage' task
86+
run: ./gradlew integrationTestObjectStorage -Dscalardb.object_storage.storage=s3 -Dscalardb.object_storage.endpoint=${{ env.S3_REGION }}/${{ env.S3_BUCKET_NAME }} ${{ matrix.mode.group_commit_enabled && env.INT_TEST_GRADLE_OPTIONS_FOR_GROUP_COMMIT || '' }}
87+
88+
- name: Upload Gradle test reports
89+
if: always()
90+
uses: actions/upload-artifact@v5
91+
with:
92+
name: cassandra_3.0_integration_test_reports_${{ matrix.mode.label }}
93+
path: core/build/reports/tests/integrationTestObjectStorage

core/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ dependencies {
174174
implementation platform("software.amazon.awssdk:bom:${awssdkVersion}")
175175
implementation 'software.amazon.awssdk:applicationautoscaling'
176176
implementation 'software.amazon.awssdk:dynamodb'
177+
implementation 'software.amazon.awssdk:s3'
178+
implementation 'software.amazon.awssdk:aws-crt-client'
177179
testImplementation 'software.amazon.awssdk:iam'
178180
testImplementation 'software.amazon.awssdk:iam-policy-builder'
179181
implementation "org.apache.commons:commons-dbcp2:${commonsDbcp2Version}"

core/src/integration-test/java/com/scalar/db/storage/objectstorage/ObjectStorageEnv.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import java.util.Properties;
88

99
public class ObjectStorageEnv {
10+
private static final String PROP_OBJECT_STORAGE_STORAGE = "scalardb.object_storage.storage";
1011
private static final String PROP_OBJECT_STORAGE_ENDPOINT = "scalardb.object_storage.endpoint";
1112
private static final String PROP_OBJECT_STORAGE_USERNAME = "scalardb.object_storage.username";
1213
private static final String PROP_OBJECT_STORAGE_PASSWORD = "scalardb.object_storage.password";
1314

15+
private static final String DEFAULT_OBJECT_STORAGE_STORAGE = BlobStorageConfig.STORAGE_NAME;
1416
private static final String DEFAULT_OBJECT_STORAGE_ENDPOINT =
1517
"http://localhost:10000/test/test-container";
1618
private static final String DEFAULT_OBJECT_STORAGE_USERNAME = "test";
@@ -19,6 +21,8 @@ public class ObjectStorageEnv {
1921
private ObjectStorageEnv() {}
2022

2123
public static Properties getProperties(String testName) {
24+
String storage =
25+
System.getProperty(PROP_OBJECT_STORAGE_STORAGE, DEFAULT_OBJECT_STORAGE_STORAGE);
2226
String accountName =
2327
System.getProperty(PROP_OBJECT_STORAGE_USERNAME, DEFAULT_OBJECT_STORAGE_USERNAME);
2428
String accountKey =
@@ -30,7 +34,7 @@ public static Properties getProperties(String testName) {
3034
properties.setProperty(DatabaseConfig.CONTACT_POINTS, endpoint);
3135
properties.setProperty(DatabaseConfig.USERNAME, accountName);
3236
properties.setProperty(DatabaseConfig.PASSWORD, accountKey);
33-
properties.setProperty(DatabaseConfig.STORAGE, BlobStorageConfig.STORAGE_NAME);
37+
properties.setProperty(DatabaseConfig.STORAGE, storage);
3438
properties.setProperty(DatabaseConfig.CROSS_PARTITION_SCAN, "true");
3539
properties.setProperty(DatabaseConfig.CROSS_PARTITION_SCAN_FILTERING, "true");
3640
properties.setProperty(DatabaseConfig.CROSS_PARTITION_SCAN_ORDERING, "false");

core/src/integration-test/java/com/scalar/db/storage/objectstorage/ObjectStorageWrapperIntegrationTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public void update_NonExistingObjectKeyGiven_ShouldThrowPreconditionFailedExcept
156156
}
157157

158158
@Test
159-
public void update_WrongVersionGiven_ShouldThrowPreconditionFailedException() throws Exception {
159+
public void update_WrongVersionGiven_ShouldThrowPreconditionFailedException() {
160160
// Arrange
161161
String wrongVersion = "wrong-version";
162162

@@ -279,9 +279,16 @@ public void deleteByPrefix_WithNonExistingPrefix_ShouldDoNothing() throws Except
279279

280280
@Test
281281
public void close_ShouldNotThrowException() {
282-
// Arrange
282+
try {
283+
// Arrange
283284

284-
// Act Assert
285-
assertThatCode(() -> wrapper.close()).doesNotThrowAnyException();
285+
// Act Assert
286+
assertThatCode(() -> wrapper.close()).doesNotThrowAnyException();
287+
} finally {
288+
Properties properties = getProperties(TEST_NAME);
289+
ObjectStorageConfig objectStorageConfig =
290+
ObjectStorageUtils.getObjectStorageConfig(new DatabaseConfig(properties));
291+
wrapper = ObjectStorageWrapperFactory.create(objectStorageConfig);
292+
}
286293
}
287294
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.scalar.db.storage.objectstorage;
2+
3+
public class ConflictOccurredException extends ObjectStorageWrapperException {
4+
5+
public ConflictOccurredException(String message, Throwable cause) {
6+
super(message, cause);
7+
}
8+
}

core/src/main/java/com/scalar/db/storage/objectstorage/ObjectStorageConfig.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ public interface ObjectStorageConfig {
99
*/
1010
String getStorageName();
1111

12-
/**
13-
* Returns the endpoint for the object storage service.
14-
*
15-
* @return the endpoint
16-
*/
17-
String getEndpoint();
18-
1912
/**
2013
* Returns the username for authentication.
2114
*

core/src/main/java/com/scalar/db/storage/objectstorage/ObjectStorageUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.scalar.db.config.DatabaseConfig;
44
import com.scalar.db.storage.objectstorage.blobstorage.BlobStorageConfig;
5+
import com.scalar.db.storage.objectstorage.s3.S3Config;
56
import java.util.Objects;
67

78
public class ObjectStorageUtils {
@@ -19,6 +20,8 @@ public static String getObjectKey(String namespace, String table) {
1920
public static ObjectStorageConfig getObjectStorageConfig(DatabaseConfig databaseConfig) {
2021
if (Objects.equals(databaseConfig.getStorage(), BlobStorageConfig.STORAGE_NAME)) {
2122
return new BlobStorageConfig(databaseConfig);
23+
} else if (Objects.equals(databaseConfig.getStorage(), S3Config.STORAGE_NAME)) {
24+
return new S3Config(databaseConfig);
2225
} else {
2326
throw new IllegalArgumentException(
2427
"Unsupported Object Storage: " + databaseConfig.getStorage());

core/src/main/java/com/scalar/db/storage/objectstorage/ObjectStorageWrapperException.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
public class ObjectStorageWrapperException extends Exception {
44

5-
public ObjectStorageWrapperException(String message) {
6-
super(message);
7-
}
8-
95
public ObjectStorageWrapperException(String message, Throwable cause) {
106
super(message, cause);
117
}

core/src/main/java/com/scalar/db/storage/objectstorage/ObjectStorageWrapperFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.scalar.db.storage.objectstorage.blobstorage.BlobStorageConfig;
44
import com.scalar.db.storage.objectstorage.blobstorage.BlobStorageWrapper;
5+
import com.scalar.db.storage.objectstorage.s3.S3Config;
6+
import com.scalar.db.storage.objectstorage.s3.S3Wrapper;
57
import java.util.Objects;
68

79
public class ObjectStorageWrapperFactory {
@@ -10,6 +12,9 @@ public static ObjectStorageWrapper create(ObjectStorageConfig objectStorageConfi
1012
if (Objects.equals(objectStorageConfig.getStorageName(), BlobStorageConfig.STORAGE_NAME)) {
1113
assert objectStorageConfig instanceof BlobStorageConfig;
1214
return new BlobStorageWrapper((BlobStorageConfig) objectStorageConfig);
15+
} else if (Objects.equals(objectStorageConfig.getStorageName(), S3Config.STORAGE_NAME)) {
16+
assert objectStorageConfig instanceof S3Config;
17+
return new S3Wrapper((S3Config) objectStorageConfig);
1318
} else {
1419
throw new IllegalArgumentException(
1520
"Unsupported Object Storage: " + objectStorageConfig.getStorageName());

core/src/main/java/com/scalar/db/storage/objectstorage/PreconditionFailedException.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
public class PreconditionFailedException extends ObjectStorageWrapperException {
44

5-
public PreconditionFailedException(String message) {
6-
super(message);
7-
}
8-
95
public PreconditionFailedException(String message, Throwable cause) {
106
super(message, cause);
117
}

0 commit comments

Comments
 (0)