pulsar-client-node: Error: Failed to send message: AlreadyClosed

Hi there, Why this example with 1 second timeout works fine:

const client = new Pulsar.Client({
    serviceUrl: 'pulsar://localhost:6650',
})

const producer = await client.createProducer({
    topic: 'persistent://public/default/my-topic',
})

setTimeout(() => {
    producer.send({
        data: Buffer.from('My Message'),
    })
}, 1000)

But this example with a few more seconds timeout occurs an error?

const client = new Pulsar.Client({
    serviceUrl: 'pulsar://localhost:6650',
})

const producer = await client.createProducer({
    topic: 'persistent://public/default/my-topic',
})

setTimeout(() => {
    producer.send({
        data: Buffer.from('My Message'),
    })
}, 9000)

Full error message:

You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:
Error: Failed to send message: AlreadyClosed

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 25 (12 by maintainers)

Most upvoted comments

@sijie sounds like a good approach, I tried my approach of creating napi ref, but couldn’t find a way to implement it.

I will implement your approach and create a pull request for that.

Changing my code to, instead of console.log(Sent message: ${msg}); to console.log(Sent message: ${msg} - client ${client}); fixes the issue for me.

okay if that’s true, i think you’re right about the root cause. @sijie how do you want to proceed?

@sijie tried out creating a reference to a client from the producer but it didn’t help (tried with InstanceAccesor) and it created a weird dependency on the code which I didn’t feel comfortable doing.

But I found out how to create a reference for a client and un-reference it when the client closes the connection.

This PR - https://github.com/apache/pulsar-client-node/pull/85 fixed the code I wrote above 😃

@alexyans @yosiat I think we can let Producer object keep a reference to the client. So if your application keeps references to Producer, it should keep the reference to the client as well. So the client instance will not be destroyed.

That would be hard to tell without looking at the code. We know the client uses a connection pool for the original client connection, but it’s not clear to me whether the producers/consumers create separate connections or piggyback on the one client connection. I’m not exactly sure what happens when you create a producer, it could be cheaper than it looks.

But yeah, I share your frustration. Hope it gets resolved soon.

For my use case, I worked around the problem by always creating the producer right before I emit a message. Flushing and closing after use should prevent leaks.

Oh, as a quick fix its a good idea. but what if I have about more than 1000 send messages per second? Is it ok to create a producer, send and then flush and close the producer each time?

@alijmlzd did you try rolling back to an older version? Any luck finding one?

I have the same problem. Sending a message immediately after initializing the producer works fine, so it can’t be a TLS handshake issue. The connection seems to timeout after a second or so.