Giter Club home page Giter Club logo

Comments (13)

codehimsa avatar codehimsa commented on August 30, 2024

Вот этот парсер выглядит поновее и понадёжнее: https://github.com/starwing/lua-protobuf
есть ли планы по его внедрению?

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Довольно странная ошибка, если учесть, что в getItem.proto это поле имеет тип int32:

// version: 1.0

syntax = "proto3";

package qlua.rpc.getItem;

option optimize_for = SPEED;
option java_package = "qlua.rpc";

message Request {

    string table_name = 1;
    int32 index = 2;
}

message Result {
    map<string, string> table_row = 1;
}

Выложите, пожалуйста, свои версии файлов getItem.proto и getItem_pb.lua -- может быть, у нас с Вами как-то по-разному они обработались.

Ещё есть предположение, что это глючит энкодер на стороне Java, но если при смене типа в .proto начинает работать, то теория шаткая. Я ещё проверю в своём клиенте сегодня эти вызовы.

Насчёт парсера: согласен, по сравнению с тем, на который Вы дали ссылку, используемый сейчас выглядит как поделка школьника. Мне и самому приходилось допиливать его напильником: оригинальный проект уже не поддерживается, а пофиксенные баги и новые фичи разбросаны по куче форков (часто тоже не первой свежести).

Посмотрю на досуге, спасибо!

from quik-lua-rpc.

codehimsa avatar codehimsa commented on August 30, 2024

getItem_pb.lua

Вот интересующий нас кусок. По типам всё честно, 32 битный нефиксированный int

module.REQUEST_INDEX_FIELD.name = 'index'
module.REQUEST_INDEX_FIELD.full_name = '.qlua.rpc.getItem.Request.index'
module.REQUEST_INDEX_FIELD.number = 2
module.REQUEST_INDEX_FIELD.index = 1
module.REQUEST_INDEX_FIELD.label = 1
module.REQUEST_INDEX_FIELD.has_default_value = false
module.REQUEST_INDEX_FIELD.default_value = 0
module.REQUEST_INDEX_FIELD.type = 5
module.REQUEST_INDEX_FIELD.cpp_type = 1

Энкодер в java оптимизировал размер структуры. когда числа вмешается в знаковый байт - он пишет один байт. Если шире - то уже два байта. Вот hexdump структур, что я отправил в lua:

$ hexdump -C firms128.dat
00000000  0a 05 66 69 72 6d 73 10  fd 01                    |..firms...|
0000000a
$ hexdump -C firms127.dat
00000000  0a 05 66 69 72 6d 73 10  7f                       |..firms..|
00000009

В первом случае делал запрос к таблице firms с индексом 128 (тогда и возникла ошибка). и во втором случае 127 (всё отработало корректно). Структуры отличаются на один байт. Изменение параметров в proto файле (optimized_for) не помогло.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Да, проблему подтверждаю.
Буду разбираться.

Пока что инспекция привела к тому, что при значении index = 128 protobuf-lua в файле init.lua по какой-то причине не находит декодера для тега поля и пытается его скипнуть (строки 669-672). По какой-то (той же?) причине скиппер выбирается неверный: вместо _SkipVarint используется _SkipFixed32 (код определения скиппера -- в файле decoder.lua, функция _FieldSkipper()). Я грешу на эту конструкцию:

local ord = string.byte
local sub = string.sub
...
local wire_type = ord(sub(tag_bytes, 1, 1)) % 8 + 1

Судя по документации Lua, string.byte в разных локалях может давать разные результаты.

Пока что думаю всё же повозиться с фиксами в protobuf-lua, т.к. оно будет быстрее, чем переписывать всё на новый биндинг, но в итоге это надо будет сделать, а то не радует меня, сколько нам открытий чудных готовит protobuf-lua.

