Skip to content

Commit 25af931

Browse files
authored
Merge pull request #15 from ydb-platform/bug-fixes
Комментарии к коду
2 parents 329fc6a + caf8e84 commit 25af931

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+392
-66
lines changed

dev-1/lesson-2.1/java/src/main/java/tech/ydb/app/Application.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@
77
import tech.ydb.query.tools.SessionRetryContext;
88
import tech.ydb.table.result.ResultSetReader;
99

10-
/**
10+
/*
1111
* @author Kirill Kurdyukov
1212
*/
13-
public class Application {
13+
public class Application {
14+
// Строка подключения к локальной базе данных YDB
15+
// Формат: grpc://<хост>:<порт>/<путь к базе данных>
1416
private static final String CONNECTION_STRING = "grpc://localhost:2136/local";
1517

1618
public static void main(String[] args) {
19+
// Создаем драйвер для подключения к YDB через gRPC
1720
try (GrpcTransport grpcTransport = GrpcTransport.forConnectionString(CONNECTION_STRING).build()) {
21+
// Создаем клиент для выполнения SQL-запросов
1822
try (QueryClient queryClient = QueryClient.newClient(grpcTransport).build()) {
23+
// Создаем контекст для автоматических повторных попыток выполнения запросов
1924
SessionRetryContext retryCtx = SessionRetryContext.create(queryClient).build();
2025

2126
System.out.println("Database is available! Result `SELECT 1;` command: " +
@@ -24,22 +29,33 @@ public static void main(String[] args) {
2429
}
2530
}
2631

32+
/*
33+
* Класс для работы с YDB, инкапсулирующий логику выполнения запросов
34+
*/
2735
public static class YdbRepository {
2836
private final SessionRetryContext retryCtx;
2937

3038
public YdbRepository(SessionRetryContext retryCtx) {
3139
this.retryCtx = retryCtx;
3240
}
3341

42+
/*
43+
* Выполняет простой SQL-запрос SELECT 1 для проверки работоспособности базы данных
44+
* @return результат запроса (всегда 1)
45+
*/
3446
public int SelectOne() {
47+
// Выполняем запрос с автоматическими повторными попытками при ошибках
3548
QueryReader resultSet = retryCtx.supplyResult(session ->
3649
QueryReader.readFrom(session.createQuery("SELECT 1;", TxMode.NONE))
3750
).join().getValue();
3851

52+
// Получаем первый набор результатов
3953
ResultSetReader resultSetReader = resultSet.getResultSet(0);
4054

55+
// Переходим к первой строке результата
4156
resultSetReader.next();
4257

58+
// Возвращаем значение из первой строки и первой колонки (нумерация с 0)
4359
return resultSetReader.getColumn(0).getInt32();
4460
}
4561
}

dev-1/lesson-3.1/java/src/main/java/tech/ydb/app/Application.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import tech.ydb.query.QueryClient;
55
import tech.ydb.query.tools.SessionRetryContext;
66

7-
/**
7+
/*
88
* @author Kirill Kurdyukov
99
*/
1010
public class Application {

dev-1/lesson-3.1/java/src/main/java/tech/ydb/app/Issue.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
import java.time.Instant;
44
import java.util.UUID;
55

6-
/**
6+
/*
7+
* Модель данных для представления тикета в примере
78
* @author Kirill Kurdyukov
89
*/
9-
public record Issue(long id, String title, Instant now) {
10+
public record Issue(
11+
long id, // Уникальный идентификатор тикета
12+
String title, // Название тикета
13+
Instant now // Время создания тикета
14+
) {
1015
}

dev-1/lesson-3.1/java/src/main/java/tech/ydb/app/IssueYdbRepository.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,36 @@
1212
import tech.ydb.table.query.Params;
1313
import tech.ydb.table.values.PrimitiveValue;
1414

15-
/**
15+
/*
16+
* Репозиторий для работы с тикетами в базе данных YDB
17+
* Реализует операции добавления и чтения тикетов
1618
* @author Kirill Kurdyukov
1719
*/
1820
public class IssueYdbRepository {
21+
// Контекст для автоматических повторных попыток выполнения запросов
22+
// Принимается извне через конструктор для:
23+
// 1. Следования принципу Dependency Injection - зависимости класса передаются ему извне
24+
// 2. Улучшения тестируемости - можно передать mock-объект для тестов
25+
// 3. Централизованного управления конфигурацией ретраев
26+
// 4. Возможности переиспользования одного контекста для разных репозиториев
1927
private final SessionRetryContext retryCtx;
2028

2129
public IssueYdbRepository(SessionRetryContext retryCtx) {
2230
this.retryCtx = retryCtx;
2331
}
2432

33+
/*
34+
* Добавляет новый тикет в базу данных
35+
* @param title название тикета
36+
* @return созданный тикет с сгенерированным ID и временем создания
37+
*/
2538
public Issue addIssue(String title) {
39+
// Генерируем случайный ID для тикета
2640
var id = ThreadLocalRandom.current().nextLong();
2741
var now = Instant.now();
2842

43+
// Выполняем UPSERT запрос для добавления тикета
44+
// Изменять данные можно только в режиме транзакции SERIALIZABLE_RW, поэтому используем его
2945
retryCtx.supplyResult(
3046
session -> session.createQuery(
3147
"""
@@ -47,8 +63,16 @@ UPSERT INTO issues (id, title, created_at)
4763
return new Issue(id, title, now);
4864
}
4965

66+
/*
67+
* Получает все тикеты из базы данных
68+
* @return список всех тикетов
69+
*/
5070
public List<Issue> findAll() {
5171
var titles = new ArrayList<Issue>();
72+
// Выполняем SELECT запрос в режиме SNAPSHOT_RO для чтения данных
73+
// Этот режим сообщает серверу, что это транзакция только для чтения.
74+
// Это позволяет снизить накладные расходы на подготовку к изменениям и просто читать данные из
75+
// одного снимка базы данных.
5276
var resultSet = retryCtx.supplyResult(
5377
session -> QueryReader.readFrom(
5478
session.createQuery("SELECT id, title, created_at FROM issues;", TxMode.SNAPSHOT_RO)
@@ -57,6 +81,7 @@ public List<Issue> findAll() {
5781

5882
var resultSetReader = resultSet.getResultSet(0);
5983

84+
// Читаем все строки результата
6085
while (resultSetReader.next()) {
6186
titles.add(new Issue(
6287
resultSetReader.getColumn(0).getInt64(),

dev-1/lesson-3.1/java/src/main/java/tech/ydb/app/SchemaYdbRepository.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,29 @@
33
import tech.ydb.common.transaction.TxMode;
44
import tech.ydb.query.tools.SessionRetryContext;
55

6-
/**
6+
/*
7+
* Репозиторий для управления схемой базы данных YDB
8+
* Отвечает за создание и удаление таблиц
79
* @author Kirill Kurdyukov
810
*/
911
public class SchemaYdbRepository {
1012

13+
// Контекст для автоматических повторных попыток выполнения запросов
1114
private final SessionRetryContext retryCtx;
1215

1316
public SchemaYdbRepository(SessionRetryContext retryCtx) {
1417
this.retryCtx = retryCtx;
1518
}
1619

20+
/*
21+
* Создает таблицу issues в базе данных
22+
* Таблица содержит поля:
23+
* - id: уникальный идентификатор тикета
24+
* - title: название тикета
25+
* - created_at: время создания тикета
26+
*
27+
* Все поля являются обязательными.
28+
*/
1729
public void createSchema() {
1830
retryCtx.supplyResult(
1931
session -> session.createQuery(
@@ -29,6 +41,10 @@ PRIMARY KEY (id)
2941
).join().getStatus().expectSuccess("Can't create table issues");
3042
}
3143

44+
/*
45+
* Удаляет таблицу issues из базы данных
46+
* Используется для очистки схемы перед созданием новой
47+
*/
3248
public void dropSchema() {
3349
retryCtx.supplyResult(
3450
session -> session.createQuery(

dev-1/lesson-4.1/java/src/main/java/tech/ydb/app/Application.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import tech.ydb.query.QueryClient;
55
import tech.ydb.query.tools.SessionRetryContext;
66

7-
/**
7+
/*
8+
* Пример работы с транзакциями в YDB, урок - 4.1 Распределенные транзакции
89
* @author Kirill Kurdyukov
910
*/
1011
public class Application {
1112

13+
// Строка подключения к локальной базе данных YDB
1214
private static final String CONNECTION_STRING = "grpc://localhost:2136/local";
1315

1416
public static void main(String[] args) {
@@ -22,6 +24,7 @@ public static void main(String[] args) {
2224
schemaYdbRepository.dropSchema();
2325
schemaYdbRepository.createSchema();
2426

27+
// Создаем тикеты с авторами
2528
issueYdbRepository.addIssue("Ticket 1", "Author 1");
2629
issueYdbRepository.addIssue("Ticket 2", "Author 2");
2730
issueYdbRepository.addIssue("Ticket 3", "Author 3");
@@ -36,6 +39,7 @@ public static void main(String[] args) {
3639
var first = allIssues.get(0);
3740
var second = allIssues.get(1);
3841

42+
// Демонстрация неинтерактивной транзакции - все запросы выполняются за один запрос к YDB
3943
System.out.println("Linked tickets by non-interactive transactions id1 = " + first.id() + ", id2 = " + second.id());
4044
var result1 = issueYdbRepository.linkTicketsNoInteractive(first.id(), second.id());
4145
System.out.println("Result operation:");
@@ -44,6 +48,7 @@ public static void main(String[] args) {
4448
}
4549

4650
var third = allIssues.get(2);
51+
// Демонстрация интерактивной транзакции - между запросами к YDB есть логика на стороне приложения
4752
System.out.println("Linked tickets by interactive transactions id2 = " + second.id() + ", id3 = " + third.id());
4853
var result2 = issueYdbRepository.linkTicketsInteractive(second.id(), third.id());
4954
System.out.println("Result operation:");

dev-1/lesson-4.1/java/src/main/java/tech/ydb/app/Issue.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@
33
import java.time.Instant;
44
import java.util.UUID;
55

6-
/**
6+
/*
7+
* Модель данных для представления тикета в системе
78
* @author Kirill Kurdyukov
89
*/
9-
public record Issue(long id, String title, Instant now, String author, long linkCounts) {
10+
public record Issue(
11+
long id, // Уникальный идентификатор тикета
12+
String title, // Название тикета
13+
Instant now, // Время создания тикета
14+
String author, // Автор тикета
15+
long linkCounts // Количество связей с другими тикетами
16+
) {
1017
}

dev-1/lesson-4.1/java/src/main/java/tech/ydb/app/IssueLinkCount.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
import java.util.UUID;
44

5-
/**
5+
/*
6+
* Модель данных для представления результата операции связывания тикетов
67
* @author Kirill Kurdyukov
78
*/
8-
public record IssueLinkCount(long id, long linkCount) {
9+
public record IssueLinkCount(
10+
long id, // Идентификатор тикета
11+
long linkCount // Количество связей тикета после операции
12+
) {
913
}

dev-1/lesson-4.1/java/src/main/java/tech/ydb/app/IssueYdbRepository.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,41 @@
1414
import tech.ydb.table.query.Params;
1515
import tech.ydb.table.values.PrimitiveValue;
1616

17-
/**
17+
/*
18+
* Репозиторий для работы с тикетами в базе данных YDB
19+
* Реализует операции добавления, чтения и связывания тикетов
1820
* @author Kirill Kurdyukov
1921
*/
2022
public class IssueYdbRepository {
23+
// Контекст для автоматических повторных попыток выполнения запросов
2124
private final SessionRetryContext retryCtx;
2225

2326
public IssueYdbRepository(SessionRetryContext retryCtx) {
2427
this.retryCtx = retryCtx;
2528
}
2629

30+
/*
31+
* Связывает два тикета в рамках неинтерактивной транзакции
32+
* Все операции (обновление счетчиков, добавление связей, чтение результатов)
33+
* выполняются за один запрос к YDB.
34+
*/
2735
public List<IssueLinkCount> linkTicketsNoInteractive(long idT1, long idT2) {
2836
var valueReader = retryCtx.supplyResult(
2937
session -> QueryReader.readFrom(session.createQuery(
3038
"""
3139
DECLARE $t1 AS Int64;
3240
DECLARE $t2 AS Int64;
33-
41+
42+
-- Обновляем счетчики связей
3443
UPDATE issues
3544
SET link_count = COALESCE(link_count, 0) + 1
3645
WHERE id IN ($t1, $t2);
37-
46+
47+
-- Добавляем записи о связях между тикетами
3848
INSERT INTO links (source, destination)
3949
VALUES ($t1, $t2), ($t2, $t1);
4050
51+
-- Читаем обновленные данные
4152
SELECT id, link_count FROM issues
4253
WHERE id IN ($t1, $t2)
4354
""",
@@ -49,11 +60,23 @@ WHERE id IN ($t1, $t2)
4960
return getLinkTicketPairs(valueReader);
5061
}
5162

63+
/*
64+
* Связывает два тикета в рамках интерактивной транзакции
65+
* Операции выполняются последовательными запросами к YDB:
66+
* 1. Обновление счетчиков связей
67+
* 2. Добавление записей о связях
68+
* 3. Чтение обновленных данных
69+
*
70+
* Между запросами к YDB может быть выполнена логика на стороне приложения,
71+
* для определения стоит ли продолжать транзакцию и какой запрос выполнить следующим.
72+
*/
5273
public List<IssueLinkCount> linkTicketsInteractive(long idT1, long idT2) {
5374
return retryCtx.supplyResult(
5475
session -> {
76+
// Транзакция будет изменять данные, поэтому используем режим SERIALIZABLE_RW
5577
var tx = session.createNewTransaction(TxMode.SERIALIZABLE_RW);
5678

79+
// Обновляем счетчики связей
5780
tx.createQuery("""
5881
DECLARE $t1 AS Int64;
5982
DECLARE $t2 AS Int64;
@@ -65,6 +88,7 @@ public List<IssueLinkCount> linkTicketsInteractive(long idT1, long idT2) {
6588
Params.of("$t1", PrimitiveValue.newInt64(idT1), "$t2", PrimitiveValue.newInt64(idT2))
6689
).execute().join().getStatus().expectSuccess();
6790

91+
// Добавляем записи о связях между тикетами
6892
tx.createQuery("""
6993
DECLARE $t1 AS Int64;
7094
DECLARE $t2 AS Int64;
@@ -75,6 +99,7 @@ INSERT INTO links (source, destination)
7599
Params.of("$t1", PrimitiveValue.newInt64(idT1), "$t2", PrimitiveValue.newInt64(idT2))
76100
).execute().join().getStatus().expectSuccess();
77101

102+
// Читаем обновленные данные и фиксируем транзакцию
78103
var valueReader = QueryReader.readFrom(
79104
tx.createQueryWithCommit("""
80105
DECLARE $t1 AS Int64;
@@ -93,6 +118,11 @@ WHERE id IN ($t1, $t2)
93118
).join().getValue();
94119
}
95120

121+
/*
122+
* Добавляет новый тикет в базу данных
123+
* @param title название тикета
124+
* @param author автор тикета
125+
*/
96126
public void addIssue(String title, String author) {
97127
var id = ThreadLocalRandom.current().nextLong();
98128
var now = Instant.now();
@@ -118,6 +148,10 @@ UPSERT INTO issues (id, title, created_at, author)
118148
).join().getStatus().expectSuccess("Failed upsert title");
119149
}
120150

151+
/*
152+
* Получает все тикеты из базы данных
153+
* @return список всех тикетов
154+
*/
121155
public List<Issue> findAll() {
122156
var titles = new ArrayList<Issue>();
123157
var resultSet = retryCtx.supplyResult(
@@ -141,6 +175,9 @@ public List<Issue> findAll() {
141175
return titles;
142176
}
143177

178+
/*
179+
* Преобразует результаты запроса в список объектов IssueLinkCount
180+
*/
144181
private static List<IssueLinkCount> getLinkTicketPairs(QueryReader valueReader) {
145182
var linkTicketPairs = new ArrayList<IssueLinkCount>();
146183
var resultSet = valueReader.getResultSet(0);

0 commit comments

Comments
 (0)