Skip to content

Commit

Permalink
#80 ensure collections before transaction start
Browse files Browse the repository at this point in the history
  • Loading branch information
aburmeis committed Aug 23, 2023
1 parent 5baea19 commit 0ffeb3c
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

import com.arangodb.ArangoDBException;
import com.arangodb.ArangoDatabase;
import com.arangodb.DbName;
import com.arangodb.springframework.core.ArangoOperations;
import com.arangodb.springframework.core.template.CollectionCallback;
import com.arangodb.springframework.repository.query.QueryTransactionBridge;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
Expand Down Expand Up @@ -67,10 +67,10 @@ public void afterPropertiesSet() {
throw new IllegalStateException("Nested transactions must not be allowed");
}
if (!isGlobalRollbackOnParticipationFailure()) {
throw new IllegalStateException("Global rollback on participating failure is needed");
throw new IllegalStateException("Global rollback on participating failure is required");
}
if (getTransactionSynchronization() == SYNCHRONIZATION_NEVER) {
throw new IllegalStateException("Transaction synchronization is needed always");
throw new IllegalStateException("Transaction synchronization must not be disabled");
}
}

Expand All @@ -81,7 +81,7 @@ public void afterPropertiesSet() {
protected ArangoTransactionObject doGetTransaction() {
ArangoTransactionHolder holder = (ArangoTransactionHolder) TransactionSynchronizationManager.getResource(this);
try {
return new ArangoTransactionObject(operations.db(), getDefaultTimeout(), holder);
return new ArangoTransactionObject(operations.db(), CollectionCallback.fromOperations(operations), getDefaultTimeout(), holder);
} catch (ArangoDBException error) {
throw new TransactionSystemException("Cannot create transaction object", error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.arangodb.ArangoDatabase;
import com.arangodb.entity.StreamTransactionStatus;
import com.arangodb.model.StreamTransactionOptions;
import com.arangodb.springframework.core.template.CollectionCallback;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
Expand All @@ -46,11 +47,13 @@ class ArangoTransactionObject implements SmartTransactionObject {
private static final Log logger = LogFactory.getLog(ArangoTransactionObject.class);

private final ArangoDatabase database;
private final CollectionCallback collectionCallback;
private final ArangoTransactionHolder holder;
private int timeout;

ArangoTransactionObject(ArangoDatabase database, int defaultTimeout, @Nullable ArangoTransactionHolder holder) {
ArangoTransactionObject(ArangoDatabase database, CollectionCallback collectionCallback, int defaultTimeout, @Nullable ArangoTransactionHolder holder) {
this.database = database;
this.collectionCallback = collectionCallback;
this.holder = holder == null ? new ArangoTransactionHolder() : holder;
this.timeout = defaultTimeout;
}
Expand All @@ -71,6 +74,7 @@ void configure(TransactionDefinition definition) {
ArangoTransactionHolder getOrBegin(Collection<String> collections) throws ArangoDBException {
addCollections(collections);
if (holder.getStreamTransactionId() == null) {
holder.getCollectionNames().forEach(collectionCallback::collection);
StreamTransactionOptions options = new StreamTransactionOptions()
.allowImplicit(true)
.writeCollections(holder.getCollectionNames().toArray(new String[0]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import java.util.List;

import com.arangodb.springframework.annotation.PersistentIndex;
import org.springframework.data.annotation.Id;

import com.arangodb.springframework.annotation.Document;
Expand All @@ -33,6 +34,7 @@
* @author Christian Lechner
*/
@Document("actors")
@PersistentIndex(fields = "name")
public class Actor {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.arangodb.springframework.ArangoTransactionalTestConfiguration;
import com.arangodb.springframework.repository.ActorRepository;
import com.arangodb.springframework.repository.MovieRepository;
import com.arangodb.springframework.testdata.Actor;
import com.arangodb.springframework.testdata.Movie;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -18,7 +17,7 @@
public class ArangoTransactionManagerRepositoryTest extends AbstractArangoTest {

public ArangoTransactionManagerRepositoryTest() {
super(Movie.class, Actor.class);
super(Movie.class);
}

@Autowired
Expand Down Expand Up @@ -66,4 +65,10 @@ public void shouldRollbackWithinTransaction() {

assertThat(movieRepository.findById(starWars.getId())).isNotPresent();
}

@Test
@Transactional(label = "actors")
public void shouldCreateCollectionsBeforeTransaction() {
actorRepository.findAll();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.arangodb.springframework.transaction;

import com.arangodb.ArangoDB;
import com.arangodb.ArangoDatabase;
import com.arangodb.DbName;
import com.arangodb.entity.StreamTransactionEntity;
import com.arangodb.entity.StreamTransactionStatus;
import com.arangodb.model.StreamTransactionOptions;
Expand Down Expand Up @@ -72,7 +70,7 @@ public void cleanupSync() {

@Test
public void getTransactionReturnsNewTransactionWithoutStreamTransaction() {
TransactionStatus status = underTest.getTransaction(new DefaultTransactionAttribute());
TransactionStatus status = underTest.getTransaction(createTransactionAttribute("test"));
assertThat(status.isNewTransaction(), is(true));
verify(bridge).setCurrentTransaction(any());
ArangoTransactionHolder resource = (ArangoTransactionHolder) TransactionSynchronizationManager.getResource(underTest);
Expand All @@ -84,12 +82,8 @@ public void getTransactionReturnsNewTransactionWithoutStreamTransaction() {

@Test
public void innerGetTransactionIsNotNewTransactionIncludingFormerCollections() {
DefaultTransactionAttribute first = new DefaultTransactionAttribute();
first.setLabels(Collections.singleton("foo"));
TransactionStatus outer = underTest.getTransaction(first);
DefaultTransactionAttribute second = new DefaultTransactionAttribute();
second.setLabels(Collections.singleton("bar"));
TransactionStatus inner = underTest.getTransaction(second);
TransactionStatus outer = underTest.getTransaction(createTransactionAttribute("outer", "foo"));
TransactionStatus inner = underTest.getTransaction(createTransactionAttribute("inner", "bar"));
assertThat(inner.isNewTransaction(), is(false));
ArangoTransactionObject transactionObject = getTransactionObject(inner);
assertThat(transactionObject.getHolder().getCollectionNames(), hasItems("foo", "bar"));
Expand All @@ -98,8 +92,8 @@ public void innerGetTransactionIsNotNewTransactionIncludingFormerCollections() {

@Test(expected = UnexpectedRollbackException.class)
public void innerRollbackCausesUnexpectedRollbackOnOuterCommit() {
TransactionStatus outer = underTest.getTransaction(new DefaultTransactionAttribute());
TransactionStatus inner = underTest.getTransaction(new DefaultTransactionAttribute());
TransactionStatus outer = underTest.getTransaction(createTransactionAttribute("outer"));
TransactionStatus inner = underTest.getTransaction(createTransactionAttribute("inner"));
underTest.rollback(inner);
try {
underTest.commit(outer);
Expand All @@ -110,8 +104,7 @@ public void innerRollbackCausesUnexpectedRollbackOnOuterCommit() {

@Test
public void getTransactionReturnsTransactionCreatesStreamTransactionWithAllCollectionsOnBridgeBeginCall() {
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
definition.setLabels(Collections.singleton("baz"));
DefaultTransactionAttribute definition = createTransactionAttribute("timeout", "baz");
definition.setTimeout(20);
TransactionStatus status = underTest.getTransaction(definition);
beginTransaction("123", "foo", "bar");
Expand All @@ -127,17 +120,14 @@ public void getTransactionReturnsTransactionCreatesStreamTransactionWithAllColle

@Test
public void nestedGetTransactionReturnsExistingTransactionWithFormerCollections() {
DefaultTransactionAttribute first = new DefaultTransactionAttribute();
first.setLabels(Collections.singleton("foo"));
TransactionStatus outer = underTest.getTransaction(first);
TransactionStatus outer = underTest.getTransaction(createTransactionAttribute("outer", "foo"));
assertThat(outer.isNewTransaction(), is(true));

beginTransaction("123", "foo", "bar");
when(streamTransaction.getStatus())
.thenReturn(StreamTransactionStatus.running);

DefaultTransactionAttribute second = new DefaultTransactionAttribute();
second.setLabels(Collections.singleton("bar"));
DefaultTransactionAttribute second = createTransactionAttribute("inner", "bar");
TransactionStatus inner1 = underTest.getTransaction(second);
assertThat(inner1.isNewTransaction(), is(false));
ArangoTransactionObject tx1 = getTransactionObject(inner1);
Expand All @@ -155,9 +145,8 @@ public void nestedGetTransactionReturnsExistingTransactionWithFormerCollections(

@Test
public void getTransactionForPropagationSupportsWithoutExistingCreatesDummyTransaction() {
DefaultTransactionAttribute supports = new DefaultTransactionAttribute();
DefaultTransactionAttribute supports = createTransactionAttribute("test", "foo");
supports.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
supports.setLabels(Collections.singleton("foo"));
TransactionStatus empty = underTest.getTransaction(supports);
assertThat(empty.isNewTransaction(), is(false));
underTest.commit(empty);
Expand All @@ -167,12 +156,9 @@ public void getTransactionForPropagationSupportsWithoutExistingCreatesDummyTrans

@Test
public void getTransactionForPropagationSupportsWithExistingCreatesInner() {
DefaultTransactionAttribute first = new DefaultTransactionAttribute();
first.setLabels(Collections.singleton("foo"));
TransactionStatus outer = underTest.getTransaction(first);
DefaultTransactionAttribute supports = new DefaultTransactionAttribute();
TransactionStatus outer = underTest.getTransaction(createTransactionAttribute("outer", "foo"));
DefaultTransactionAttribute supports = createTransactionAttribute("supports", "bar");
supports.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
supports.setLabels(Collections.singleton("bar"));
TransactionStatus inner = underTest.getTransaction(supports);
assertThat(inner.isNewTransaction(), is(false));
underTest.commit(inner);
Expand All @@ -183,10 +169,7 @@ public void getTransactionForPropagationSupportsWithExistingCreatesInner() {

@Test
public void getTransactionWithMultipleBridgeCallsWorksForKnownCollections() {
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
definition.setLabels(Collections.singleton("baz"));
definition.setTimeout(20);
underTest.getTransaction(definition);
underTest.getTransaction(createTransactionAttribute("test", "baz"));
beginTransaction("123", "foo");
beginPassed.getValue().apply(Arrays.asList("foo", "baz"));
verify(database).beginStreamTransaction(optionsPassed.capture());
Expand All @@ -196,10 +179,7 @@ public void getTransactionWithMultipleBridgeCallsWorksForKnownCollections() {

@Test
public void getTransactionWithMultipleBridgeCallsIgnoresAdditionalCollections() {
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
definition.setLabels(Collections.singleton("bar"));
definition.setTimeout(20);
TransactionStatus state = underTest.getTransaction(definition);
TransactionStatus state = underTest.getTransaction(createTransactionAttribute("test", "bar"));
beginTransaction("123", "foo");
beginPassed.getValue().apply(Collections.singletonList("baz"));
assertThat(getTransactionObject(state).getHolder().getCollectionNames(), hasItems("foo", "bar"));
Expand All @@ -208,7 +188,7 @@ public void getTransactionWithMultipleBridgeCallsIgnoresAdditionalCollections()

@Test(expected = InvalidIsolationLevelException.class)
public void getTransactionThrowsInvalidIsolationLevelExceptionForIsolationSerializable() {
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
DefaultTransactionAttribute definition = createTransactionAttribute("serializable");
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
underTest.getTransaction(definition);
}
Expand All @@ -235,4 +215,11 @@ private ArangoTransactionObject getTransactionObject(TransactionStatus status) {
private TransactionCollectionOptions getCollections(StreamTransactionOptions options) {
return (TransactionCollectionOptions) forDirectFieldAccess(options).getPropertyValue("collections");
}

private static DefaultTransactionAttribute createTransactionAttribute(String name, String... collections) {
DefaultTransactionAttribute transactionAttribute = new DefaultTransactionAttribute();
transactionAttribute.setName(name);
transactionAttribute.setLabels(Arrays.asList(collections));
return transactionAttribute;
}
}
3 changes: 2 additions & 1 deletion src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
</encoder>
</appender>

<root level="info">
<root level="warn">
<appender-ref ref="STDOUT" />
</root>
<logger name="com.arangodb.springframework" level="debug" />

<!-- <logger name="com.arangodb.internal.velocystream.internal.MessageStore" level="debug" />-->
<!-- <logger name="com.arangodb.internal.velocystream.VstCommunicationSync" level="debug" />-->
Expand Down

0 comments on commit 0ffeb3c

Please sign in to comment.