<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ydb/library/cpp, branch oidc-1.2.8.12-dev</title>
<subtitle>Mirror of YDB github repos</subtitle>
<id>https://code.mastervirt.ru/ydb/atom?h=oidc-1.2.8.12-dev</id>
<link rel='self' href='https://code.mastervirt.ru/ydb/atom?h=oidc-1.2.8.12-dev'/>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/'/>
<updated>2026-04-29T10:36:58Z</updated>
<entry>
<title>YT_DECLARE_SPIN_LOCK whack-a-mole 2: electric boogaloo, Theatrical Cut</title>
<updated>2026-04-29T10:36:58Z</updated>
<author>
<name>dann239</name>
<email>dann239@yandex-team.com</email>
</author>
<published>2026-04-29T10:05:49Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=ecec96bec80b2bb134672a52de4d67eca8cd480a'/>
<id>urn:sha1:ecec96bec80b2bb134672a52de4d67eca8cd480a</id>
<content type='text'>
commit_hash:946123c814d23e070516ef5f7d339cf6025547b6
</content>
</entry>
<entry>
<title>Introduce YT_SPIN_LOCK_INPLACE_TYPE</title>
<updated>2026-04-28T07:12:31Z</updated>
<author>
<name>dann239</name>
<email>dann239@yandex-team.com</email>
</author>
<published>2026-04-28T06:44:22Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=d9f4779c7c85a26654593380e3dac43e0b7fc7af'/>
<id>urn:sha1:d9f4779c7c85a26654593380e3dac43e0b7fc7af</id>
<content type='text'>
commit_hash:a21fb954574aa503699e20da93fad863363d4adf
</content>
</entry>
<entry>
<title>New version of the tld SKIP_CHECK SKIP_REVIEW</title>
<updated>2026-04-28T02:01:04Z</updated>
<author>
<name>robot-ratatosk</name>
<email>robot-ratatosk@yandex-team.com</email>
</author>
<published>2026-04-28T01:30:02Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=b43d16290e56ff33972f637a0b7410f966988871'/>
<id>urn:sha1:b43d16290e56ff33972f637a0b7410f966988871</id>
<content type='text'>
commit_hash:a68c6e6d84fdd6f57df4488325de919b99c21d79
</content>
</entry>
<entry>
<title>Use implicit bool conversion for null check in origin_attributes.cpp</title>
<updated>2026-04-27T13:12:31Z</updated>
<author>
<name>babenko</name>
<email>babenko@yandex-team.com</email>
</author>
<published>2026-04-27T12:52:34Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=b36733c26de293fbc1562234f05ce2b41f7251a2'/>
<id>urn:sha1:b36733c26de293fbc1562234f05ce2b41f7251a2</id>
<content type='text'>
commit_hash:cc1f5b9ecc05f6b098f1645ba338fc644c0bb53f
</content>
</entry>
<entry>
<title>Add Abseil-compatible support hashers</title>
<updated>2026-04-27T12:16:34Z</updated>
<author>
<name>babenko</name>
<email>babenko@yandex-team.com</email>
</author>
<published>2026-04-27T11:10:55Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=ac1b929087542a400ab0f55f7263c95544baa0b8'/>
<id>urn:sha1:ac1b929087542a400ab0f55f7263c95544baa0b8</id>
<content type='text'>
commit_hash:2d2808f61599fcfea314ad660585e984d50ffbb3
</content>
</entry>
<entry>
<title>New version of the tld SKIP_CHECK SKIP_REVIEW</title>
<updated>2026-04-24T23:22:15Z</updated>
<author>
<name>robot-ratatosk</name>
<email>robot-ratatosk@yandex-team.com</email>
</author>
<published>2026-04-24T22:59:06Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=cbd77b02b3fff2de323862c8e822d7d53f6163a9'/>
<id>urn:sha1:cbd77b02b3fff2de323862c8e822d7d53f6163a9</id>
<content type='text'>
commit_hash:5e6c329f3fd9e1aa58d910dba02af63568e95294
</content>
</entry>
<entry>
<title>gRPC inactivity watchdog only for negotiated protocol v1+</title>
<updated>2026-04-24T09:55:23Z</updated>
<author>
<name>andybg</name>
<email>andybg@yandex-team.com</email>
</author>
<published>2026-04-24T09:15:16Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=cd465393cf4f26e84ccc5554532cfbde88500f9a'/>
<id>urn:sha1:cd465393cf4f26e84ccc5554532cfbde88500f9a</id>
<content type='text'>
Unified Agent: новый протокол стриминга и изменения в клиенте

