Skip to content

Commit bddf084

Browse files
author
Alexander Lavrukov
committed
split-table: split Table interface by behavior
1 parent 3f96e88 commit bddf084

File tree

8 files changed

+391
-345
lines changed

8 files changed

+391
-345
lines changed

repository/src/main/java/tech/ydb/yoj/repository/db/AbstractDelegatingTable.java

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import tech.ydb.yoj.databind.expression.FilterExpression;
77
import tech.ydb.yoj.databind.expression.OrderExpression;
88
import tech.ydb.yoj.repository.BaseDb;
9+
import tech.ydb.yoj.repository.db.cache.FirstLevelCache;
910
import tech.ydb.yoj.repository.db.readtable.ReadTableParams;
1011
import tech.ydb.yoj.repository.db.statement.Changeset;
1112

@@ -32,6 +33,11 @@ private Class<T> resolveEntityType() {
3233
}).getRawType();
3334
}
3435

36+
@Override
37+
public FirstLevelCache getFirstLevelCache() {
38+
return target.getFirstLevelCache();
39+
}
40+
3541
@Override
3642
public List<T> find(@Nullable String indexName, @Nullable FilterExpression<T> filter, @Nullable OrderExpression<T> orderBy, @Nullable Integer limit, @Nullable Long offset) {
3743
return target.find(indexName, filter, orderBy, limit, offset);

repository/src/main/java/tech/ydb/yoj/repository/db/Table.java

+4-343
Original file line numberDiff line numberDiff line change
@@ -1,355 +1,16 @@
11
package tech.ydb.yoj.repository.db;
22

3-
import com.google.common.collect.Sets;
4-
import lombok.NonNull;
5-
import tech.ydb.yoj.databind.expression.FilterExpression;
6-
import tech.ydb.yoj.databind.expression.OrderExpression;
73
import tech.ydb.yoj.repository.db.bulk.BulkParams;
8-
import tech.ydb.yoj.repository.db.cache.FirstLevelCache;
9-
import tech.ydb.yoj.repository.db.list.ListRequest;
10-
import tech.ydb.yoj.repository.db.list.ListResult;
11-
import tech.ydb.yoj.repository.db.list.ViewListResult;
12-
import tech.ydb.yoj.repository.db.readtable.ReadTableParams;
13-
import tech.ydb.yoj.repository.db.statement.Changeset;
4+
import tech.ydb.yoj.repository.db.table.TableReader;
5+
import tech.ydb.yoj.repository.db.table.WriteTable;
146

15-
import javax.annotation.CheckForNull;
16-
import javax.annotation.Nullable;
17-
import java.util.Collection;
18-
import java.util.HashMap;
19-
import java.util.HashSet;
207
import java.util.List;
21-
import java.util.Optional;
22-
import java.util.Set;
23-
import java.util.function.Function;
24-
import java.util.function.Supplier;
25-
import java.util.stream.Collectors;
26-
import java.util.stream.Stream;
27-
28-
import static java.util.stream.Collectors.toList;
29-
import static java.util.stream.Collectors.toSet;
30-
import static java.util.stream.Stream.concat;
31-
32-
public interface Table<T extends Entity<T>> {
33-
<ID extends Entity.Id<T>> Stream<T> readTable(ReadTableParams<ID> params);
34-
35-
<ID extends Entity.Id<T>> Stream<ID> readTableIds(ReadTableParams<ID> params);
36-
37-
<V extends ViewId<T>, ID extends Entity.Id<T>> Stream<V> readTable(Class<V> viewClass, ReadTableParams<ID> params);
38-
39-
Class<T> getType();
40-
41-
@CheckForNull
42-
T find(Entity.Id<T> id);
43-
44-
<V extends View> V find(Class<V> viewType, Entity.Id<T> id);
45-
46-
<ID extends Entity.Id<T>> List<T> find(Range<ID> range);
47-
48-
<ID extends Entity.Id<T>> List<ID> findIds(Range<ID> range);
49-
50-
<ID extends Entity.Id<T>> List<ID> findIds(Set<ID> partialIds);
51-
52-
<V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType, Range<ID> range);
53-
54-
<V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType, Set<ID> ids);
55-
56-
List<T> findAll();
57-
58-
<V extends View> List<V> findAll(Class<V> viewType);
59-
60-
List<T> find(
61-
@Nullable String indexName,
62-
@Nullable FilterExpression<T> filter,
63-
@Nullable OrderExpression<T> orderBy,
64-
@Nullable Integer limit,
65-
@Nullable Long offset
66-
);
67-
68-
<ID extends Entity.Id<T>> List<ID> findIds(
69-
@Nullable String indexName,
70-
@Nullable FilterExpression<T> filter,
71-
@Nullable OrderExpression<T> orderBy,
72-
@Nullable Integer limit,
73-
@Nullable Long offset
74-
);
75-
76-
<V extends Table.View> List<V> find(
77-
Class<V> viewType,
78-
@Nullable String indexName,
79-
@Nullable FilterExpression<T> filter,
80-
@Nullable OrderExpression<T> orderBy,
81-
@Nullable Integer limit,
82-
@Nullable Long offset,
83-
boolean distinct
84-
);
85-
86-
<ID extends Entity.Id<T>> List<T> find(
87-
Set<ID> ids,
88-
@Nullable FilterExpression<T> filter,
89-
@Nullable OrderExpression<T> orderBy,
90-
@Nullable Integer limit
91-
);
92-
93-
<ID extends Entity.Id<T>> List<T> findUncached(
94-
Set<ID> ids,
95-
@Nullable FilterExpression<T> filter,
96-
@Nullable OrderExpression<T> orderBy,
97-
@Nullable Integer limit
98-
);
99-
100-
<V extends Table.View, ID extends Entity.Id<T>> List<V> find(
101-
Class<V> viewType,
102-
Set<ID> ids,
103-
@Nullable FilterExpression<T> filter,
104-
@Nullable OrderExpression<T> orderBy,
105-
@Nullable Integer limit
106-
);
107-
108-
<K> List<T> find(
109-
String indexName,
110-
Set<K> keys,
111-
@Nullable FilterExpression<T> filter,
112-
@Nullable OrderExpression<T> orderBy,
113-
@Nullable Integer limit
114-
);
115-
116-
<V extends Table.View, K> List<V> find(
117-
Class<V> viewType,
118-
String indexName,
119-
Set<K> keys,
120-
@Nullable FilterExpression<T> filter,
121-
@Nullable OrderExpression<T> orderBy,
122-
@Nullable Integer limit
123-
);
124-
125-
Stream<T> streamAll(int batchSize);
126-
127-
<V extends ViewId<T>> Stream<V> streamAll(Class<V> viewType, int batchSize);
128-
129-
<ID extends Entity.Id<T>> Stream<T> streamPartial(ID partial, int batchSize);
130-
131-
<ID extends Entity.Id<T>, V extends ViewId<T>> Stream<V> streamPartial(Class<V> viewType, ID partial, int batchSize);
132-
133-
<ID extends Entity.Id<T>> Stream<ID> streamAllIds(int batchSize);
134-
135-
<ID extends Entity.Id<T>> Stream<ID> streamPartialIds(ID partial, int batchSize);
136-
137-
long count(String indexName, FilterExpression<T> filter);
138-
139-
long countAll();
140-
141-
// Unsafe
142-
T insert(T t);
143-
144-
// Unsafe
145-
T save(T t);
146-
147-
// Unsafe: may delete only entity, but not its projections, if entity was not loaded
148-
void delete(Entity.Id<T> id);
149-
150-
// Unsafe
151-
void deleteAll();
152-
153-
default Stream<T> readTable() {
154-
return readTable(ReadTableParams.getDefault());
155-
}
156-
157-
default <ID extends Entity.Id<T>> Stream<ID> readTableIds() {
158-
return readTableIds(ReadTableParams.getDefault());
159-
}
160-
161-
default FirstLevelCache getFirstLevelCache() {
162-
return null;
163-
};
164-
165-
@NonNull
166-
default <X extends Exception> T find(Entity.Id<T> id, Supplier<? extends X> throwIfAbsent) throws X {
167-
T found = find(id);
168-
if (found != null) {
169-
return found;
170-
} else {
171-
throw throwIfAbsent.get();
172-
}
173-
}
174-
175-
default T findOrDefault(Entity.Id<T> id, Supplier<T> defaultSupplier) {
176-
T found = find(id);
177-
return found != null ? found : defaultSupplier.get();
178-
}
179-
180-
default <V extends View, X extends Exception> V find(Class<V> viewType, Entity.Id<T> id, Supplier<? extends X> throwIfAbsent) throws X {
181-
V found = find(viewType, id);
182-
if (found != null) {
183-
return found;
184-
} else {
185-
throw throwIfAbsent.get();
186-
}
187-
}
188-
189-
default T modifyIfPresent(Entity.Id<T> id, Function<T, T> modify) {
190-
return Optional.ofNullable(find(id))
191-
.map(modify)
192-
.map(this::save)
193-
.orElse(null);
194-
}
195-
196-
default T generateAndSaveNew(@NonNull Supplier<T> generator) {
197-
for (int i = 0; i < 7; i++) {
198-
T t = generator.get();
199-
if (find(t.getId()) == null) {
200-
return save(t);
201-
}
202-
}
203-
throw new IllegalStateException("Cannot generate unique entity id");
204-
}
205-
206-
default <X extends Throwable> T saveNewOrThrow(@NonNull T t, @NonNull Supplier<? extends X> alreadyExists) throws X {
207-
if (find(t.getId()) != null) {
208-
throw alreadyExists.get();
209-
}
210-
return save(t);
211-
}
212-
213-
default <X extends Throwable> T updateExistingOrThrow(@NonNull T t, @NonNull Supplier<? extends X> notFound) throws X {
214-
if (find(t.getId()) == null) {
215-
throw notFound.get();
216-
}
217-
return save(t);
218-
}
219-
220-
default T saveOrUpdate(@NonNull T t) {
221-
find(t.getId());
222-
return save(t);
223-
}
224-
225-
default T deleteIfExists(@NonNull Entity.Id<T> id) {
226-
T t = find(id);
227-
if (t != null) {
228-
delete(id);
229-
}
230-
return t;
231-
}
232-
233-
default <ID extends Entity.Id<T>> void deleteAll(Set<ID> ids) {
234-
find(ids);
235-
ids.forEach(this::delete);
236-
}
237-
238-
default <ID extends Entity.Id<T>> void deleteAll(Range<ID> range) {
239-
find(range).forEach(e -> delete(e.getId()));
240-
}
241-
242-
// Unsafe
243-
@SuppressWarnings("unchecked")
244-
default void insert(T first, T... rest) {
245-
insertAll(concat(Stream.of(first), Stream.of(rest)).collect(toList()));
246-
}
247-
248-
// Unsafe
249-
default void insertAll(Collection<? extends T> entities) {
250-
entities.forEach(this::insert);
251-
}
252-
253-
// Unsafe
254-
default <ID extends Entity.Id<T>> void delete(Set<ID> ids) {
255-
ids.forEach(this::delete);
256-
}
257-
258-
// Unsafe
259-
default <ID extends Entity.Id<T>> void delete(Range<ID> range) {
260-
findIds(range).forEach(this::delete);
261-
}
262-
263-
default ListResult<T> list(ListRequest<T> request) {
264-
List<T> nextPage = toQueryBuilder(request).find();
265-
return ListResult.forPage(request, postLoad(nextPage));
266-
}
267-
268-
default <V extends Table.View> ViewListResult<T, V> list(Class<V> viewType, ListRequest<T> request) {
269-
List<V> nextPage = toQueryBuilder(request).find(viewType);
270-
return ViewListResult.forPage(request, viewType, nextPage);
271-
}
272-
273-
default <ID extends Entity.Id<T>> List<T> find(Set<ID> ids) {
274-
if (ids.isEmpty()) {
275-
return List.of();
276-
}
277-
278-
var orderBy = EntityExpressions.defaultOrder(getType());
279-
var cache = getFirstLevelCache();
280-
var isPartialIdMode = ids.iterator().next().isPartial();
281-
282-
var foundInCache = ids.stream()
283-
.filter(cache::containsKey)
284-
.map(cache::peek)
285-
.flatMap(Optional::stream)
286-
.collect(Collectors.toMap(Entity::getId, Function.identity()));
287-
var remainingIds = Sets.difference(ids, foundInCache.keySet());
288-
var foundInDb = findUncached(remainingIds, null, orderBy, null);
289-
290-
var merged = new HashMap<Entity.Id<T>, T>();
291-
292-
// some entries found in db with partial id query may already be in cache (after update/delete),
293-
// so we must return actual entries from cache
294-
for (var entry : foundInDb) {
295-
var id = entry.getId();
296-
if (cache.containsKey(id)) {
297-
var cached = cache.peek(id);
298-
cached.ifPresent(t -> merged.put(id, t));
299-
// not present means marked as deleted in cache
300-
} else {
301-
merged.put(id, this.postLoad(entry));
302-
}
303-
}
304-
305-
// add entries found in cache and not fetched from db
306-
for (var pair : foundInCache.entrySet()) {
307-
var id = pair.getKey();
308-
var entry = pair.getValue();
309-
merged.put(id, entry);
310-
}
311-
312-
if (!isPartialIdMode) {
313-
Set<Entity.Id<T>> foundInDbIds = foundInDb.stream().map(Entity::getId).collect(toSet());
314-
Set<Entity.Id<T>> foundInCacheIds = new HashSet<>(foundInCache.keySet());
315-
Sets.difference(Sets.difference(ids, foundInDbIds), foundInCacheIds).forEach(cache::putEmpty);
316-
}
317-
318-
return merged.values().stream().sorted(EntityIdSchema.SORT_ENTITY_BY_ID).collect(Collectors.toList());
319-
}
3208