P.S.
Ещё мне что-то совсем не понравилась молчанка со стороны скрипта на сервере -- выплюнул ошибку в консоль и всё, а клиент при этом висит, не получив ответ. Тоже исправлю.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Ещё, судя по документации к Protocol Buffers (https://developers.google.com/protocol-buffers/docs/encoding#varints), можно сделать вывод, что у Вас protobuf на стороне клиента неверно кодирует число 128 в varint (либо Вы ошиблись, когда сохраняли байтовый вывод в файл). Либо я что-то не понял :)

$ hexdump -C firms128.dat
00000000  0a 05 66 69 72 6d 73 10  **fd 01**                 |..firms...|
0000000a

,где fd 01 по технике декодирования превращается в 253.

Должно быть что-то типа

$ hexdump -C firms128.dat
00000000  0a 05 66 69 72 6d 73 10  **80 01**                    |..firms...|
0000000a

, где 80 01 по технике декодирования превращается в 128.

Для достоверности можно проверить тут: https://protogen.marcgravell.com/decode

У меня в клиенте на Java запрос с параметрами "firms", 128 в hex выглядит примерно так:
ByteString: 000000000000000000000a056669726d73108001. Но, конечно, один фиг, баг с декодером проявляется.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Проблемы появляются уже на этапе доставания байтов из ZeroMQ (скрипт service.lua, строка 39).
С index = 127 из ret:data() приходит 0A-05-66-69-72-6D-73-10-7F, в то время как с index = 128 приходит не совсем понятное 0A-05-66-69-72-6D-73-10-EF-BF-BD-01.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Проблема оказалась в коде самого Java-клиента:
в классе com.enfernuz.quik.lua.rpc.api.zmq.impl.ZmqTcpRpcGatewayImpl в методе makeRequest
байтовый массив запроса преобразовывался в UTF8-строку. Мне почему-то показалось, что единственный способ создать экземпляр ZMsg -- это вызвать ZMsg.newStringMsg(String... strings). Но, оказывается, можно создать new ZMsg() и передать туда байтовый массив уже после.

Поправил код в репозитории Java-клиента -- теперь должно работать.

from quik-lua-rpc.

codehimsa avatar codehimsa commented on August 30, 2024

Да, всё полечилось. Спасибо. По пути ещё одну багу нашёл - если в терминале quik выставлен русский язык интерфейса, то при некорректном запросе в ответе содержится текст с русскими буквами. И это ломает декодер на стороне java, например в SendTransaction.Result.parseFrom(resultAsByteString);. Но это уже мелочи

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

С этими кодировками вообще там беда. На моей системе с локалью Russian (Russia) QLua выдаёт текст в кодировке CP1251. Если ничего не делать, то на стороне Java то ли не удаётся это распарсить вообще (protobuf пишет про not valid UTF8 string), то ли кракозябры выводятся (точно уже не помню). В итоге я на стороне сервиса весь текст перевожу костылём в UTF8.
Возможно, где-то не углядел и не перевёл. Посмотрю.
Если QLua выдаёт текст в зависимости от системной локали, то дела будут плохи, конечно, т.к. надо будет всё переписывать.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Перекодировал сообщение об ошибке в UTF8 в коммите 567b909.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Играюсь сейчас с lua-protobuf. Он, конечно, в целом, почище, чем protobuf-lua, но тоже не без "подарков".
Например, кодирую в Java RPC-запрос к getOrderByNumber:

string: class_code = "SPBFUT",
int64: order_number = 30745970930

Java hex sent:    0a0653504246555410f291e9c472
Lua hex received: 0a0653504246555410f291e9c472

Lua decoded struct:
{
  class_code = "SPBFUT",
  order_id = 681199858
}

Проставление типов uint64, fixed64 к order_num не помогло. Более мелкие числа обрабатываются нормально.

Онлайн-декодер на https://protogen.marcgravell.com/decode парсит корректно.

Примечательно, что тестовый пример с https://github.com/starwing/lua-protobuf на Lua 5.1 вместо данных phonenumber выдаёт отрицательные числа. Если запускать на Lua 5.3, то всё нормально.
Оставил репорт: starwing/lua-protobuf#58

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Проблему вроде как решил. Буду продолжать внедрять lua-protobuf.

from quik-lua-rpc.

Enfernuz avatar Enfernuz commented on August 30, 2024

Переход на lua-protobuf в качестве Lua-обёртки для protobuf осуществлён.

from quik-lua-rpc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.