Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ledger/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dependencies {
implementation group: 'com.github.everit-org.json-schema', name: 'org.everit.json.schema', version: '1.14.4'

testImplementation group: 'com.scalar-labs', name: 'scalardb-schema-loader', version: "${scalarDbVersion}"
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: "${junitVersion}"

// for Error Prone
errorprone "com.google.errorprone:error_prone_core:${errorproneVersion}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,17 @@ public List<AssetProof> commit() {
if (snapshot.hasWriteSet()) {
puts = assetComposer.compose(snapshot, request);

if (config.isTxStateManagementEnabled()) {
stateManager.putCommit(transaction, transaction.getId());
}

transaction.put(puts);

if (!config.isDirectAssetAccessEnabled()) {
Comment on lines 134 to 137

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Moving the stateManager.putCommit call after the transaction.put call ensures that the transaction state is updated only if the data is successfully written. This prevents inconsistencies where the transaction is marked as committed but the data is not actually persisted. This is a critical change to ensure data integrity.

Suggested change
if (config.isTxStateManagementEnabled()) {
stateManager.putCommit(transaction, transaction.getId());
}
transaction.put(puts);
if (!config.isDirectAssetAccessEnabled()) {
transaction.put(puts);
if (!config.isDirectAssetAccessEnabled()) {
metadata.put(snapshot.getWriteSet().values());
}
}
if (config.isTxStateManagementEnabled()) {
stateManager.putCommit(transaction, transaction.getId());

metadata.put(snapshot.getWriteSet().values());
}
}

if (config.isTxStateManagementEnabled()) {
stateManager.putCommit(transaction, transaction.getId());
}

transaction.commit();
} catch (CrudConflictException e) {
throw new ConflictException("putting asset records failed", e, Collections.emptyMap());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
Expand Down Expand Up @@ -466,6 +468,7 @@ public void commit_EmptySnapshotGiven_ShouldDoNothing()
CrudException {
// Arrange
when(config.isDirectAssetAccessEnabled()).thenReturn(false);
when(config.isTxStateManagementEnabled()).thenReturn(false);

// Act
ledger.commit();
Expand All @@ -482,6 +485,7 @@ public void commit_EmptySnapshotGivenAndDirectAssetAccessEnabled_ShouldDoNothing
CrudException {
// Arrange
when(config.isDirectAssetAccessEnabled()).thenReturn(true);
when(config.isTxStateManagementEnabled()).thenReturn(false);

// Act
ledger.commit();
Expand Down Expand Up @@ -741,12 +745,14 @@ public void commit_CommitExceptionThrownInCommit_ShouldThrowDatabaseException()
assertThat(proofs).containsOnly(proof);
}
Comment on lines 745 to 746

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The original test commit_TxStateManagementEnabled_ShouldPutWithStateManager is being replaced with a parameterized test to cover both true and false cases for txStateManagementEnabled. This is a good improvement to ensure that the state manager is called correctly based on the configuration.

  @ParameterizedTest
  @ValueSource(booleans = {true, false})
  public void commit_WriteTransactionGiven_ShouldPutWithStateManagerAccordingToConfig(
      boolean txStateManagementEnabled)


@Test
public void commit_TxStateManagementEnabled_ShouldPutWithStateManager()
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void commit_WriteTransactionGiven_ShouldPutWithStateManagerAccordingToConfig(
boolean txStateManagementEnabled)
throws CrudException, CommitException,
com.scalar.db.exception.transaction.UnknownTransactionStatusException {
// Arrange
when(config.isTxStateManagementEnabled()).thenReturn(true);
when(config.isTxStateManagementEnabled()).thenReturn(txStateManagementEnabled);
snapshot.put(ANY_ID, asset);
snapshot.put(ANY_ID, ANY_DATA);
doNothing().when(transaction).put(any(List.class));
Expand All @@ -758,32 +764,40 @@ public void commit_TxStateManagementEnabled_ShouldPutWithStateManager()
ledger.commit();

// Assert
verify(stateManager).putCommit(transaction, ANY_NONCE);
if (txStateManagementEnabled) {
verify(stateManager).putCommit(transaction, ANY_NONCE);
} else {
verify(stateManager, never()).putCommit(any(DistributedTransaction.class), anyString());
}
verify(transaction).put(any(List.class));
verify(transaction).put(any(Put.class));
verify(transaction).commit();
}

@Test
public void commit_TxStateManagementDisabled_ShouldNotPutWithStateManager()
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void commit_ReadOnlyTransactionGiven_ShouldPutWithStateManagerAccordingToConfig(
boolean txStateManagementEnabled)
throws CrudException, CommitException,
com.scalar.db.exception.transaction.UnknownTransactionStatusException {
// Arrange
when(config.isTxStateManagementEnabled()).thenReturn(false);
snapshot.put(ANY_ID, asset);
snapshot.put(ANY_ID, ANY_DATA);
doNothing().when(transaction).put(any(List.class));
doNothing().when(transaction).put(any(Put.class));
when(config.isTxStateManagementEnabled()).thenReturn(txStateManagementEnabled);
when(config.isDirectAssetAccessEnabled()).thenReturn(false);
when(transaction.getId()).thenReturn(ANY_NONCE);
doNothing().when(stateManager).putCommit(any(DistributedTransaction.class), anyString());
snapshot.put(ANY_ID, asset);

// Act
ledger.commit();

// Assert
verify(stateManager, never()).putCommit(transaction, ANY_NONCE);
verify(transaction).put(any(List.class));
verify(transaction).put(any(Put.class));
if (txStateManagementEnabled) {
verify(stateManager).putCommit(transaction, ANY_NONCE);
} else {
verify(stateManager, never()).putCommit(any(DistributedTransaction.class), anyString());
}
verify(transaction, never()).put(any(List.class));
verify(transaction, never()).put(any(Put.class));
verify(transaction).commit();
}

Expand Down