Skip to content

Commit

Permalink
separate-projections-poc: MigrationProjectionCache
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Lavrukov committed Jun 2, 2024
1 parent 443869c commit 07f41b1
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -420,25 +420,25 @@ public void update(Entity.Id<T> id, Changeset changeset) {
public T insert(T t) {
T entityToSave = t.preSave();
executor.pendingExecute(YqlStatement.insert(type), entityToSave);
executor.getTransactionLocal().firstLevelCache().put(entityToSave);
executor.getTransactionLocal().projectionCache().save(entityToSave);
executor.getTransactionLocal().firstLevelCache().put(entityToSave);
return t;
}

@Override
public T save(T t) {
T entityToSave = t.preSave();
executor.pendingExecute(YqlStatement.save(type), entityToSave);
executor.getTransactionLocal().firstLevelCache().put(entityToSave);
executor.getTransactionLocal().projectionCache().save(entityToSave);
executor.getTransactionLocal().firstLevelCache().put(entityToSave);
return t;
}

@Override
public void delete(Entity.Id<T> id) {
executor.pendingExecute(YqlStatement.delete(type), id);
executor.getTransactionLocal().firstLevelCache().putEmpty(id);
executor.getTransactionLocal().projectionCache().delete(id);
executor.getTransactionLocal().firstLevelCache().putEmpty(id);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,39 @@
import lombok.NonNull;
import tech.ydb.yoj.repository.BaseDb;
import tech.ydb.yoj.repository.db.TxOptions;
import tech.ydb.yoj.repository.db.projection.MigrationProjectionCache;
import tech.ydb.yoj.repository.db.projection.ProjectionCache;
import tech.ydb.yoj.repository.db.projection.RoProjectionCache;
import tech.ydb.yoj.repository.db.projection.RwProjectionCache;

import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Supplier;

public class TransactionLocal {
private final Map<Supplier<?>, Object> singletons = new IdentityHashMap<>();

private final Supplier<FirstLevelCache> firstLevelCacheSupplier;
private final Supplier<ProjectionCache> projectionCacheSupplier;
private final Supplier<TransactionLog> logSupplier;
private final FirstLevelCache firstLevelCache;
private final ProjectionCache projectionCache;
private final TransactionLog log;

public TransactionLocal(@NonNull TxOptions options) {
this.firstLevelCacheSupplier = options.isFirstLevelCache() ? FirstLevelCache::create : FirstLevelCache::empty;
this.projectionCacheSupplier = options.isMutable() ? RwProjectionCache::new : RoProjectionCache::new;
this.logSupplier = () -> new TransactionLog(options.getLogLevel());
this.firstLevelCache = options.isFirstLevelCache() ? FirstLevelCache.create() : FirstLevelCache.empty();
if (options.isMutable()) {
this.projectionCache = new MigrationProjectionCache(firstLevelCache);
} else {
this.projectionCache = new RoProjectionCache();
}
this.log = new TransactionLog(options.getLogLevel());
}

public static TransactionLocal get() {
return BaseDb.current(Holder.class).getTransactionLocal();
}

@SuppressWarnings("unchecked")
public <X> X instance(@NonNull Supplier<X> supplier) {
return (X) singletons.computeIfAbsent(supplier, Supplier::get);
}

public ProjectionCache projectionCache() {
return instance(projectionCacheSupplier);
return projectionCache;
}

public FirstLevelCache firstLevelCache() {
return instance(firstLevelCacheSupplier);
return firstLevelCache;
}

public TransactionLog log() {
return instance(logSupplier);
return log;
}

public interface Holder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package tech.ydb.yoj.repository.db.projection;

import lombok.RequiredArgsConstructor;
import tech.ydb.yoj.repository.db.Entity;
import tech.ydb.yoj.repository.db.RepositoryTransaction;
import tech.ydb.yoj.repository.db.Tx;
import tech.ydb.yoj.repository.db.cache.FirstLevelCache;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@RequiredArgsConstructor
public class MigrationProjectionCache implements ProjectionCache {
private final FirstLevelCache cache;

@Override
public void load(Entity<?> entity) {
}

@Override
public void save(Entity<?> entity) {
delete(entity.getId());

List<Entity<?>> newProjections = entity.createProjections();
for (Entity<?> projection : newProjections) {
saveEntity(projection);
}
}

@Override
public void delete(Entity.Id<?> id) {
Optional<? extends Entity<?>> oldEntity;
try {
oldEntity = cache.peek(id);
} catch (NoSuchElementException e) {
return;
}

if (oldEntity.isPresent()) {
List<Entity<?>> oldProjections = oldEntity.get().createProjections();
for (Entity<?> projection : oldProjections) {
deleteEntity(projection.getId());
}
}
}

@Override
public void applyProjectionChanges(RepositoryTransaction transaction) {
}

private <T extends Entity<T>> void deleteEntity(Entity.Id<T> entityId) {
getTransaction().table(entityId.getType()).delete(entityId);
}

private <T extends Entity<T>> void saveEntity(Entity<T> entity) {
@SuppressWarnings("unchecked")
T castedEntity = (T) entity;

getTransaction().table(entity.getId().getType()).save(castedEntity);
}

private static RepositoryTransaction getTransaction() {
return Tx.Current.get().getRepositoryTransaction();
}
}

0 comments on commit 07f41b1

Please sign in to comment.