Документ опирается на `library/cpp/unified_agent_client/proto/unified_agent.proto` и реализацию `TClientSession` в `client_impl.cpp`.

---

## 1. Новый протокол

**Legacy** — сессия без согласования версии: в ответе `Initialized` поле `protocol_version` отсутствует или равно **0**. Поведение соответствует старому контракту до появления опциональных полей согласования.

**Версионированный режим (v1 и выше)** — клиент объявляет максимально поддерживаемую версию (`accept_protocol_version`), агент возвращает **согласованную** версию `protocol_version` и опционально **opaque**-токен привязки сессии. Дальнейшие реконнекты с тем же `session_id` требуют передачи **доказательства** привязки (`session_binding_proof`), чтобы сервер мог отличить легитимное продолжение от подмены.

Семантика потока данных не меняется: после `Initialized` идут `DataBatch` / `Ack`, ретраи по `seq_no` и дедупликация на стороне агента при совпадении `session_id` и повторной отправке записей.

---

### 1.2. Новые поля

**Запрос `Request.Initialize`**

| Поле | Тип | Назначение |
|------|-----|------------|
| `accept_protocol_version` | `optional uint32` | Верхняя граница версии, которую клиент готов использовать (стиль HTTP Accept). **Не задано или 0** — клиент не предлагает новый протокол (legacy-only). |
| `session_binding_proof` | `bytes` | Доказательство привязки при реконнекте; используется, когда согласована версия **&gt; 0** и у клиента есть токен от предыдущего `Initialized`. |

Поля `session_id`, `meta`, `shared_secret_key` — как раньше; `session_id` при реконнекте передаётся для дедупликации.

**Ответ `Response.Initialized`**

| Поле | Тип | Назначение |
|------|-----|------------|
| `protocol_version` | `optional uint32` | Согласованная версия: **min**(accept клиента, максимум сервера). **Не задано или 0** — сессия считается **legacy**. |
| `session_binding_token` | `bytes` | Непрозрачный токен: клиент обязан вернуть его в следующем `Initialize` как `session_binding_proof` при переподключении (для версий протокола **≥ 1**). |

Остальное без изменений: `session_id`, `last_seq_no`.

---

### 1.3. Процесс и логика выбора версии

1. Клиент задаёт **`MaxAcceptProtocolVersion`** (в коде: `SetMaxAcceptProtocolVersion`). Значение **0** означает: поле `accept_protocol_version` в `Initialize` **не отправляется** — только legacy.
2. Если `MaxAcceptProtocolVersion &gt; 0`, в первом (и последующих) сообщении `Initialize` выставляется `accept_protocol_version = MaxAcceptProtocolVersion`.
3. Агент вычисляет согласованную версию как **min**(`accept_protocol_version`, собственный потолок поддерживаемых версий) и возвращает её в `Initialized.protocol_version`. Если клиент не прислал accept (legacy-only) или сервер отвечает **0** / не задаёт поле — на клиенте фиксируется **legacy** (`NegotiatedProtocol` сбрасывается).
4. При успешном `Initialized` с **`protocol_version &gt; 0`** клиент сохраняет число версии в `NegotiatedProtocol` и копирует `session_binding_token` во внутреннее состояние для следующих коннектов.

#### Диаграмма обмена (Mermaid sequence)

Первое подключение с согласованием версии и привязкой:

