Skip to content

Commit

Permalink
#250 avoid collection creation or index creation inside transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
aburmeis committed Aug 23, 2023
1 parent b9b48d3 commit e75199b
Showing 1 changed file with 33 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.domain.Persistable;
Expand Down Expand Up @@ -155,30 +156,33 @@ private DataAccessException translateExceptionIfPossible(final RuntimeException
return exceptionTranslator.translateExceptionIfPossible(exception);
}

private ArangoCollection _collection(final String name) {
return _collection(name, null, null);
private ArangoCollection _collection(final String name, boolean transactional) {
return _collection(name, null, null, transactional);
}

private ArangoCollection _collection(final Class<?> entityClass) {
return _collection(entityClass, null);
private ArangoCollection _collection(final Class<?> entityClass, boolean transactional) {
return _collection(entityClass, null, transactional);
}

private ArangoCollection _collection(final Class<?> entityClass, final Object id) {
private ArangoCollection _collection(final Class<?> entityClass, final Object id, boolean transactional) {
final ArangoPersistentEntity<?> persistentEntity = converter.getMappingContext()
.getRequiredPersistentEntity(entityClass);
final String name = determineCollectionFromId(id).orElse(persistentEntity.getCollection());
return _collection(name, persistentEntity, persistentEntity.getCollectionOptions());
return _collection(name, persistentEntity, persistentEntity.getCollectionOptions(), transactional;
}

private ArangoCollection _collection(final String name, final ArangoPersistentEntity<?> persistentEntity,
final CollectionCreateOptions options) {
final CollectionCreateOptions options, boolean transactional) {

final ArangoDatabase db = db();
final Class<?> entityClass = persistentEntity != null ? persistentEntity.getType() : null;
final CollectionCacheValue value = collectionCache.computeIfAbsent(new CollectionCacheKey(db.name(), name),
key -> {
final ArangoCollection collection = db.collection(name);
if (!collection.exists()) {
if (transactional) {
throw new InvalidDataAccessResourceUsageException("Missing collection cannot be created during transaction");
}
collection.create(options);
}
return new CollectionCacheValue(collection);
Expand All @@ -187,7 +191,9 @@ private ArangoCollection _collection(final String name, final ArangoPersistentEn
final ArangoCollection collection = value.getCollection();
if (persistentEntity != null && !entities.contains(entityClass)) {
value.addEntityClass(entityClass);
ensureCollectionIndexes(collection(collection), persistentEntity);
if (!transactional) {
ensureCollectionIndexes(collection(collection), persistentEntity);
}
}
return collection;
}
Expand Down Expand Up @@ -334,14 +340,14 @@ public ArangoDBVersion getVersion() throws DataAccessException {
@Override
public <T> ArangoCursor<T> query(final String query, final Map<String, Object> bindVars,
final AqlQueryOptions options, final Class<T> entityClass) throws DataAccessException {
return db().query(query, bindVars == null ? null : prepareBindVars(bindVars), options, entityClass);
return db().query(query, bindVars == null ? null : prepareBindVars(bindVars, false), options, entityClass);
}

private Map<String, Object> prepareBindVars(final Map<String, Object> bindVars) {
private Map<String, Object> prepareBindVars(final Map<String, Object> bindVars, boolean transactional) {
final Map<String, Object> prepared = new HashMap<>(bindVars.size());
for (final Entry<String, Object> entry : bindVars.entrySet()) {
if (entry.getKey().startsWith("@") && entry.getValue() instanceof Class) {
prepared.put(entry.getKey(), _collection((Class<?>) entry.getValue()).name());
prepared.put(entry.getKey(), _collection((Class<?>) entry.getValue(), transactional).name());
} else {
prepared.put(entry.getKey(), toVPack(entry.getValue()));
}
Expand All @@ -357,7 +363,7 @@ public MultiDocumentEntity<? extends DocumentEntity> delete(final Iterable<Objec

MultiDocumentEntity<? extends DocumentEntity> result;
try {
result = _collection(entityClass).deleteDocuments(toVPackCollection(values), entityClass, options);
result = _collection(entityClass, options.getStreamTransactionId() != null).deleteDocuments(toVPackCollection(values), entityClass, options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -374,7 +380,7 @@ public DocumentEntity delete(final Object id, final Class<?> entityClass, final

final DocumentEntity result;
try {
result = _collection(entityClass, id).deleteDocument(determineDocumentKeyFromId(id), entityClass, options);
result = _collection(entityClass, id, options.getStreamTransactionId() != null).deleteDocument(determineDocumentKeyFromId(id), entityClass, options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -391,7 +397,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> update(final Iterable<T

final MultiDocumentEntity<? extends DocumentEntity> result;
try {
result = _collection(entityClass).updateDocuments(toVPackCollection(values), options);
result = _collection(entityClass, options.getStreamTransactionId() != null).updateDocuments(toVPackCollection(values), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -409,7 +415,7 @@ public DocumentEntity update(final Object id, final Object value, final Document

final DocumentEntity result;
try {
result = _collection(value.getClass(), id).updateDocument(determineDocumentKeyFromId(id), toVPack(value),
result = _collection(value.getClass(), id, options.getStreamTransactionId() != null).updateDocument(determineDocumentKeyFromId(id), toVPack(value),
options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
Expand All @@ -428,7 +434,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> replace(final Iterable<

final MultiDocumentEntity<? extends DocumentEntity> result;
try {
result = _collection(entityClass).replaceDocuments(toVPackCollection(values), options);
result = _collection(entityClass, options.getStreamTransactionId() != null).replaceDocuments(toVPackCollection(values), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -445,7 +451,7 @@ public DocumentEntity replace(final Object id, final Object value, final Documen

final DocumentEntity result;
try {
result = _collection(value.getClass(), id).replaceDocument(determineDocumentKeyFromId(id), toVPack(value),
result = _collection(value.getClass(), id, false).replaceDocument(determineDocumentKeyFromId(id), toVPack(value),
options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
Expand All @@ -460,7 +466,7 @@ public DocumentEntity replace(final Object id, final Object value, final Documen
public <T> Optional<T> find(final Object id, final Class<T> entityClass, final DocumentReadOptions options)
throws DataAccessException {
try {
final VPackSlice doc = _collection(entityClass, id).getDocument(determineDocumentKeyFromId(id),
final VPackSlice doc = _collection(entityClass, id, options.getStreamTransactionId() != null).getDocument(determineDocumentKeyFromId(id),
VPackSlice.class, options);
return Optional.ofNullable(fromVPack(entityClass, doc));
} catch (final ArangoDBException e) {
Expand All @@ -481,7 +487,7 @@ public <T> Iterable<T> find(final Iterable<?> ids, final Class<T> entityClass, D
try {
final Collection<String> keys = new ArrayList<>();
ids.forEach(id -> keys.add(determineDocumentKeyFromId(id)));
final MultiDocumentEntity<VPackSlice> docs = _collection(entityClass).getDocuments(keys, VPackSlice.class, options);
final MultiDocumentEntity<VPackSlice> docs = _collection(entityClass, options.getStreamTransactionId() != null).getDocuments(keys, VPackSlice.class, options);
return docs.getDocuments().stream().map(doc -> fromVPack(entityClass, doc)).collect(Collectors.toList());
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
Expand All @@ -496,7 +502,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> insert(final Iterable<T

final MultiDocumentEntity<? extends DocumentEntity> result;
try {
result = _collection(entityClass).insertDocuments(toVPackCollection(values), options);
result = _collection(entityClass, options.getStreamTransactionId() != null).insertDocuments(toVPackCollection(values), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -512,7 +518,7 @@ public DocumentEntity insert(final Object value, final DocumentCreateOptions opt

final DocumentEntity result;
try {
result = _collection(value.getClass()).insertDocument(toVPack(value), options);
result = _collection(value.getClass(), options.getStreamTransactionId() != null).insertDocument(toVPack(value), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -529,7 +535,7 @@ public DocumentEntity insert(final String collectionName, final Object value, fi

final DocumentEntity result;
try {
result = _collection(collectionName).insertDocument(toVPack(value), options);
result = _collection(collectionName, options.getStreamTransactionId() != null).insertDocument(toVPack(value), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand Down Expand Up @@ -610,7 +616,7 @@ public <T> void upsert(final Iterable<T> value, final UpsertStrategy strategy) t
@Override
public <T> void repsert(final T value, AqlQueryOptions options) throws DataAccessException {
@SuppressWarnings("unchecked") final Class<T> clazz = (Class<T>) value.getClass();
final String collectionName = _collection(clazz).name();
final String collectionName = _collection(clazz, options.getStreamTransactionId() != null).name();

potentiallyEmitEvent(new BeforeSaveEvent<>(value));

Expand Down Expand Up @@ -638,7 +644,7 @@ public <T> void repsert(final Iterable<? extends T> values, final Class<T> entit
return;
}

final String collectionName = _collection(entityClass).name();
final String collectionName = _collection(entityClass, options.getStreamTransactionId() != null).name();
potentiallyEmitBeforeSaveEvent(values);

final Iterable<? extends T> result;
Expand Down Expand Up @@ -730,7 +736,7 @@ private void updateDBFields(final Object value, final DocumentEntity documentEnt
@Override
public boolean exists(final Object id, final Class<?> entityClass, DocumentExistsOptions options) throws DataAccessException {
try {
return _collection(entityClass).documentExists(determineDocumentKeyFromId(id), options);
return _collection(entityClass, options.getStreamTransactionId() != null).documentExists(determineDocumentKeyFromId(id), options);
} catch (final ArangoDBException e) {
throw translateExceptionIfPossible(e);
}
Expand All @@ -751,18 +757,13 @@ public void dropDatabase() throws DataAccessException {

@Override
public CollectionOperations collection(final Class<?> entityClass) throws DataAccessException {
return collection(_collection(entityClass));
}

@Override
public CollectionOperations collection(final String name) throws DataAccessException {
return ArangoOperations.super.collection(name);
return collection(_collection(entityClass, false));
}

@Override
public CollectionOperations collection(final String name, final CollectionCreateOptions options)
throws DataAccessException {
return collection(_collection(name, null, options));
return collection(_collection(name, null, options, false));
}

private CollectionOperations collection(final ArangoCollection collection) {
Expand Down

0 comments on commit e75199b

Please sign in to comment.