-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Refined Topic Alias support. (Implement #1300) #1301
Conversation
Add automatic topic alias management functionality. - On PUBLISH sending, the client can automatic using/assin Topic Alias (optional). - On PUBLISH receiving, the topic parameter of on message handler is automatically complemented but the packet.topic preserves the original topic. Fix invalid tests.
5b89b94
to
f8178aa
Compare
@redboltz my next question, do you think this is changing the behavior of the existing API at all? |
README.md
Outdated
@@ -206,7 +206,41 @@ the final connection when it drops. | |||
The default value is 1000 ms which means it will try to reconnect 1 second | |||
after losing the connection. | |||
|
|||
<a name="topicalias"></a> | |||
## About Topic Alias management |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: caps on Management
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I will fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
No. I don't think so. InterfaceThis PR adds options. Not contains breaking changes for existing APIs. BehaviorAuto Use/Assign Topic Alias functionality are enabled only if the user set options There is one exception. When QoS1/2 packets that use Topic Alias are inserted into the store, Topic Alias is removed and Topic Name is recovered. It is expected behavior by MQTT spec. So I think this behavior change is a bug fix. |
lib/client.js
Outdated
} | ||
|
||
function removeTopicAlias (client, packet) { | ||
// remove topic alias because it shouldn't be used on re-sending |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a bit of a better comment here. What's the use for this function? Is it removing a topic alias because some other topic has overridden the topic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a kind of utility function for internal use.
I think that the commend should be removed here.
This function removes Topic Alias property and recover Topic Name from the Topic Alias.
Perhaps the function name should be removeTopicAliasAndRecoverTopicName
. Is this too long?
I think that the comment should be written the caller side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@@ -73,6 +74,7 @@ | |||
"number-allocator": "^1.0.7", | |||
"pump": "^3.0.0", | |||
"readable-stream": "^3.6.0", | |||
"rfdc": "^1.3.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
always hesitant to add more dependencies. Could you explain the purpose of rfdc and collections, and why there isn't a suitable Node.js / JS builtin that can perform their tasks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rfdc is for clone that I mentioned at #1301 (comment)
It is efficient and straightforward notation. It seems that the library is well maintained and the big number of weekly downloads. See Benchmarks https://www.npmjs.com/package/rfdc
AFAIK, Node.js/JS there is no straightforward way.
One of the built-in way is as follows:
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
https://stackoverflow.com/questions/6089058/nodejs-how-to-clone-an-object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems to have created alot of issues with collections...
see there :
#homebridge-plugins/homebridge-camera-ffmpeg#1240
#NorthernMan54/homebridge-alexa#481
#dgreif/ring#844
and probably many more...
test/client_mqtt5.js
Outdated
qos: 0, | ||
properties: { topicAlias: 1 } | ||
}) | ||
// overwrite register topicAlias |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "overwrite registered topicAlias"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I will fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
// use topicAlias | ||
client.publish('', 'Message', { properties: { topicAlias: 1 } }) | ||
// use topicAlias by autoApplyTopicAlias | ||
client.publish('test1', 'Message') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so when you enable autoApplyTopicAlias it will substitute the alias for the message, and existing behaviour without it set to true is that on client.publish('test1', 'Message')
, the topicAlias already registered wouldn't be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. If autoApplyTopicAlias is true, and the user wants to use Topic Alias, the user needs to set the empty TopicName and add Topic Alias property manually.
client.publish('test3', 'Message') | ||
|
||
// renew LRU topicAlias | ||
client.publish('test4', 'Message') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so here the topic alias will be updated dynamically because autoAssignTopicAlias is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens on reconnect? or client.end? is there persistence of the topicAliases? Not 100% on the MQTT spec for this scenario...
also, great PR. Thanks for providing this along with tests. @redboltz great job. |
if (entry) { | ||
delete this.topicToAlias[entry.topic] | ||
} | ||
this.aliasToTopic.set(alias, {'topic': topic, 'alias': alias}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this redundant to have the set
method on aliasToTopic
and topicToAlias
as a general JS object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.aliasToTopic = new LruMap()
this.topicToAlias = {}
aliasToTopic
is an instance of LruMap(). aliasToTopic
requires LRU for overwriting. So it cannot be a simple JS Object.
topicToAlias
is JS Object. It doesn't require LRU.
Could you elaborate your question?
Do you mean add set method to topicToAlias
?
And update the code using this/topicToAlias.set(topic, alias)
instead of this.topicToAlias[topic] = alias
?
I personally think it is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that makes sense. Ignore my initial question. New question: why {topic: topic, alias: alias}
, when the information for the alias
is the key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for
return this.aliasToTopic.min().alias
lru-map only provide least value not key. I tried to find getting key-value entry way but it seems that it doesn't exist. https://www.collectionsjs.com/lru-map
That's why I added alias not only as key but also as value.
lib/topic-alias-send.js
Outdated
} | ||
|
||
/** | ||
* Get LRU topic alias |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expand LRU to "Get Least Recently Used (LRU) topic alias"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will fix it.
See #1300 (comment) Topic Alias lifetime and Impact for implementation. Topic Alias lifetime is during connection, not session. So the client/server cannot use Topic Aliases that is used by the previous connection. This is the spec. |
pending nits on comments, this PR looks good to me. Will approve once changes are pushed. |
…AndRecoverTopicName`. Add comments for caller side of `removeTopicAliasAndRecoverTopicName`.
I think that I've done all requested fixes. Please check them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
thank you @redboltz! |
@YoDaMa Thank you for merging !! I noticed one minor behavior change. Lines 68 to 79 in e3e15c3
On message handler, when broker sends an empty TopicName and registered TopicAliasProperty, the first parameter It always happens even if TopicAlias related options are not set. But I believe that it is expected behavior for users. |
I think that collections should be replaced some other library. |
Sorry I looked over montagejs/collections#241 (comment). I said "replacing" but it was my overreaction. Just in case, I continue to look for altenative one. |
I analyzed the issue and commected montagejs/collections#241 (comment) collections.js updates |
Add automatic topic alias management functionality.
Alias (optional).
automatically complemented but the packet.topic preserves the original
topic.
Fix invalid tests.