```mermaid
sequenceDiagram
    participant C as Клиент (TClientSession)
    participant G as gRPC stream
    participant A as Unified Agent

    C-&gt;&gt;G: открыть Session(stream Request / stream Response)
    C-&gt;&gt;A: Request.initialize&lt;br/&gt;accept_protocol_version = N (если N&gt;0)&lt;br/&gt;session_id (опц.)&lt;br/&gt;meta, shared_secret_key, …

    Note over A: min(N, server_max) → negotiated

    A-&gt;&gt;C: Response.initialized&lt;br/&gt;session_id&lt;br/&gt;last_seq_no&lt;br/&gt;protocol_version = negotiated&lt;br/&gt;session_binding_token (opaque)

    C-&gt;&gt;C: сохранить NegotiatedProtocol,&lt;br/&gt;SessionBindingToken, SessionId

    loop Данные
        C-&gt;&gt;A: Request.data_batch (seq_no, payload, …)
        A-&gt;&gt;C: Response.ack (seq_no)
    end

    Note over C,A: обрыв стрима → реконнект
```

Реконнект при согласованной версии **&gt; 0**:

```mermaid
sequenceDiagram
    participant C as Клиент
    participant A as Unified Agent

    C-&gt;&gt;A: Request.initialize&lt;br/&gt;session_id = сохранённый&lt;br/&gt;accept_protocol_version = N&lt;br/&gt;session_binding_proof = прежний token&lt;br/&gt;…

    A-&gt;&gt;C: Response.initialized&lt;br/&gt;session_id, last_seq_no,&lt;br/&gt;protocol_version, session_binding_token (может обновиться)

    C-&gt;&gt;A: Request.data_batch …
```

---

### 1.4. Восстановление сессии и обмен ключами

- **Идентификатор сессии:** `session_id` приходит от сервера в `Initialized` и дальше передаётся в `Initialize` при реконнекте — основа для дедупликации и продолжения с теми же `seq_no`.
- **Shared secret:** по-прежнему `shared_secret_key` в `Initialize` (если задан в параметрах клиента) — отдельный канал авторизации/проверки, не смешивается с биндингом стрима.
- **Привязка сессии (protocol v1+):** после первого успешного `Initialized` с `protocol_version &gt; 0` клиент хранит `session_binding_token`. При следующем `PrepareInitializeRequest`, если есть `NegotiatedProtocol &gt; 0` и непустой токен, в запрос кладётся `session_binding_proof` (содержимое токена). Так сервер связывает новый gRPC-стрим с прежней логической сессией.
- **Конфликт сессии:** при завершении gRPC-вызова с кодом **`ALREADY_EXISTS`** клиент **сбрасывает** `SessionId`, `NegotiatedProtocol` и `SessionBindingToken`, чтобы следующий коннект не повторял конфликтующий идентификатор и не слал устаревшее proof (см. `OnGrpcCallFinished` в `client_impl.cpp`).

---

### 1.5. Совместимость клиентов и серверов

| Клиент | Сервер | Результат |
|--------|--------|-----------|
| `MaxAcceptProtocolVersion = 0` | любой | Поле `accept_protocol_version` не отправляется; ожидается legacy-ответ (`protocol_version` 0 / отсутствует). Биндинг по токену не используется. |
| `MaxAcceptProtocolVersion &gt; 0` | только legacy | Обычно `protocol_version` в ответе 0 или отсутствует — клиент остаётся в legacy для этой сессии. |
| `MaxAcceptProtocolVersion &gt; 0` | поддерживает v1+ | Согласуется конкретное число (например 1); включаются `session_binding_token` / `session_binding_proof` на реконнектах. |
| Новый клиент | старый агент | Безопасный откат: нет обязательных новых полей в wire-format для legacy; сервер игнорирует неизвестные optional-поля (proto3). |

Важно: поведение «только новый протокол» для отдельных механизмов (например принудительная отмена стрима по неактивности) в клиенте завязано на **фактически согласованную** версию **`NegotiatedProtocol &gt; 0`**, а не только на настройку `MaxAcceptProtocolVersion`.

---

## 2. Изменения в клиенте — исправления и защита от регрессий

