dapr / js-sdk

Dapr SDK for Javascript
Apache License 2.0
194 stars 82 forks source link

Dapr client.pubsub.publish Function Does Not Send CloudEvent with Correct Data Field Content #538

Open MotaOcimar opened 10 months ago

MotaOcimar commented 10 months ago

Expected Behavior

When calling the client.pubsub.publish function for a class, Dapr should send a CloudEvent with the data field filled with the value passed to the function. A type conversion could be done so that the value is sent correctly. For example, JavaScript's Object.assign could be used.

If this option is not possible, the Dapr sdk function should return a response with the error field filled with a message describing the error.

Actual Behavior

When calling the client.pubsub.publish function for a class, Dapr sends a CloudEvent with the data field empty. The data_base64 field is filled with the value [object Object], which does not describe the real object that should be sent.

Steps to Reproduce the Problem

  1. Create a class with the data you want to be sent by Dapr
class EventData {
    constructor(id, name) {
        this.id = id;
        this.name = name;
    }
}
  1. Try to send an event with an instance of this class
const client = new DaprClient({daprHost, daprPort});
const data = new EventData(1, 'Teste');
const response = await client.pubsub.publish("pubsub", "topic", data);
console.log("Response: ", response); // Response:  {}
  1. Check the contents of the event received by Dapr. One possibility is to use a Dapr subscriber receiving the events in JSON format instead of CloudEvent:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 3000;

app.use(bodyParser.json({ type: 'application/*+json' }));

// Subscribe to topic
app.get('/dapr/subscribe', (_req, res) => {
    res.json([ { pubsubname: "pubsub", topic: "topic", route: "route" } ]);
});

// Handle incoming events
app.post('/route', (req, res) => {
    console.log(req.body);
    res.sendStatus(200);
});

app.listen(port, () => console.log(`Node App listening on port ${port}!`));

The received event will be something like: (Note there is no data field, but data_base64)

{
  data_base64: 'W29iamVjdCBPYmplY3Rd',
  datacontenttype: 'application/octet-stream',
  id: '951b5617-4929-413b-aebe-f092044d0eaf',
  pubsubname: 'pubsub',
  source: 'subscriber',
  specversion: '1.0',
  time: '2023-10-18T13:39:41-03:00',
  topic: 'topic',
  traceid: '00-8431b0187017d5f21cf078b68061a55e-eed8a8f906f35146-01',
  traceparent: '00-8431b0187017d5f21cf078b68061a55e-eed8a8f906f35146-01',
  tracestate: '',
  type: 'com.dapr.event.sent'
}

Decoding the value of data_base64 using base64, the value will be literally [object Object], which does not describe the real object that should have been sent.

  1. Extra: Convert data before sending the event and check the contents of the event received by Dapr:
// ...
const response = await client.pubsub.publish(pubSubId, topic, Object.assign({}, data));
// Object.assign was used to convert the type                 ^^^^^^^^^^^^^^^^^^^^^^^
console.log("Response: ", response); // Response:  {}

The received event will be something like: (Note that the data field is filled correctly)

{
  data: { id: 1, name: 'Teste' },
  datacontenttype: 'application/json',
  id: 'deb2b6fe-2727-4ae9-8190-4027b8911d60',
  pubsubname: 'pubsub',
  source: 'subscriber',
  specversion: '1.0',
  time: '2023-10-18T13:45:58-03:00',
  topic: 'topic',
  traceid: '00-b29556072612451e044b137c8ed741ee-fb12d350adf79fa2-01',
  traceparent: '00-b29556072612451e044b137c8ed741ee-fb12d350adf79fa2-01',
  tracestate: '',
  type: 'com.dapr.event.sent'
}
MotaOcimar commented 10 months ago

Note: I'm using Dapr SDK 3.0.0 because newer versions give me the following error

internal/modules/cjs/loader.js:888
  throw err;
  ^

Error: Cannot find module 'node:stream'
Require stack:
- D:\dapr-playground\node_modules\@dapr\dapr\utils\Streams.util.js
- D:\dapr-playground\node_modules\@dapr\dapr\implementation\Client\GRPCClient\crypto.js
- D:\dapr-playground\node_modules\@dapr\dapr\implementation\Client\DaprClient.js
- D:\dapr-playground\node_modules\@dapr\dapr\implementation\Server\DaprServer.js
- D:\dapr-playground\node_modules\@dapr\dapr\index.js
- D:\dapr-playground\publisher.js

Edit: Node Version: 14.17.0 Updating Node to v18.16.0 makes this error related to "node:stream" no longer happen. But the problem reported in this issue persists using Dapr SDK 3.2.0

dapr-bot commented 8 months ago

This issue has been automatically marked as stale because it has not had activity in the last 60 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.

MotaOcimar commented 8 months ago

Oh, I think this issue shouldn't be closed until it is solved