From 7ccfc1211bc36aecbbf72d775761fd6407257cac Mon Sep 17 00:00:00 2001 From: Alexander Lavrukov Date: Mon, 23 Dec 2024 21:14:18 +0300 Subject: [PATCH] Use TableDescriptor in InMemoryTable --- .../test/inmemory/InMemoryDataShard.java | 27 +++++---- .../test/inmemory/InMemoryRepository.java | 20 +++---- .../InMemoryRepositoryTransaction.java | 17 ++++-- .../test/inmemory/InMemoryStorage.java | 60 +++++++++---------- .../test/inmemory/InMemoryTable.java | 53 +++++++++------- .../test/inmemory/InMemoryTxLockWatcher.java | 33 +++++----- .../test/RepositoryTestSupport.java | 11 +--- .../ydb/yoj/repository/ydb/YdbRepository.java | 28 +++------ .../ydb/YdbRepositoryTransaction.java | 6 ++ .../yoj/repository/ydb/table/YdbTable.java | 7 +++ .../java/tech/ydb/yoj/repository/BaseDb.java | 8 ++- .../ydb/yoj/repository/db/Repository.java | 13 ++-- .../repository/db/RepositoryTransaction.java | 6 +- 13 files changed, 156 insertions(+), 133 deletions(-) diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java index 785d8ead..0cfe3abe 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryDataShard.java @@ -6,6 +6,7 @@ import tech.ydb.yoj.repository.db.EntitySchema; import tech.ydb.yoj.repository.db.Range; import tech.ydb.yoj.repository.db.Table; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.ViewSchema; import tech.ydb.yoj.repository.db.exception.EntityAlreadyExistsException; import tech.ydb.yoj.repository.db.exception.OptimisticLockException; @@ -20,21 +21,27 @@ import java.util.TreeMap; final class InMemoryDataShard> { - private final Class type; + private final TableDescriptor tableDescriptor; private final EntitySchema schema; private final TreeMap, InMemoryEntityLine> entityLines; private final Map>> uncommited = new HashMap<>(); private InMemoryDataShard( - Class type, EntitySchema schema, TreeMap, InMemoryEntityLine> entityLines + TableDescriptor tableDescriptor, + EntitySchema schema, + TreeMap, InMemoryEntityLine> entityLines ) { - this.type = type; + this.tableDescriptor = tableDescriptor; this.schema = schema; this.entityLines = entityLines; } - public InMemoryDataShard(Class type) { - this(type, EntitySchema.of(type), createEmptyLines(type)); + public InMemoryDataShard(TableDescriptor tableDescriptor) { + this( + tableDescriptor, + EntitySchema.of(tableDescriptor.entityType()), + createEmptyLines(tableDescriptor.entityType()) + ); } private static > TreeMap, InMemoryEntityLine> createEmptyLines(Class type) { @@ -42,11 +49,11 @@ private static > TreeMap, InMemoryEntityLine> c } public synchronized InMemoryDataShard createSnapshot() { - TreeMap, InMemoryEntityLine> snapshotLines = createEmptyLines(type); + TreeMap, InMemoryEntityLine> snapshotLines = createEmptyLines(tableDescriptor.entityType()); for (Map.Entry, InMemoryEntityLine> entry : entityLines.entrySet()) { snapshotLines.put(entry.getKey(), entry.getValue().createSnapshot()); } - return new InMemoryDataShard<>(type, schema, snapshotLines); + return new InMemoryDataShard<>(tableDescriptor, schema, snapshotLines); } public synchronized void commit(long txId, long version) { @@ -60,14 +67,14 @@ public synchronized void commit(long txId, long version) { } public synchronized void checkLocks(long version, InMemoryTxLockWatcher watcher) { - for (Entity.Id lockedId : watcher.getReadRows(type)) { + for (Entity.Id lockedId : watcher.getReadRows(tableDescriptor)) { InMemoryEntityLine entityLine = entityLines.get(lockedId); if (entityLine != null && entityLine.hasYounger(version)) { throw new OptimisticLockException("Row lock failed " + lockedId); } } - List>> lockedRanges = watcher.getReadRanges(type); + List>> lockedRanges = watcher.getReadRanges(tableDescriptor); if (lockedRanges.isEmpty()) { return; } @@ -79,7 +86,7 @@ public synchronized void checkLocks(long version, InMemoryTxLockWatcher watcher) for (Range> lockedRange: lockedRanges) { if (lockedRange.contains(entry.getKey())) { - throw new OptimisticLockException("Table lock failed " + type.getSimpleName()); + throw new OptimisticLockException("Table lock failed " + tableDescriptor.toDebugString()); } } } diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepository.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepository.java index a133c1b8..21b30de0 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepository.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepository.java @@ -6,11 +6,11 @@ import tech.ydb.yoj.repository.db.Repository; import tech.ydb.yoj.repository.db.RepositoryTransaction; import tech.ydb.yoj.repository.db.SchemaOperations; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.TxOptions; import tech.ydb.yoj.repository.db.exception.DropTableException; import java.util.Map; -import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -37,36 +37,30 @@ public void loadSnapshot(String id) { storage = snapshots.get(id).createSnapshot(); } - @Override - public Set>> tables() { - return Set.copyOf(storage.tables()); - } - @Override public RepositoryTransaction startTransaction(TxOptions options) { return new InMemoryRepositoryTransaction(options, this); } - @Override - public > SchemaOperations schema(Class c) { + public > SchemaOperations schema(TableDescriptor tableDescriptor) { return new SchemaOperations() { @Override public void create() { - storage.createTable(c); + storage.createTable(tableDescriptor); } @Override public void drop() { - if (!storage.dropTable(c)) { - throw new DropTableException( - String.format("Can't drop table %s: table doesn't exist", c.getSimpleName()) + if (!storage.dropTable(tableDescriptor)) { + throw new DropTableException(String.format("Can't drop table %s: table doesn't exist", + tableDescriptor.toDebugString()) ); } } @Override public boolean exists() { - return storage.containsTable(c); + return storage.containsTable(tableDescriptor); } }; } diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepositoryTransaction.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepositoryTransaction.java index 89e15003..b154c3cb 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepositoryTransaction.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryRepositoryTransaction.java @@ -7,6 +7,7 @@ import tech.ydb.yoj.repository.db.Entity; import tech.ydb.yoj.repository.db.RepositoryTransaction; import tech.ydb.yoj.repository.db.Table; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.TxOptions; import tech.ydb.yoj.repository.db.cache.TransactionLocal; import tech.ydb.yoj.repository.db.exception.IllegalTransactionIsolationLevelException; @@ -59,6 +60,12 @@ public > Table table(Class c) { return new InMemoryTable<>(getMemory(c)); } + @Override + public > Table table(TableDescriptor tableDescriptor) { + return new InMemoryTable<>(this, tableDescriptor); + } + + @Deprecated // use other constructor of InMemoryTable public final > InMemoryTable.DbMemory getMemory(Class c) { return new InMemoryTable.DbMemory<>(c, this); } @@ -119,7 +126,7 @@ private boolean isFinalActionNeeded(String action) { } final > void doInWriteTransaction( - String log, Class type, Consumer> consumer + String log, TableDescriptor tableDescriptor, Consumer> consumer ) { if (options.isScan()) { throw new IllegalTransactionScanException("Mutable operations"); @@ -129,7 +136,7 @@ final > void doInWriteTransaction( } Runnable query = () -> logTransaction(log, () -> { - WriteTxDataShard shard = storage.getWriteTxDataShard(type, txId, getVersion()); + WriteTxDataShard shard = storage.getWriteTxDataShard(tableDescriptor, txId, getVersion()); consumer.accept(shard); hasWrites = true; @@ -143,11 +150,13 @@ final > void doInWriteTransaction( } final , R> R doInTransaction( - String action, Class type, Function, R> func + String action, TableDescriptor tableDescriptor, Function, R> func ) { return logTransaction(action, () -> { InMemoryTxLockWatcher findWatcher = hasWrites ? watcher : InMemoryTxLockWatcher.NO_LOCKS; - ReadOnlyTxDataShard shard = storage.getReadOnlyTxDataShard(type, txId, getVersion(), findWatcher); + ReadOnlyTxDataShard shard = storage.getReadOnlyTxDataShard( + tableDescriptor, txId, getVersion(), findWatcher + ); try { return func.apply(shard); } catch (OptimisticLockException e) { diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryStorage.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryStorage.java index 353ce90c..f78d86f6 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryStorage.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryStorage.java @@ -1,6 +1,7 @@ package tech.ydb.yoj.repository.test.inmemory; import tech.ydb.yoj.repository.db.Entity; +import tech.ydb.yoj.repository.db.TableDescriptor; import java.util.HashMap; import java.util.HashSet; @@ -8,8 +9,8 @@ import java.util.Set; final class InMemoryStorage { - private final Map, InMemoryDataShard> shards; - private final Map>> uncommited = new HashMap<>(); + private final Map, InMemoryDataShard> shards; + private final Map>> uncommited = new HashMap<>(); private long currentVersion; @@ -17,7 +18,7 @@ public InMemoryStorage() { this(0, new HashMap<>()); } - private InMemoryStorage(long version, Map, InMemoryDataShard> shards) { + private InMemoryStorage(long version, Map, InMemoryDataShard> shards) { this.shards = shards; this.currentVersion = version; } @@ -27,8 +28,8 @@ public synchronized long getCurrentVersion() { } public synchronized InMemoryStorage createSnapshot() { - Map, InMemoryDataShard> snapshotDb = new HashMap<>(); - for (Map.Entry, InMemoryDataShard> entry : shards.entrySet()) { + Map, InMemoryDataShard> snapshotDb = new HashMap<>(); + for (Map.Entry, InMemoryDataShard> entry : shards.entrySet()) { snapshotDb.put(entry.getKey(), entry.getValue().createSnapshot()); } return new InMemoryStorage(currentVersion, snapshotDb); @@ -45,42 +46,42 @@ public synchronized void commit(long txId, long version, InMemoryTxLockWatcher w currentVersion++; - Set> uncommitedTables = uncommited.remove(txId); - for (Class type : uncommitedTables) { - shards.get(type).commit(txId, currentVersion); + Set> uncommitedTables = uncommited.remove(txId); + for (TableDescriptor tableDescriptor : uncommitedTables) { + shards.get(tableDescriptor).commit(txId, currentVersion); } } public synchronized void rollback(long txId) { - Set> uncommitedTables = uncommited.remove(txId); + Set> uncommitedTables = uncommited.remove(txId); if (uncommitedTables == null) { return; } - for (Class type : uncommitedTables) { - shards.get(type).rollback(txId); + for (TableDescriptor tableDescriptor : uncommitedTables) { + shards.get(tableDescriptor).rollback(txId); } } public synchronized > WriteTxDataShard getWriteTxDataShard( - Class type, long txId, long version + TableDescriptor tableDescriptor, long txId, long version ) { - uncommited.computeIfAbsent(txId, __ -> new HashSet<>()).add(type); - return getTxDataShard(type, txId, version, InMemoryTxLockWatcher.NO_LOCKS); + uncommited.computeIfAbsent(txId, __ -> new HashSet<>()).add(tableDescriptor); + return getTxDataShard(tableDescriptor, txId, version, InMemoryTxLockWatcher.NO_LOCKS); } public synchronized > ReadOnlyTxDataShard getReadOnlyTxDataShard( - Class type, long txId, long version, InMemoryTxLockWatcher watcher + TableDescriptor tableDescriptor, long txId, long version, InMemoryTxLockWatcher watcher ) { - return getTxDataShard(type, txId, version, watcher); + return getTxDataShard(tableDescriptor, txId, version, watcher); } private > TxDataShardImpl getTxDataShard( - Class type, long txId, long version, InMemoryTxLockWatcher watcher + TableDescriptor tableDescriptor, long txId, long version, InMemoryTxLockWatcher watcher ) { @SuppressWarnings("unchecked") - InMemoryDataShard shard = (InMemoryDataShard) shards.get(type); + InMemoryDataShard shard = (InMemoryDataShard) shards.get(tableDescriptor); if (shard == null) { - throw new InMemoryRepositoryException("Table is not created: " + type.getSimpleName()); + throw new InMemoryRepositoryException("Table is not created: " + tableDescriptor.toDebugString()); } return new TxDataShardImpl<>(shard, txId, version, watcher); } @@ -89,27 +90,26 @@ public synchronized void dropDb() { shards.clear(); } - @SuppressWarnings({"unchecked", "rawtypes"}) - public synchronized Set>> tables() { - return (Set) shards.keySet(); + public synchronized Set> tables() { + return shards.keySet(); } - public synchronized boolean containsTable(Class type) { - return shards.containsKey(type); + public synchronized boolean containsTable(TableDescriptor tableDescriptor) { + return shards.containsKey(tableDescriptor); } - public synchronized > void createTable(Class type) { - if (containsTable(type)) { + public synchronized > void createTable(TableDescriptor tableDescriptor) { + if (containsTable(tableDescriptor)) { return; } - shards.put(type, new InMemoryDataShard<>(type)); + shards.put(tableDescriptor, new InMemoryDataShard<>(tableDescriptor)); } - public synchronized boolean dropTable(Class type) { - if (!containsTable(type)) { + public synchronized boolean dropTable(TableDescriptor tableDescriptor) { + if (!containsTable(tableDescriptor)) { return false; } - shards.remove(type); + shards.remove(tableDescriptor); return true; } } diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTable.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTable.java index 47b4e308..3779071e 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTable.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTable.java @@ -33,21 +33,28 @@ import static java.util.stream.Collectors.toUnmodifiableSet; public class InMemoryTable> implements Table { - private final Class type; private final EntitySchema schema; private final TableDescriptor tableDescriptor; private final InMemoryRepositoryTransaction transaction; + @Deprecated // Don't use DbMemory, use other constructor instead public InMemoryTable(DbMemory memory) { - this.type = memory.type(); - this.schema = EntitySchema.of(type); + this(memory.transaction(), memory.type()); + } + + public InMemoryTable(InMemoryRepositoryTransaction transaction, Class type) { + this(transaction, TableDescriptor.from(EntitySchema.of(type))); + } + + public InMemoryTable(InMemoryRepositoryTransaction transaction, TableDescriptor tableDescriptor) { + this.schema = EntitySchema.of(tableDescriptor.entityType()); this.tableDescriptor = TableDescriptor.from(schema); - this.transaction = memory.transaction(); + this.transaction = transaction; } @Override public List findAll() { - transaction.getWatcher().markTableRead(type); + transaction.getWatcher().markTableRead(tableDescriptor); return findAll0(); } @@ -155,7 +162,7 @@ public , ID extends Entity.Id> Stream readTable( @Override public Class getType() { - return type; + return tableDescriptor.entityType(); } @Override @@ -165,7 +172,7 @@ public T find(Entity.Id id) { } return transaction.getTransactionLocal().firstLevelCache().get(id, __ -> { markKeyRead(id); - T entity = transaction.doInTransaction("find(" + id + ")", type, shard -> shard.find(id)); + T entity = transaction.doInTransaction("find(" + id + ")", tableDescriptor, shard -> shard.find(id)); return postLoad(entity); }); } @@ -184,13 +191,13 @@ public V find(Class viewType, Entity.Id id) { } markKeyRead(id); - return transaction.doInTransaction("find(" + id + ")", type, shard -> shard.find(id, viewType)); + return transaction.doInTransaction("find(" + id + ")", tableDescriptor, shard -> shard.find(id, viewType)); } @Override @SuppressWarnings("unchecked") public > List find(Range range) { - transaction.getWatcher().markRangeRead(type, range); + transaction.getWatcher().markRangeRead(tableDescriptor, range); return findAll0().stream() .filter(e -> range.contains((ID) e.getId())) .sorted(EntityIdSchema.SORT_ENTITY_BY_ID) @@ -352,7 +359,7 @@ public List find( ); for (Map id : keysSet) { - transaction.getWatcher().markRangeRead(type, id); + transaction.getWatcher().markRangeRead(tableDescriptor, id); } Stream result = getAllEntries().stream() @@ -388,9 +395,9 @@ private > void markKeyRead(ID id) { EntityIdSchema> idSchema = schema.getIdSchema(); if (idSchema.flattenFieldNames().size() != idSchema.flatten(id).size()) { // Partial key, will throw error when not searching by PK prefix - transaction.getWatcher().markRangeRead(type, Range.create(id, id)); + transaction.getWatcher().markRangeRead(tableDescriptor, Range.create(id, id)); } else { - transaction.getWatcher().markRowRead(type, id); + transaction.getWatcher().markRowRead(tableDescriptor, id); } } @@ -406,8 +413,8 @@ public > List findIds(Set ids) { @Override public T insert(T tt) { T t = tt.preSave(); - transaction.getWatcher().markRowRead(type, t.getId()); - transaction.doInWriteTransaction("insert(" + t + ")", type, shard -> shard.insert(t)); + transaction.getWatcher().markRowRead(tableDescriptor, t.getId()); + transaction.doInWriteTransaction("insert(" + t + ")", tableDescriptor, shard -> shard.insert(t)); transaction.getTransactionLocal().firstLevelCache().put(t); transaction.getTransactionLocal().projectionCache().save(t); return t; @@ -416,7 +423,7 @@ public T insert(T tt) { @Override public T save(T tt) { T t = tt.preSave(); - transaction.doInWriteTransaction("save(" + t + ")", type, shard -> shard.save(t)); + transaction.doInWriteTransaction("save(" + t + ")", tableDescriptor, shard -> shard.save(t)); transaction.getTransactionLocal().firstLevelCache().put(t); transaction.getTransactionLocal().projectionCache().save(t); return t; @@ -424,18 +431,22 @@ public T save(T tt) { @Override public void delete(Entity.Id id) { - transaction.doInWriteTransaction("delete(" + id + ")", type, shard -> shard.delete(id)); + transaction.doInWriteTransaction("delete(" + id + ")", tableDescriptor, shard -> shard.delete(id)); transaction.getTransactionLocal().firstLevelCache().putEmpty(id); transaction.getTransactionLocal().projectionCache().delete(id); } @Override public void deleteAll() { - transaction.doInWriteTransaction("deleteAll(" + type.getName() + ")", type, WriteTxDataShard::deleteAll); + transaction.doInWriteTransaction( + "deleteAll(" + tableDescriptor.toDebugString() + ")", tableDescriptor, WriteTxDataShard::deleteAll + ); } private List getAllEntries() { - return transaction.doInTransaction("findAll(" + type.getName() + ")", type, ReadOnlyTxDataShard::findAll); + return transaction.doInTransaction( + "findAll(" + tableDescriptor.toDebugString() + ")", tableDescriptor, ReadOnlyTxDataShard::findAll + ); } private List findAll0() { @@ -494,9 +505,9 @@ public > Stream streamPartialIds(ID partial, int bat private > void markRangeRead(Range range) { if (range == null) { - transaction.getWatcher().markTableRead(type); + transaction.getWatcher().markTableRead(tableDescriptor); } else { - transaction.getWatcher().markRangeRead(type, range); + transaction.getWatcher().markRangeRead(tableDescriptor, range); } } @@ -565,6 +576,8 @@ private static > V toView( return Columns.fromEntity(schema, entity).toSchema(viewSchema); } + + @Deprecated // Legacy. Using only for creating InMemoryTable. Use constructor of InMemoryTable instead public record DbMemory>( Class type, InMemoryRepositoryTransaction transaction diff --git a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTxLockWatcher.java b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTxLockWatcher.java index 6d7d7b87..878280b2 100644 --- a/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTxLockWatcher.java +++ b/repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTxLockWatcher.java @@ -5,6 +5,7 @@ import tech.ydb.yoj.repository.db.Entity; import tech.ydb.yoj.repository.db.EntitySchema; import tech.ydb.yoj.repository.db.Range; +import tech.ydb.yoj.repository.db.TableDescriptor; import java.util.ArrayList; import java.util.HashMap; @@ -17,40 +18,40 @@ public final class InMemoryTxLockWatcher { public static final InMemoryTxLockWatcher NO_LOCKS = new InMemoryTxLockWatcher(Map.of(), Map.of()); - private final Map, Set>> readRows; - private final Map, List>> readRanges; + private final Map, Set>> readRows; + private final Map, List>> readRanges; public InMemoryTxLockWatcher() { this(new HashMap<>(), new HashMap<>()); } - public > void markRowRead(Class type, Entity.Id id) { - readRows.computeIfAbsent(type, __ -> new HashSet<>()).add(id); + public > void markRowRead(TableDescriptor tableDescriptor, Entity.Id id) { + readRows.computeIfAbsent(tableDescriptor, __ -> new HashSet<>()).add(id); } - public , ID extends Entity.Id> void markRangeRead(Class type, Range range) { - readRanges.computeIfAbsent(type, __ -> new ArrayList<>()).add(range); + public , ID extends Entity.Id> void markRangeRead(TableDescriptor tableDescriptor, Range range) { + readRanges.computeIfAbsent(tableDescriptor, __ -> new ArrayList<>()).add(range); } - public , ID extends Entity.Id> void markRangeRead(Class type, Map map) { - Range range = Range.create(EntitySchema.of(type).getIdSchema(), map); - markRangeRead(type, range); + public , ID extends Entity.Id> void markRangeRead(TableDescriptor tableDescriptor, Map map) { + Range range = Range.create(EntitySchema.of(tableDescriptor.entityType()).getIdSchema(), map); + markRangeRead(tableDescriptor, range); } - public , ID extends Entity.Id> void markTableRead(Class type) { - Range range = Range.create(EntitySchema.of(type).getIdSchema(), Map.of()); - markRangeRead(type, range); + public , ID extends Entity.Id> void markTableRead(TableDescriptor tableDescriptor) { + Range range = Range.create(EntitySchema.of(tableDescriptor.entityType()).getIdSchema(), Map.of()); + markRangeRead(tableDescriptor, range); } - public > Set> getReadRows(Class type) { + public > Set> getReadRows(TableDescriptor tableDescriptor) { @SuppressWarnings({"unchecked", "rawtypes"}) - Set> lockedRows = (Set) readRows.getOrDefault(type, Set.of()); + Set> lockedRows = (Set) readRows.getOrDefault(tableDescriptor, Set.of()); return lockedRows; } - public > List>> getReadRanges(Class type) { + public > List>> getReadRanges(TableDescriptor tableDescriptor) { @SuppressWarnings({"unchecked", "rawtypes"}) - List>> lockedRanges = (List) readRanges.getOrDefault(type, List.of()); + List>> lockedRanges = (List) readRanges.getOrDefault(tableDescriptor, List.of()); return lockedRanges; } } diff --git a/repository-test/src/main/java/tech/ydb/yoj/repository/test/RepositoryTestSupport.java b/repository-test/src/main/java/tech/ydb/yoj/repository/test/RepositoryTestSupport.java index 6cbe33db..35c47e63 100644 --- a/repository-test/src/main/java/tech/ydb/yoj/repository/test/RepositoryTestSupport.java +++ b/repository-test/src/main/java/tech/ydb/yoj/repository/test/RepositoryTestSupport.java @@ -3,8 +3,6 @@ import org.junit.After; import org.junit.Before; import tech.ydb.yoj.repository.db.Repository; -import tech.ydb.yoj.repository.db.StdTxManager; -import tech.ydb.yoj.repository.db.Tx; import java.util.IdentityHashMap; import java.util.Map; @@ -30,13 +28,6 @@ public void setUp() { @After public void tearDown() { - clearDb(this.repository); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public static void clearDb(Repository repo) { - var tables = repo.tables(); - new StdTxManager(repo).tx(() -> tables - .forEach(table -> Tx.Current.get().getRepositoryTransaction().table((Class) table).deleteAll())); + repository.dropDb(); } } diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepository.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepository.java index dcfe87ed..63d38691 100644 --- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepository.java +++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepository.java @@ -18,6 +18,7 @@ import tech.ydb.yoj.repository.db.Repository; import tech.ydb.yoj.repository.db.RepositoryTransaction; import tech.ydb.yoj.repository.db.SchemaOperations; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.TxOptions; import tech.ydb.yoj.repository.ydb.client.SessionManager; import tech.ydb.yoj.repository.ydb.client.YdbPaths; @@ -34,15 +35,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Objects; -import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import static java.util.stream.Collectors.toUnmodifiableSet; import static tech.ydb.yoj.repository.ydb.client.YdbPaths.canonicalDatabase; public class YdbRepository implements Repository { @@ -198,14 +196,6 @@ public void createTablespace() { getSchemaOperations().createTablespace(); } - @Override - public Set>> tables() { - return getSchemaOperations().getTableNames().stream() - .map(entityClassesByTableName::get) - .filter(Objects::nonNull) - .collect(toUnmodifiableSet()); - } - @Override public RepositoryTransaction startTransaction(TxOptions options) { return new YdbRepositoryTransaction<>(this, options); @@ -249,12 +239,12 @@ public void dropDb() { } @Override - public > SchemaOperations schema(Class c) { - EntitySchema schema = EntitySchema.of(c); + public > SchemaOperations schema(TableDescriptor tableDescriptor) { + EntitySchema schema = EntitySchema.of(tableDescriptor.entityType()); return new SchemaOperations<>() { @Override public void create() { - String tableName = schema.getName(); + String tableName = tableDescriptor.tableName(); getSchemaOperations().createTable( tableName, schema.flattenFields(), @@ -264,12 +254,12 @@ public void create() { schema.getTtlModifier(), schema.getChangefeeds() ); - entityClassesByTableName.put(tableName, c); + entityClassesByTableName.put(tableName, tableDescriptor.entityType()); } private YdbTableHint extractHint() { try { - Field ydbTableHintField = c.getDeclaredField("ydbTableHint"); + Field ydbTableHintField = tableDescriptor.entityType().getDeclaredField("ydbTableHint"); ydbTableHintField.setAccessible(true); return (YdbTableHint) ydbTableHintField.get(null); } catch (NoSuchFieldException | IllegalAccessException ignored) { @@ -279,17 +269,17 @@ private YdbTableHint extractHint() { @Override public void drop() { - String tableName = schema.getName(); + String tableName = tableDescriptor.tableName(); getSchemaOperations().dropTable(tableName); entityClassesByTableName.remove(tableName); } @Override public boolean exists() { - String tableName = schema.getName(); + String tableName = tableDescriptor.tableName(); boolean exists = getSchemaOperations().hasTable(tableName); if (exists) { - entityClassesByTableName.put(tableName, c); + entityClassesByTableName.put(tableName, tableDescriptor.entityType()); } else { entityClassesByTableName.remove(tableName); } diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepositoryTransaction.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepositoryTransaction.java index 5a9edd93..55a184e6 100644 --- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepositoryTransaction.java +++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/YdbRepositoryTransaction.java @@ -36,6 +36,7 @@ import tech.ydb.yoj.repository.db.IsolationLevel; import tech.ydb.yoj.repository.db.RepositoryTransaction; import tech.ydb.yoj.repository.db.Table; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.TxOptions; import tech.ydb.yoj.repository.db.bulk.BulkParams; import tech.ydb.yoj.repository.db.cache.RepositoryCache; @@ -120,6 +121,11 @@ public > Table table(Class c) { return new YdbTable<>(c, this); } + @Override + public > Table table(TableDescriptor tableDescriptor) { + return new YdbTable<>(tableDescriptor, this); + } + @Override public void commit() { if (isBadSession) { diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java index ba253df8..393853cd 100644 --- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java +++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java @@ -85,6 +85,13 @@ protected YdbTable(QueryExecutor executor) { this.tableDescriptor = TableDescriptor.from(schema); } + public YdbTable(TableDescriptor tableDescriptor, QueryExecutor executor) { + this.type = tableDescriptor.entityType(); + this.executor = new CheckingQueryExecutor(executor); + this.schema = EntitySchema.of(type); + this.tableDescriptor = tableDescriptor; + } + @SuppressWarnings("unchecked") private Class resolveEntityType() { return (Class) (new TypeToken(getClass()) { diff --git a/repository/src/main/java/tech/ydb/yoj/repository/BaseDb.java b/repository/src/main/java/tech/ydb/yoj/repository/BaseDb.java index 7a0eaf2b..ebeffbde 100644 --- a/repository/src/main/java/tech/ydb/yoj/repository/BaseDb.java +++ b/repository/src/main/java/tech/ydb/yoj/repository/BaseDb.java @@ -1,7 +1,9 @@ package tech.ydb.yoj.repository; import tech.ydb.yoj.repository.db.Entity; +import tech.ydb.yoj.repository.db.EntitySchema; import tech.ydb.yoj.repository.db.Table; +import tech.ydb.yoj.repository.db.TableDescriptor; import tech.ydb.yoj.repository.db.Tx; import tech.ydb.yoj.util.lang.Proxies; @@ -10,5 +12,9 @@ static T current(Class type) { return Proxies.proxy(type, () -> Tx.Current.get().getRepositoryTransaction()); } - > Table table(Class c); + default > Table table(Class c) { + return table(TableDescriptor.from(EntitySchema.of(c))); + } + + > Table table(TableDescriptor tableDescriptor); } diff --git a/repository/src/main/java/tech/ydb/yoj/repository/db/Repository.java b/repository/src/main/java/tech/ydb/yoj/repository/db/Repository.java index f7b44ca6..ecdc8aad 100644 --- a/repository/src/main/java/tech/ydb/yoj/repository/db/Repository.java +++ b/repository/src/main/java/tech/ydb/yoj/repository/db/Repository.java @@ -1,7 +1,5 @@ package tech.ydb.yoj.repository.db; -import java.util.Set; - public interface Repository { default void createTablespace() { } @@ -12,14 +10,11 @@ default void checkDataCompatibility() { default void checkSchemaCompatibility() { } - > SchemaOperations schema(Class c); + default > SchemaOperations schema(Class c) { + return schema(TableDescriptor.from(EntitySchema.of(c))); + } - /** - * @deprecated For testing purposes only. Will only reliably work for tables that were created or inspected - * using calls to {@link #schema(Class)}. - */ - @Deprecated - Set>> tables(); + > SchemaOperations schema(TableDescriptor c); default RepositoryTransaction startTransaction() { return startTransaction(IsolationLevel.SERIALIZABLE_READ_WRITE); diff --git a/repository/src/main/java/tech/ydb/yoj/repository/db/RepositoryTransaction.java b/repository/src/main/java/tech/ydb/yoj/repository/db/RepositoryTransaction.java index 112f9c8c..4a5d9e8a 100644 --- a/repository/src/main/java/tech/ydb/yoj/repository/db/RepositoryTransaction.java +++ b/repository/src/main/java/tech/ydb/yoj/repository/db/RepositoryTransaction.java @@ -8,7 +8,11 @@ * one call to either method) lest your transaction stays active on the DB server. */ public interface RepositoryTransaction { - > Table table(Class c); + default > Table table(Class c) { + return table(TableDescriptor.from(EntitySchema.of(c))); + } + + > Table table(TableDescriptor tableDescriptor); /** * Commits the transaction or throws exception. Note that this method is not expected to be called, if the last