Ниже — логика, связанная с новым протоколом и устойчивостью сессий (файл `client_impl.cpp`, заголовки `client.h` / `client_impl.h`).

1. **Согласование версии и биндинг** — `PrepareInitializeRequest` выставляет `accept_protocol_version` только при `MaxAcceptProtocolVersion &gt; 0`; при наличии согласованной версии и токена добавляет `session_binding_proof`. `OnGrpcCallInitialized` выставляет `NegotiatedProtocol` и `SessionBindingToken` только если `protocol_version` задан и **&gt; 0**, иначе очищает их (строгий legacy).

2. **Конфликт `ALREADY_EXISTS`** — при таком статусе завершения стрима сбрасываются `SessionId`, `NegotiatedProtocol` и `SessionBindingToken`, чтобы не зациклиться на неверной паре (session_id, proof) и не провоцировать повторные конфликты на стороне агента.

3. **Watchdog неактивности gRPC (`GrpcCallInactivityTimeout`)** — принудительное закрытие активного вызова (`BeginClose(true)`) и счётчик `GrpcCallsClosedByInactivity` выполняются **только** при `NegotiatedProtocol.Defined() &amp;&amp; *NegotiatedProtocol &gt; 0`. Для legacy и до первого успешного `Initialized` с ненулевой версией отмена по этому таймеру **не** выполняется; таймер перепланируется как раньше. Это устраняет нежелательное принудительное реконнект-поведение на транспортах, где ранее допускалось «молчание» без отмены (см. план по этому пути).

4. **Пост-fork дочерний процесс** — сброс `SessionId`, `NegotiatedProtocol`, `SessionBindingToken` вместе с очередями, чтобы дочерний процесс не унаследовал привязку чужой сессии.

Документация в публичном API: комментарий к `SetGrpcCallInactivityTimeout` в `client.h` описывает ограничение по согласованной версии протокола.

---

*При необходимости уточнения формулы `min(accept, server_max)` на стороне агента смотрите реализацию сервера в репозитории `logbroker/unified_agent` (обработка `Initialize` в gRPC-сессии).*
commit_hash:9d5ef1cdc0faf793b4f56bfd2bafa362d7995ac5
</content>
</entry>
<entry>
<title>YT-27951: Use truncated string view to limit query length in traces</title>
<updated>2026-04-23T08:16:41Z</updated>
<author>
<name>osidorkin</name>
<email>osidorkin@yandex-team.com</email>
</author>
<published>2026-04-23T07:46:30Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=3eafe425787c0c3d6b9388faca597c1ab1a978b0'/>
<id>urn:sha1:3eafe425787c0c3d6b9388faca597c1ab1a978b0</id>
<content type='text'>
commit_hash:84610a30b17de408952f5c68dbc32b18b753b247
</content>
</entry>
<entry>
<title>Fix grammar</title>
<updated>2026-04-22T18:38:46Z</updated>
<author>
<name>akhropov</name>
<email>akhropov@yandex-team.com</email>
</author>
<published>2026-04-22T18:17:18Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=18294f5ca11a14dd88b31c7f79cdb66e1ebe7a2f'/>
<id>urn:sha1:18294f5ca11a14dd88b31c7f79cdb66e1ebe7a2f</id>
<content type='text'>
commit_hash:9a5da6e51df2e59de0c2558361b5026e3651bfaa
</content>
</entry>
<entry>
<title>Poison memory in allocation holders</title>
<updated>2026-04-22T11:44:50Z</updated>
<author>
<name>sabdenovch</name>
<email>sabdenovch@yandex-team.com</email>
</author>
<published>2026-04-22T10:53:16Z</published>
<link rel='alternate' type='text/html' href='https://code.mastervirt.ru/ydb/commit/?id=9143706b1e7b69c6d88e825c2822060a5b4b518b'/>
<id>urn:sha1:9143706b1e7b69c6d88e825c2822060a5b4b518b</id>
<content type='text'>
commit_hash:c574e7092eae2a9ed715448139ca905f0af5562c
</content>
</entry>
</feed>
