Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: problem with publish callback invoked twice #1635

Merged

Conversation

ogis-yamazaki
Copy link
Contributor

@ogis-yamazaki ogis-yamazaki commented Jul 12, 2023

User callback is executed twice if the received PUBACK indicates failure (by reason code).
Related issue: #1511

The following modification prevents the callback from invoked twice.

  • If resonCode in PUBACK to failure, set the cb variable to NULL after the callback is invoked.
  • When deleting a message from the store, do not invoke the callback if cb is null

@codecov
Copy link

codecov bot commented Jul 12, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +0.53 🎉

Comparison is base (d71b000) 85.74% compared to head (d226163) 86.28%.

❗ Current head d226163 differs from pull request most recent head b5ffdd8. Consider uploading reports for the commit b5ffdd8 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1635      +/-   ##
==========================================
+ Coverage   85.74%   86.28%   +0.53%     
==========================================
  Files          13       13              
  Lines        1249     1254       +5     
==========================================
+ Hits         1071     1082      +11     
+ Misses        178      172       -6     
Impacted Files Coverage Δ
lib/client.js 91.16% <100.00%> (+0.73%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@ogis-yamazaki ogis-yamazaki changed the title Fix problem with publish callback invoked twice Fix: problem with publish callback invoked twice Jul 12, 2023
@ogis-yamazaki ogis-yamazaki changed the title Fix: problem with publish callback invoked twice fix: problem with publish callback invoked twice Jul 12, 2023
Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @ogis-yamazaki ! Would you mind to add a unit test that covers this?

lib/client.js Outdated
@@ -1626,6 +1626,7 @@ class MqttClient extends EventEmitter {
err = new Error('Publish error: ' + errors[pubackRC])
err.code = pubackRC
cb(err, packet)
cb = null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cb = null
// prevent invoking callback twice when deleting message from store #1511
cb = null

@ogis-yamazaki
Copy link
Contributor Author

@robertsLando

Added qos 1 and qos2 tests.

When an error occurs in PUBREC, added a process to remove the message from the outgoingStore.

robertsLando
robertsLando previously approved these changes Jul 12, 2023
Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By checking the code on my side I saw that this:

delete this.outgoing[messageId]
      this.outgoingStore.del(packet, cb)
      this.messageIdProvider.deallocate(messageId)
      this._invokeStoreProcessingQueue()

Is used 3 times in the code. Would you mind to create a dedicated function for that?

I see we also have a method removeOutgoingMessage, it doesn't call _invokeStoreProcessingQueue and messageIdProvider.deallocate maybe that's an error too?

@ogis-yamazaki
Copy link
Contributor Author

@robertsLando

Is used 3 times in the code. Would you mind to create a dedicated function for that?

OK

I see we also have a method removeOutgoingMessage, it doesn't call _invokeStoreProcessingQueue and messageIdProvider.deallocate maybe that's an error too?

As you said, additional processing was needed.

In removeOutgoingMessage, needs to call messageIdProvider.deallocate.
If not called, the messageId will be in use forever.

_invokeStoreProcessingQueue must also be called.
Normally, _invokeStoreProcessingQueue is called when a PUBACK or similar event occurs, but removeOutgoingMessage will not pass through it.
The _storeProcessingQueue may remain unprocessed.

The _invokeStoreProcessingQueue function also seems to have an implementation problem.

There is a problem if _invokeStoreProcessingQueue is called while the store is resending(_storeProcessing = true).
Specifically, Message overtaking may occur.
It is necessary to modify the content of _storeProcessingQueue`` so that it is not processed during resend(_storeProcessing = true).

@robertsLando
Copy link
Member

Would you mind to also fix those errors or do you prefer to do that in a separeted PR?

@ogis-yamazaki ogis-yamazaki force-pushed the fix_publish_callback_invoke_twice branch from 79a5789 to b5ffdd8 Compare July 13, 2023 10:39
@ogis-yamazaki
Copy link
Contributor Author

@robertsLando

Would you mind to also fix those errors or do you prefer to do that in a separeted PR?

Fixed in this PR.

Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, now everything is much cleaner. Thanks @ogis-yamazaki 🙏🏼

@robertsLando robertsLando merged commit 79b23a8 into mqttjs:main Jul 14, 2023
4 checks passed
@ogis-yamazaki ogis-yamazaki deleted the fix_publish_callback_invoke_twice branch July 14, 2023 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants