@hlf-core/transport
Транспорт в hlf-core намеренно разнесён на три пакета, и прежде чем говорить о клиенте, стоит
назвать всю тройку. @hlf-core/transport-common держит протокол —
конверты, подпись, nonce, константы. @hlf-core/transport-chaincode
это сторона chaincode. А @hlf-core/transport, о котором здесь и речь, это клиентская сторона.
Общий пакет посередине не роскошь: он гарантирует, что клиент и chaincode говорят на одном и том
же языке конвертов.
Главный класс — TransportFabric, наследник TransportImpl из @ts-core. Отсюда и привычные
connect, send, sendListen, и доступ к api: FabricApiClient. По флагу isReadonly транспорт
сам выбирает, вызвать evaluate или submit, так что прикладному коду об этом думать не нужно.
Если chaincode бросил доменную ошибку, parseChaincodeError восстанавливает её из обёртки Fabric
обратно в ExtendedError с кодом — то есть ровно в том виде, в каком её бросил обработчик.
const transport = new TransportFabric(logger, settings);
await transport.connect();
const user = await transport.sendListen(new UserGetCommand(uid));
await transport.sendListen(new UserAddCommand(dto), {userId, signature});
Ответ на изменяющую команду приходит не сразу, а из блока, и разбирает его
TransportFabricBlockParser. Он превращает блок в типизированный ITransportFabricBlock и
связывает события с транзакциями по хэшу, так что у события появляются requestId и код валидации.
По requestId клиент и сопоставляет пришедший ответ с исходной командой.
Отдельно стоит batch-режим — TransportFabricBatch и TransportFabricBlockParserBatch. В нём
изменяющие команды не ждут ответа поодиночке: chaincode накапливает их и исполняет одной транзакцией,
а ответы приходят позже, из блока, как карта «хэш → ответ». Это тот случай, когда мы сознательно
жертвуем мгновенностью ответа ради пропускной способности и стоимости endorsement. Readonly-команды
в batch не попадают — им это и не нужно.
Настройки подключения клиентского транспорта (ITransportFabricConnectionSettings) добавляют к
настройкам сети параметры переподключения, и здесь стоит знать об одном умолчании:
isExitApplicationOnDisconnect включён, то есть при разрыве соединения процесс по умолчанию
завершается. Поведение разумное для сервиса под присмотром оркестратора, но знать о нём нужно
заранее.