Please answer the following questions for yourself before submitting an issue.
Be able to receive 0 and false as a result of some action in a service using NATS and Protobuf.
0 and false are received as undefined.
Protobuf serialize or deserialize the message incorrectly and turns 0 and false results into undefined
const broker = new ServiceBroker({
transporter: "NATS",
serializer: 'ProtoBuf'
});
broker.createService({
name: "greeter",
version: 1,
actions: {
willReturnFalse() {
return false;
},
willReturnZero() {
return 0;
}
});
describe("Test 'greeter' service", () => {
const broker = new ServiceBroker({ transporter: 'nats://localhost:4222', serializer: 'ProtoBuf' });
beforeAll(async () => {
await broker.start();
await broker.waitForServices([{ name: 'greeter', version: 1 }]);
});
afterAll(() => broker.stop());
describe("Test 'greeter.willReturnFalse' action", () => {
it("should return false", () => {
expect(broker.call("v1.greeter.willReturnFalse")).resolves.toBe(false);
});
});
describe("Test 'greeter.willReturnFalse' action", () => {
it("should return 0", () => {
expect(broker.call("v1.greeter.willReturnZero")).resolves.toBe(0);
});
});
});
// both tests will fail receiving undefined
https://github.com/alvarocantador/moleculer-zero-and-false-bug
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
@AndreMaz could you help with it?
@hoanganh25991 Could you check once?
Hi @alvarocantador ,
I've tested ProtoBuf on NATS, the serializer work as expected

In my test, I only use moleculer-cli to init minimal project template.
I guess your API service make change on value.
Example ready to run:
https://github.com/hoanganh25991/protobuf-serialize-false-zero
@icebob @hoanganh25991 In your case, the greeter is a local service and its work as expected. Try to run dev in a shell and call it in another repl, you will see undefined.
I have the bug example here: https://github.com/alvarocantador/moleculer-zero-and-false-bug
In this case I am using the moleculer-runner inside of a docker image, and via NATS in another broker, I am trying to call the willReturnFalse and willReturnZero actions.
Only in the npm run dev shell:

Now with an REPL:

Hi @alvarocantador ,
By default, broker config "prefer local", which lead to call without send through NATS.
I see your issue when add another repl.
I digging in transporter & serializer code to figure out.
Protobuf serialize flow:
I think the if check falsy value on obj.data in serializer/base.js cause the problem:
As what I test, remove the falsy check, response return false, 0 as expected
https://github.com/moleculerjs/moleculer/blob/master/src/serializers/base.js#L98

https://github.com/moleculerjs/moleculer/blob/master/src/serializers/protobuf.js
base.js > serializeCustomFields
Falsy value not converted to string
case P.PACKET_RESPONSE: {
obj.meta = JSON.stringify(obj.meta);
if (obj.data) {
if (!obj.stream) {
obj.data = JSON.stringify(obj.data);
}
}
}
protobuf.js > serializeCustomFields
Buffer not built up
case P.PACKET_RESPONSE: {
if (obj.data && !obj.stream)
obj.data = Buffer.from(obj.data);
break;
}
protobuf.js > deserializeCustomFields
No data key on obj, return undefined
case P.PACKET_RESPONSE: {
if (obj.data && !obj.stream) {
if (obj.data.length)
obj.data = obj.data.toString("utf8");
else
obj.data = undefined;
}
break;
}
@hoanganh25991 good catch. Thank you, I'm fixing.
I've fixed. @hoanganh25991 @alvarocantador could you check it to install master with npm i moleculerjs/moleculer?
Hi @icebob ,
I've tested your fix in "moleculerjs/moleculer" package, now Protobuf serialize correctly on false, 0 case. However, it return as "undefined" on null case.

As my test above, on "greeter.willReturnNull", Protobuf deserialize as "undefined".
Test example ready to run:
https://github.com/hoanganh25991/protobuf-serialize-false-zero
Thanks. I'm checking...
I've fixed it.
Most helpful comment
I've fixed it.