Skip to content

Commit 56e56fa

Browse files
jnmtjosh-wong
andauthored
Add ClientService for hash store abstraction (#255)
Co-authored-by: Josh Wong <joshua.wong@scalar-labs.com>
1 parent dae93be commit 56e56fa

File tree

17 files changed

+2716
-47
lines changed

17 files changed

+2716
-47
lines changed

.github/workflows/scalar.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,40 @@ jobs:
156156
name: integration_test_reports_for_generic_contracts
157157
path: generic-contracts/build/reports/tests/integrationTest
158158

159+
integration-test-for-hash-store:
160+
name: Integration test for hash store
161+
runs-on: ubuntu-latest
162+
163+
services:
164+
mysql:
165+
image: mysql:8.1
166+
env:
167+
MYSQL_ROOT_PASSWORD: mysql
168+
ports:
169+
- 3306:3306
170+
171+
steps:
172+
- uses: actions/checkout@v5
173+
174+
- name: Set up JDK 1.8
175+
uses: actions/setup-java@v5
176+
with:
177+
distribution: 'temurin'
178+
java-version: '8'
179+
180+
- name: Setup Gradle
181+
uses: gradle/actions/setup-gradle@v4
182+
183+
- name: Run integration tests
184+
run: ./gradlew :hash-store:integrationTest
185+
186+
- name: Upload Gradle test reports
187+
if: always()
188+
uses: actions/upload-artifact@v4
189+
with:
190+
name: integration_test_reports_for_hash_store
191+
path: hash-store/build/reports/tests/integrationTest
192+
159193
integration-test-for-table-store:
160194
name: Integration test for table store
161195
runs-on: ubuntu-latest

common-test/src/main/java/com/scalar/dl/ledger/LedgerEndToEndTestBase.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public abstract class LedgerEndToEndTestBase {
3636
private static final String ASSET_TABLE = "asset";
3737
private static final String ASSET_METADATA_TABLE = "asset_metadata";
3838
private static final String LEDGER_SCHEMA_PATH = "/../schema-loader/ledger-schema.json";
39+
private static final String FUNCTION_DB_SCHEMA_PATH =
40+
"/../generic-contracts/scripts/objects-table-schema.json";
41+
private static final String FUNCTION_NAMESPACE = "test";
42+
private static final String FUNCTION_TABLE = "objects";
3943

4044
private static final String JDBC_TRANSACTION_MANAGER = "jdbc";
4145
private static final String PROP_STORAGE = "scalardb.storage";
@@ -79,6 +83,7 @@ public abstract class LedgerEndToEndTestBase {
7983
private Properties props;
8084
private Map<String, String> creationOptions = new HashMap<>();
8185
private Path ledgerSchemaPath;
86+
private Path databaseSchemaPath;
8287
private DistributedStorage storage;
8388
private DistributedStorageAdmin storageAdmin;
8489

@@ -89,7 +94,9 @@ public void setUpBeforeClass() throws Exception {
8994
storage = factory.getStorage();
9095
storageAdmin = factory.getStorageAdmin();
9196
ledgerSchemaPath = Paths.get(System.getProperty("user.dir") + LEDGER_SCHEMA_PATH);
97+
databaseSchemaPath = Paths.get(System.getProperty("user.dir") + FUNCTION_DB_SCHEMA_PATH);
9298
SchemaLoader.load(props, ledgerSchemaPath, creationOptions, true);
99+
SchemaLoader.load(props, databaseSchemaPath, creationOptions, true);
93100
createServer(new LedgerConfig(props));
94101
}
95102

@@ -99,6 +106,7 @@ public void tearDownAfterClass() throws SchemaLoaderException, InterruptedExcept
99106
storage.close();
100107
storageAdmin.close();
101108
SchemaLoader.unload(props, ledgerSchemaPath, true);
109+
SchemaLoader.unload(props, databaseSchemaPath, true);
102110
}
103111

104112
@BeforeEach
@@ -108,6 +116,7 @@ public void setUp() {}
108116
public void tearDown() throws ExecutionException {
109117
storageAdmin.truncateTable(SCALAR_NAMESPACE, ASSET_TABLE);
110118
storageAdmin.truncateTable(SCALAR_NAMESPACE, ASSET_METADATA_TABLE);
119+
storageAdmin.truncateTable(FUNCTION_NAMESPACE, FUNCTION_TABLE);
111120
}
112121

113122
private Properties createLedgerProperties() {
@@ -160,4 +169,28 @@ protected ClientConfig createClientConfig(String entity) throws IOException {
160169
props.put(ClientConfig.DS_PRIVATE_KEY_PEM, SOME_PRIVATE_KEY);
161170
return new ClientConfig(props);
162171
}
172+
173+
protected DistributedStorage getStorage() {
174+
return storage;
175+
}
176+
177+
protected DistributedStorageAdmin getStorageAdmin() {
178+
return storageAdmin;
179+
}
180+
181+
protected String getScalarNamespace() {
182+
return SCALAR_NAMESPACE;
183+
}
184+
185+
protected String getAssetTable() {
186+
return ASSET_TABLE;
187+
}
188+
189+
protected String getFunctionNamespace() {
190+
return FUNCTION_NAMESPACE;
191+
}
192+
193+
protected String getFunctionTable() {
194+
return FUNCTION_TABLE;
195+
}
163196
}

table-store/src/main/java/com/scalar/dl/tablestore/client/model/StatementExecutionResult.java renamed to common/src/main/java/com/scalar/dl/ledger/model/ExecutionResult.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
1-
package com.scalar.dl.tablestore.client.model;
1+
package com.scalar.dl.ledger.model;
22

33
import com.google.common.collect.ImmutableList;
4-
import com.scalar.dl.ledger.model.ContractExecutionResult;
54
import com.scalar.dl.ledger.proof.AssetProof;
65
import java.util.List;
76
import java.util.Objects;
87
import java.util.Optional;
98
import javax.annotation.concurrent.Immutable;
109

1110
/**
12-
* The result of statement execution. It contains the result of the statement execution along with a
13-
* list of {@link AssetProof}s from Ledger and Auditor.
11+
* The result of an operation execution in Ledger. It contains the result of the internal contract
12+
* execution along with a list of {@link AssetProof}s from Ledger and Auditor.
1413
*/
1514
@Immutable
1615
// non-final for mocking
17-
public class StatementExecutionResult {
16+
public class ExecutionResult {
1817
private final String result;
1918
private final ImmutableList<AssetProof> ledgerProofs;
2019
private final ImmutableList<AssetProof> auditorProofs;
2120

2221
/**
23-
* Constructs a {@code StatementExecutionResult} using the specified {@code
24-
* ContractExecutionResult}
22+
* Constructs a {@code ExecutionResult} using the specified {@code ContractExecutionResult}
2523
*
2624
* @param contractExecutionResult a {@code ContractExecutionResult}
2725
*/
28-
public StatementExecutionResult(ContractExecutionResult contractExecutionResult) {
26+
public ExecutionResult(ContractExecutionResult contractExecutionResult) {
2927
this.result = contractExecutionResult.getContractResult().orElse(null);
3028
this.ledgerProofs = ImmutableList.copyOf(contractExecutionResult.getLedgerProofs());
3129
this.auditorProofs = ImmutableList.copyOf(contractExecutionResult.getAuditorProofs());
3230
}
3331

3432
/**
35-
* Returns the result of statement execution.
33+
* Returns the result of an operation execution in Ledger.
3634
*
37-
* @return the result of statement execution
35+
* @return the result of an operation execution in Ledger
3836
*/
3937
public Optional<String> getResult() {
4038
return Optional.ofNullable(result);
@@ -73,7 +71,7 @@ public int hashCode() {
7371
* equal if it is the same instance or if:
7472
*
7573
* <ul>
76-
* <li>it is also an {@code StatementExecutionResult} and
74+
* <li>it is also an {@code ExecutionResult} and
7775
* <li>both instances have the same result and proofs.
7876
* </ul>
7977
*
@@ -85,10 +83,10 @@ public boolean equals(Object o) {
8583
if (o == this) {
8684
return true;
8785
}
88-
if (!(o instanceof StatementExecutionResult)) {
86+
if (!(o instanceof ExecutionResult)) {
8987
return false;
9088
}
91-
StatementExecutionResult other = (StatementExecutionResult) o;
89+
ExecutionResult other = (ExecutionResult) o;
9290
return Objects.equals(this.result, other.result)
9391
&& this.ledgerProofs.equals(other.ledgerProofs)
9492
&& this.auditorProofs.equals(other.auditorProofs);

hash-store/build.gradle

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
plugins {
2+
id 'net.ltgt.errorprone' version "${errorpronePluginVersion}"
3+
id "com.github.spotbugs" version "${spotbugsPluginVersion}"
4+
}
5+
6+
apply plugin:'application'
7+
startScripts.enabled = false
8+
9+
sourceSets {
10+
integrationTest {
11+
java {
12+
compileClasspath += main.output + test.output
13+
runtimeClasspath += main.output + test.output
14+
srcDir file('src/integration-test/java')
15+
}
16+
resources.srcDir file('src/integration-test/resources')
17+
}
18+
}
19+
20+
configurations {
21+
integrationTestImplementation.extendsFrom testImplementation
22+
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
23+
integrationTestCompileOnly.extendsFrom testCompileOnly
24+
}
25+
26+
dependencies {
27+
implementation project(':client')
28+
implementation project(':generic-contracts')
29+
implementation project(':ledger') // to use JacksonBasedContract
30+
implementation group: 'info.picocli', name: 'picocli', version: "${picoCliVersion}"
31+
implementation group: 'org.partiql', name: 'partiql-parser', version: "${partiqlVersion}"
32+
33+
// for test
34+
testImplementation project(':common-test')
35+
integrationTestImplementation project(':common-test')
36+
integrationTestImplementation group: 'com.scalar-labs', name: 'scalardb-schema-loader', version: "${scalarDbVersion}"
37+
38+
// for Error Prone
39+
errorprone "com.google.errorprone:error_prone_core:${errorproneVersion}"
40+
errorproneJavac "com.google.errorprone:javac:${errorproneJavacVersion}"
41+
42+
// for SpotBugs
43+
spotbugs "com.github.spotbugs:spotbugs:${spotbugsVersion}"
44+
compileOnly "com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}"
45+
testCompileOnly "com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}"
46+
}
47+
48+
task HashStore(type: CreateStartScripts) {
49+
mainClass = 'com.scalar.dl.hashstore.client.tool.HashStoreCommandLine'
50+
applicationName = 'scalardl-hash-store'
51+
outputDir = new File(project.buildDir, 'tmp')
52+
classpath = jar.outputs.files + project.configurations.runtimeClasspath
53+
}
54+
55+
applicationDistribution.into('bin') {
56+
from(HashStore)
57+
fileMode = 0755
58+
}
59+
60+
task integrationTest(type: Test) {
61+
useJUnitPlatform()
62+
description 'Runs the integration tests.'
63+
group 'verification'
64+
testClassesDirs = sourceSets.integrationTest.output.classesDirs
65+
classpath = sourceSets.integrationTest.runtimeClasspath
66+
outputs.upToDateWhen { false } // ensures integration tests are run every time when called
67+
shouldRunAfter test
68+
options {
69+
systemProperties(System.getProperties().findAll{it.key.toString().startsWith("scalar")})
70+
}
71+
}
72+
73+
spotless {
74+
java {
75+
target 'src/*/java/**/*.java'
76+
importOrder()
77+
removeUnusedImports()
78+
googleJavaFormat('1.7')
79+
}
80+
}
81+
82+
spotbugs {
83+
ignoreFailures = false
84+
showStackTraces = true
85+
showProgress = true
86+
effort = 'default'
87+
reportLevel = 'default'
88+
maxHeapSize = '1g'
89+
extraArgs = [ '-nested:false' ]
90+
jvmArgs = [ '-Duser.language=en' ]
91+
}
92+
93+
spotbugsMain.reports {
94+
html.enabled = true
95+
}
96+
97+
spotbugsTest.reports {
98+
html.enabled = true
99+
}
100+
101+
task sourcesJar(type: Jar) {
102+
classifier = 'sources'
103+
from sourceSets.main.allSource
104+
}

0 commit comments

Comments
 (0)