9+
public interface Table<T extends Entity<T>> extends TableReader<T>, WriteTable<T> {
32110
default void bulkUpsert(List<T> input, BulkParams params) {
32211
throw new UnsupportedOperationException();
32312
}
32413

325-
default TableQueryBuilder<T> toQueryBuilder(ListRequest<T> request) {
326-
return query()
327-
.index(request.getIndex())
328-
.filter(request.getFilter())
329-
.orderBy(request.getOrderBy())
330-
.offset(request.getOffset())
331-
.limit(request.getPageSize() + 1);
332-
}
333-
334-
default List<T> postLoad(List<T> list) {
335-
return list.stream().map(this::postLoad).collect(Collectors.toList());
336-
}
337-
338-
default T postLoad(T e) {
339-
return e.postLoad();
340-
}
341-
342-
default long count(FilterExpression<T> filter) {
343-
return count(null, filter);
344-
}
345-
346-
default TableQueryBuilder<T> query() {
347-
return new TableQueryBuilder<>(this);
348-
}
349-
350-
@Deprecated
351-
void update(Entity.Id<T> id, Changeset changeset);
352-
35314
interface View {
35415
}
35516

@@ -361,7 +22,7 @@ interface ViewId<T extends Entity<T>> extends View {
36122
* Base interface for ID-aware table views that are Java {@link java.lang.Record records}.
36223
* <p>Forwards {@link ViewId#getId() ViewId's getId() method} to the record's {@code id()} accessor.
36324
*
364-
* @param <E> entity type
25+
* @param <T> entity type
36526
*/
36627
interface RecordViewId<T extends Entity<T>> extends ViewId<T> {
36728
Entity.Id<T> id();

0 commit comments

Comments
 (0)