Глава 6: Передача данных
6.1 Двунаправленный поток данных
DTP поддерживает передачу данных в обоих направлениях без взаимного влияния:
| Направление | Название | Описание |
|---|---|---|
| Terminal → Fay | Сбор данных | Постоянное сохранение данных, произведённых терминалом, в Personal Data Heap |
| Fay → Terminal | Инъекция данных | Минимизированный набор данных, отфильтрованный и оценённый iFay |
Оба направления используют одинаковый формат LogicalFrame и процесс обработки, но поддерживают независимые пространства порядковых номеров и состояния возобновления.
6.2 Поток сбора данных (Terminal → Fay)
Полный поток сбора данных проходит следующие этапы:
Terminal Application
│
▼ Отправка данных
DTP_Slave Engine
│ 1. Прикрепление контекстных метаданных
│ 2. Построение LogicalFrame (Header + Payload)
│ 3. Шифрование Payload
│ 4. Сериализация LogicalFrame
│
▼ send(binary_data)
Transport_Adapter
│
▼ onReceive(binary_data)
DTP_Master Engine
│ 1. Десериализация LogicalFrame
│ 2. Валидация Agreement_ID
│ 3. Дешифрование Payload
│ 4. Валидация DAG-зависимостей
│ 5. Обновление порядкового номера + отправка подтверждения
│
▼ Сохранение
Personal Data Heap
6.3 Поток инъекции данных (Fay → Terminal)
Полный поток инъекции данных проходит следующие этапы:
Personal Data Heap
│
▼ Запрос и фильтрация данных
DTP_Master Engine
│ 1. Построение Fragment + контекстные метаданные
│ 2. Построение LogicalFrame
│ 3. Шифрование Payload
│ 4. Сериализация LogicalFrame
│
▼ send(binary_data)
Transport_Adapter
│
▼ onReceive(binary_data)
DTP_Slave Engine
│ 1. Десериализация LogicalFrame
│ 2. Валидация Agreement_ID
│ 3. Дешифрование Payload
│ 4. Обновление порядкового номера + отправка подтверждения
│
▼ Доставка данных
Terminal Application
6.4 Сжатая передача Agreement_ID
Для снижения накладных расходов на передачу DTP поддерживает сжатую передачу Agreement_ID:
- Когда последовательные Fragment принадлежат одному соглашению, только первый Fragment в пакете несёт полный Agreement_ID в заголовке
- У последующих Fragment поле agreementId установлено в null, что означает наследование предыдущего
Правила обработки получателем:
- Получен Fragment с Agreement_ID → Обновить Agreement_ID текущего контекста
- Получен Fragment без Agreement_ID → Ассоциировать с последним объявленным Agreement_ID в текущем контексте
- Получен Fragment, ссылающийся на неизвестный Agreement_ID → Отбросить и отправить уведомление об ошибке
Пример:
Fragment 1: agreementId = "abc-123" ← Полный ID
Fragment 2: agreementId = null ← Наследует "abc-123"
Fragment 3: agreementId = null ← Наследует "abc-123"
Fragment 4: agreementId = "def-456" ← Новое соглашение, полный ID
Fragment 5: agreementId = null ← Наследует "def-456"
6.5 Управление порядковыми номерами
Монотонное возрастание
Каждый Fragment несёт порядковый номер передачи (Sequence_Number), монотонно возрастающий в рамках одной сессии.
Двунаправленная независимость
Направление сбора данных и направление инъекции данных поддерживают полностью независимые пространства порядковых номеров:
Направление сбора данных: seq 1, 2, 3, 4, 5 ...
Направление инъекции данных: seq 1, 2, 3, 4, 5 ...
Изменения порядковых номеров в одном направлении не влияют на другое направление.
6.6 Сохранение временной метки происхождения
DTP гарантирует, что временная метка происхождения (Origin_Timestamp) каждого Fragment остаётся неизменной на протяжении всего процесса передачи:
- Фиксирует момент фактического создания данных в источнике, а не момент передачи
- Использует часовой пояс UTC с миллисекундной точностью
- После сериализации, шифрования, передачи, дешифрования и десериализации временная метка остаётся идентичной значению до отправки
- Получатель сохраняет оригинальный Origin_Timestamp без модификации
Это гарантирует, что даже при загрузке данных с задержкой (например, в офлайн-сценариях) iFay может восстановить истинную временную шкалу.
6.7 Валидация DAG-зависимостей
Получатель выполняет валидацию DAG-зависимостей при получении Fragment:
- Обнаружение циклов: проверяет, что зависимости нового Fragment не формируют цикл в DAG. При обнаружении цикла Fragment отклоняется
- Разрешение зависимостей: если целевой Fragment зависимости ещё не прибыл, текущий Fragment помечается как «зависимость ожидает разрешения» и кэшируется
- Отложенное разрешение: когда зависимый Fragment прибывает, ранее кэшированные Fragment автоматически разрешаются
