4 минуты
Быстрая и простая отладка субграфа с использованием форков
Как и многие системы, обрабатывающие большие объемы данных, Индексаторы The Graph (Graph Nodes) могут потребовать значительное время для синхронизации вашего субграфа с целевым блокчейном. Несоответствие между быстрыми изменениями, необходимыми для отладки, и длительным временем ожидания индексирования крайне контрпродуктивно, и мы хорошо осведомлены об этом. Именно поэтому мы представляем форк субграфа, разработанный LimeChain, и в этой статье я покажу, как эта функция может существенно ускорить процесс отладки субграфов!
И так, что это?
Форкинг субграфа — это процесс ленивой загрузки объектов из другого хранилища субграфа (обычно удаленного).
В контексте отладки форкинг субграфа позволяет вам отлаживать ваш неудавшийся субграф на блоке X без необходимости ждать синхронизации с этим блоком X.
Что? Как?
Когда вы развертываете субграф на удалённой Graph Node для индексирования и он даёт сбой на блоке X, хорошая новость заключается в том, что Graph Node всё равно будет обслуживать GraphQL-запросы, используя своё хранилище, синхронизированное с блоком X. Это замечательно! Это означает, что мы можем воспользоваться этим “актуальным” хранилищем, чтобы исправить ошибки, возникающие при индексировании блока X.
Короче говоря, мы собираемся форкать неудавшийся субграф с удалённой Graph Node, которая гарантированно имеет индексированный субграф до блока X, чтобы предоставить локально развернутому субграфу, который отлаживается на блоке X, актуальное представление о состоянии индексирования.
Пожалуйста, покажите мне какой-нибудь код!
Чтобы сосредоточиться на отладке субграфа, давайте сделаем всё проще и используем пример субграфа, индексирующий смарт-контракт Ethereum Gravity.
Вот обработчики, определённые для индексирования Gravatar
, без каких-либо ошибок:
1export function handleNewGravatar(event: NewGravatar): void {2 let gravatar = new Gravatar(event.params.id.toHex().toString())3 gravatar.owner = event.params.owner4 gravatar.displayName = event.params.displayName5 gravatar.imageUrl = event.params.imageUrl6 gravatar.save()7}89export function handleUpdatedGravatar(event: UpdatedGravatar): void {10 let gravatar = Gravatar.load(event.params.id.toI32().toString())11 if (gravatar == null) {12 log.critical('Gravatar not found!', [])13 return14 }15 gravatar.owner = event.params.owner16 gravatar.displayName = event.params.displayName17 gravatar.imageUrl = event.params.imageUrl18 gravatar.save()19}
Ой, как неудачно! Когда я деплою мой идеально выглядящий субграф в Subgraph Studio, он терпит неудачу с ошибкой “Gravatar не найден!”.
Обычный способ попытаться исправить это:
- Внести изменения в источник мэппингов, которые, по Вашему мнению, решат проблему (в то время как я знаю, что это не так).
- Перезапустить развертывание своего субграфа в Subgraph Studio (или на другую удалённую Graph Node).
- Подождать, пока он синхронизируется.
- Если он снова сломается, вернуться к пункту 1, в противном случае: Ура!
Действительно, это похоже на обычный процесс отладки, но есть один шаг, который ужасно замедляет процесс: 3. Ждите, пока завершится синхронизация.
Используя форкинг субграфа, мы можем фактически исключить этот шаг. Вот как это выглядит:
- Запустите локальную Graph Node с помощью соответстсвующего набора fork-base.
- Внесите изменения в источник мэппингов, которые, по Вашему мнению, решат проблему.
- Разверните на локальной Graph Node, используя форкинг неудавшегося субграфа и начав с проблемного блока.
- Если он снова сломается, вернитесь к пункту 1, в противном случае: Ура!
Сейчас у Вас может появиться 2 вопроса:
- fork-base - что это???
- Форкнуть кого?!
И я вам отвечаю:
fork-base
— это “базовый” URL, так что когда ID субграфа добавляется, получившийся URL (<fork-base>/<subgraph-id>
) становится действительной конечной точкой GraphQL для хранилища субграфа.- Форкнуть легко, не нужно напрягаться:
1$ graph deploy <subgraph-name> --debug-fork <subgraph-id> --ipfs http://localhost:5001 --node http://localhost:8020
Кроме того, не забудьте установить поле dataSources.source.startBlock
в манифесте субграфа на номер проблемного блока, чтобы пропустить индексирование ненужных блоков и воспользоваться форком!
Итак, вот что я делаю:
- Я запускаю локальную Graph Node (вот как это сделать) с опцией
fork-base
, установленной на:https://api.thegraph.com/subgraphs/id/
, так как я собираюсь форкать субграф, тот самый, который я развернул ранее, с Subgraph Studio.
1$ cargo run -p graph-node --release -- \2 --postgres-url postgresql://USERNAME[:PASSWORD]@localhost:5432/graph-node \3 --ethereum-rpc NETWORK_NAME:[CAPABILITIES]:URL \4 --ipfs 127.0.0.1:50015 --fork-base https://api.thegraph.com/subgraphs/id/
- После тщательной проверки я замечаю, что существует несоответствие в представлениях
id
, используемых при индексированииGravatar
в двух моих обработчиках. В то время какhandleNewGravatar
конвертирует его в hex (event.params.id.toHex()
),handleUpdatedGravatar
использует int32 (event.params.id.toI32()
), что приводит к тому, чтоhandleUpdatedGravatar
завершается ошибкой и появляется сообщение “Gravatar not found!”. Я заставляю оба обработчика конвертироватьid
в hex. - После внесения изменений, я развертываю свой субграф на локальной Graph Node, форкаю неудачно развернутый субграф и устанавливаю значение
dataSources.source.startBlock
равным6190343
в файлеsubgraph.yaml
:
1$ graph deploy gravity --debug-fork QmNp169tKvomnH3cPXTfGg4ZEhAHA6kEq5oy1XDqAxqHmW --ipfs http://localhost:5001 --node http://localhost:8020
- Я проверяю логи, созданные локальной Graph Node, и, ура!, кажется, все работает.
- Я развертываю теперь безошибочный субграф на удаленной Graph Node и живу счастливо до конца своих дней! (только без картошки)