-
Notifications
You must be signed in to change notification settings - Fork 227
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
feat(azure-iot-device): adds emit to connect #819
Conversation
// MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message. | ||
}); | ||
async function disconnectHandler () { | ||
clearInterval(sendInterval); |
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.
Weren't we told not to send async to functions that weren't expecting them? You don't send async's as any of the other callbacks.
|
||
client.on('connected', connectCallback); | ||
client.on('error', (err) => console.error(err.message)); | ||
client.on('disconnect', disconnectHandler); |
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.
One is past tense the other isn't.
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.
🕐
@@ -78,6 +78,9 @@ export abstract class InternalClient extends EventEmitter { | |||
debug('Transport error: ' + err.toString()); | |||
}); | |||
|
|||
/*Codes_SRS_NODE_INTERNAL_CLIENT_16_041: [on a connected event from the transport the client will emit connected]*/ | |||
this._transport.on('connected', () => this.emit('connect')); |
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._transport.on('connected', () => this.emit('connect')); [](start = 4, length = 60)
There's an asymmetry here between when we emit('connect')
and when we emit('disconnect')
.
'connect'
is emitted whenever the transport FSM enters the "connected"
(mqtt) or "authenticated"
(amqp) state. No matter what. I think that's good.
'disconnect'
, however, has some big caveats.
In the transport:
1 For MQTT, it is not passed up (emitted) to the client if the disconnect is intentional (disconnectCallback
is set becaues mqtt.disconnect
was called with a callback or mqtt.connect
was called with a callback but failed). If mqtt.disconnect
was called without a callback or if mqtt.connect
was called without a callback and failed, then it is passed up to the client no matter what.
- For AMQP, it is passed up if there is an error updating the sas token or if common/amqp calls the
setDisconnectHandler
callback. If there's an error updating the sas token and the transport is disconnected as a result, 2 events might be passed up. I didn't dig into common/amqp to see when thesetDisconnectHandler
callback gets called.
Then, in the client:
-
It isn't emitted if the disconnect was caused by a retryable error, unless the retry fails to re-enable twins or methods. If both twin and methods fail to be re-enabled, then it gets emitted twice. If neither twins or methods are enabled, then it is never emitted.
-
If the disconnect wasn't caused by an error, or if the error isn't retryable, then it does get emitted.
I feel your pain, brother, but I'm not sure how reliable this is going to be.
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.
@BertKleewein AMQP support wasn't really factored into this PR too much. It should come along later if needed.
In inclined to agree that we need to look more at the device and common transports. My own wonder is how do we deal with MQTTs inherent disconnect/connect on re-authorization. Does the client application really want to know about that?
I'm imagining that with some of your testing we'll quickly iterate to the right emission of both the disconnect and the connect. (In deference to your analysis, I was more worried about the connect emits as this is the newer action)
OK, so @BertKleewein, I appreciate your analysis of the disconnect logic. It is.... not simple? Should it be simple? Is it right to be as complex as it currently is...? Let me respond in sections: Stuff for this PR
@anthonyvercolano you're saying that we should look more at the common transports for dealing with these event emissions? I mean... We could... But what's the definition of when I am a simpleton, so my brain first said this: anytime we enter a conneted state. The reason is because I don't want to have users confused if their application is supposed to be receiving a connect even but we've been too clever and said well we don't think in this specific instance you want to receive a Finally, @anthonyvercolano, ur comment:
this is a good point... from the code, it looks that the logic for AMQP and MQTT reauth transitions happen at the common layer, i.e. there are alot of state changes going on with SAS token updates, but on the device layer... there are no such transitions! This is good in my opinion... Maybe a caveat for the more thoughtful users to include in documentation, that if there is a SAS related Does this sound good? Also @anthonyvercolano what changes do you still have in mind for requested changes? I'm not clear on that any more since I changed the past tense to the present tense (for your grammatics) |
I agree that we can leave disconnect alone for now. My big concern is that I was worried about losing events. e.g. the transport gets disconnected but the event never fires. My secondary concern is about getting double events. e.g. you're already connected and you get another connected event. Disconnect/reconnect because of SAS renewal? My intuition says to shield the user from this, but I'm not sure. The timing of "connected" gets weird when you add subscribing and sasl. Are you "connected" once you get a CONNACK, or do you have to wait until after you're done subscribing (If this happens as part of the connect). Do you need to wait until the sasl auth is complete and all the channels are open? I don't know the answer to this. I'm just pointing out that there can be more than one definition of "connected" Saying "every time you enter the connected state" is simple for you, but you're leaking the state machine logic into the API. If you're in "connected", and then you go into "subscribing" and back to "connected", then you're entering the connected state again. The only reason you would fire the event in this case is because that's what the state machine is doing. The problem is that "connected" from the user's standpoint is different than "connected" from the state machine standpoint. There are many different state machine states that could be considered "connected" and there are many different state machine transitions that could mean "I was previously disconnected but now I am connected". Likewise with disconnected and the connected->disconnected transitions. I could go on a whole rant here on how state machines are broken, but that's a different conversation that I'd be glad to go into (just not here and not now :)) |
My intuition says don't show this to users. So in MQTT and AMQP this PR would shield this from users, because the device level state machine does not transition states when updating the SAS Token. I agree, we do not necessarily want to 1-1 expose the internal state machine to the user... HOWEVER, the device state machine for
I am honestly not well acquainted enough with sasl auth to know the answer to this. I also don't know where sasl auth is used in the device client library. |
@@ -6,6 +6,7 @@ | |||
require('es5-shim'); | |||
const assert = require('chai').assert; | |||
const sinon = require('sinon'); | |||
const { on } = require('process'); |
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's this doing here?
Enter in a backlog item now to address the issues that @bert Kleewein raised with disconnects with twin and methods. We want to make sure that this is clean. See if we can test correct action at the unit testing phase. |
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.
* fix(azure-iothub): fix signatue for getTwin, updateTwin, updateModuleTwin to use Twin fix #673 * improvement(provisioning samples): use the results of the registration to create and open device * test(azure-iot-device-mqtt): reformat _mqtt_test.js (#741) * (chore) add issue templates workflow * Delete ISSUE_TEMPLATE.md * Update bug-report.md * fix(azure-iot-mqtt-base): forceReconnect for disconnecting hang in mqtt-base (#770) * release(2020-04-24): bump package versions (#771) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * refactor: update to mqtt.js v4 (#772) * build: update to mqtt.js v4 * refactor: add debug logs * fix: eslint issue * chore: remove network_e2e directory - no longer used (#775) * refactor: expose connection error in mqtt (#776) * release(2020-05-07): bump package versions (#788) * release(2020-05-07): bump package versions Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * refactor(multipe packages): c2d states no longer using booleans (#797) This moves the logic of checking if C2D is enabled down to the transport level, since it is not necessarily accurate to represent it at the device client level. There is not enough information at that level to make totally accurate judgements of if it is connected or not. * chore(azure-iot-device-amqp): debug logs for c2d (#804) * build: update to mqtt.js v4 * chore: add debug logs * chore(azure-iot-device): updating api version to support twin arrays (#806) * improvement(azure-iot-mqtt-base): maintain knowledge of on the wire publishes (#808) By tracking the on the wire publishes we can reliably complete in case of disconnects or other errors. * feat(azure-iot-mqtt-device): modelID option (#809) This adds the setOption for ModelID, which will enable users to use the existing device client library as a PnP library. To accomodate the lack of support in the existing service API, a switching API call has been added that will use the preview API version if the modelID is set. * release(2020-05-28): bump package versions (#810) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * Create synctodevops.yml * chore(azure-iot-provisioning-device): update samples to use env var (#816) * Add CodeQL security scanning (#815) Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> * improvement(azure-iot-mqtt-base): add timeouts to publishes that have… (#818) * improvement(azure-iot-mqtt-base): add timeouts to publishes that have not been PUBACKed by the service 744 * update classes and unique identifiers. * chore: create config.yml for issue templates (#823) * chore: create config.yml for issue templates * chore: update technical question for msft q&a * fix: add vanity link for IoT help * chore: update technical question options * fix: add https:// * fix: add https:// * fix: add https:// * fix: add https:// Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> * feat(azure-iot-device): adds emit to connect (#819) 'connect' is emitted whenever the device transport FSM enters the "connected" state for MQTT, and "authenticated" for AMQP. * fix(azure-iot-device): lint error on simple sample (#826) * fix(azure-iot-device): lint error on simple sample * fix(azure-iot-device): add sample linting to the CI * refactor(multiple): update to typescript 3.7.5 move to dist instead of lib parameter checking and suppression (#824) * chore: updating docs to clarify edge support for linux only * refactor(multiple): update to typescript 3.7.5 move to dist etc (#830) * chore: node pnp sample for summer * chore: update prov sample to use env variables (#831) * chore: node pnp sample for summer * refactor(multiple): update to typescript 3.7.5 move to dist vs lib other minor (#833) * chore: node pnp sample for summer * chore: rename digital-twin-model-id to model-id in mqtt (#829) * chore: node pnp sample for summer * chore: node pnp sample for summer * chore: initial addition of pnp simple thermostat sample (#827) * chore: node pnp sample for summer * release(2020-07-06): bump package versions (#838) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * chore: fixing the sample for feedback (#839) * chore: remove writable property in reported (#842) * chore: some changes * chore: some changes * chore: some changes * Update pnpTemperatureController.js * Updated file upload sample to reflect current SDK changes. (#834) * fix(sample): update sample to use current SDK changes * fix(sample): update to use latest SDK changes, add use strict * fix(sample): update sample to use current SDK changes, fix linting issue * Update upload_to_blob_advanced.js * Update upload_to_blob_advanced.js Co-authored-by: Chandler Lattin <chlattin@microsoft.com> Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@microsoft.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@gmail.com> * chore: align environment variable names * Update pnpTemperatureController.js * chore: removing all the lib folders in repo Co-authored-by: Anthony Ercolano <toercola@microsoft.com> Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@microsoft.com> Co-authored-by: Elena Horton <52430760+elhorton@users.noreply.github.com> Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> Co-authored-by: Justin Hutchings <jhutchings1@users.noreply.github.com> Co-authored-by: olivakar <oliva.kar@microsoft.com> Co-authored-by: olivakar <oliva.tanusree@gmail.com> Co-authored-by: Chandler Lattin <chandlerlattin@knights.ucf.edu> Co-authored-by: Chandler Lattin <chlattin@microsoft.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@gmail.com>
* fix(azure-iothub): fix signatue for getTwin, updateTwin, updateModuleTwin to use Twin fix #673 * improvement(provisioning samples): use the results of the registration to create and open device * test(azure-iot-device-mqtt): reformat _mqtt_test.js (#741) * (chore) add issue templates workflow * Delete ISSUE_TEMPLATE.md * Update bug-report.md * fix(azure-iot-mqtt-base): forceReconnect for disconnecting hang in mqtt-base (#770) * release(2020-04-24): bump package versions (#771) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * refactor: update to mqtt.js v4 (#772) * build: update to mqtt.js v4 * refactor: add debug logs * fix: eslint issue * chore: remove network_e2e directory - no longer used (#775) * refactor: expose connection error in mqtt (#776) * release(2020-05-07): bump package versions (#788) * release(2020-05-07): bump package versions Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * refactor(multipe packages): c2d states no longer using booleans (#797) This moves the logic of checking if C2D is enabled down to the transport level, since it is not necessarily accurate to represent it at the device client level. There is not enough information at that level to make totally accurate judgements of if it is connected or not. * chore(azure-iot-device-amqp): debug logs for c2d (#804) * build: update to mqtt.js v4 * chore: add debug logs * chore(azure-iot-device): updating api version to support twin arrays (#806) * improvement(azure-iot-mqtt-base): maintain knowledge of on the wire publishes (#808) By tracking the on the wire publishes we can reliably complete in case of disconnects or other errors. * feat(azure-iot-mqtt-device): modelID option (#809) This adds the setOption for ModelID, which will enable users to use the existing device client library as a PnP library. To accomodate the lack of support in the existing service API, a switching API call has been added that will use the preview API version if the modelID is set. * release(2020-05-28): bump package versions (#810) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * Create synctodevops.yml * chore(azure-iot-provisioning-device): update samples to use env var (#816) * Add CodeQL security scanning (#815) Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> * improvement(azure-iot-mqtt-base): add timeouts to publishes that have… (#818) * improvement(azure-iot-mqtt-base): add timeouts to publishes that have not been PUBACKed by the service 744 * update classes and unique identifiers. * chore: create config.yml for issue templates (#823) * chore: create config.yml for issue templates * chore: update technical question for msft q&a * fix: add vanity link for IoT help * chore: update technical question options * fix: add https:// * fix: add https:// * fix: add https:// * fix: add https:// Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> * feat(azure-iot-device): adds emit to connect (#819) 'connect' is emitted whenever the device transport FSM enters the "connected" state for MQTT, and "authenticated" for AMQP. * fix(azure-iot-device): lint error on simple sample (#826) * fix(azure-iot-device): lint error on simple sample * fix(azure-iot-device): add sample linting to the CI * refactor(multiple): update to typescript 3.7.5 move to dist instead of lib parameter checking and suppression (#824) * chore: updating docs to clarify edge support for linux only * refactor(multiple): update to typescript 3.7.5 move to dist etc (#830) * chore: node pnp sample for summer * chore: update prov sample to use env variables (#831) * chore: node pnp sample for summer * refactor(multiple): update to typescript 3.7.5 move to dist vs lib other minor (#833) * chore: node pnp sample for summer * chore: rename digital-twin-model-id to model-id in mqtt (#829) * chore: node pnp sample for summer * chore: node pnp sample for summer * chore: initial addition of pnp simple thermostat sample (#827) * chore: node pnp sample for summer * release(2020-07-06): bump package versions (#838) Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> * chore: fixing the sample for feedback (#839) * chore: remove writable property in reported (#842) * chore: some changes * chore: some changes * chore: some changes * Update pnpTemperatureController.js * Updated file upload sample to reflect current SDK changes. (#834) * fix(sample): update sample to use current SDK changes * fix(sample): update to use latest SDK changes, add use strict * fix(sample): update sample to use current SDK changes, fix linting issue * Update upload_to_blob_advanced.js * Update upload_to_blob_advanced.js Co-authored-by: Chandler Lattin <chlattin@microsoft.com> Co-authored-by: Anthony V. Ercolano <anthonyvercolano@users.noreply.github.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@microsoft.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@gmail.com> * chore: align environment variable names * Update pnpTemperatureController.js * chore: removing all the lib folders in repo * chore: removing a few more lib folders * chore: updating twin calls to the pnp api-version * chore: adding modelId object to twin * chore: fixing registry sample * fix(azure-iothub): update vesion and support modelId service side Updated to -pnp-refresh.4. Fixed the sample to print out the modelId. Updated various dependents to the latest branch. Co-authored-by: Yoseph Maguire <yoseph.maguire@microsoft.com> Co-authored-by: Elena Horton <52430760+elhorton@users.noreply.github.com> Co-authored-by: Azure IoT Client Build <aziotclb@microsoft.com> Co-authored-by: Jelani Brandon <jelani.brandon@microsoft.com> Co-authored-by: Justin Hutchings <jhutchings1@users.noreply.github.com> Co-authored-by: olivakar <oliva.kar@microsoft.com> Co-authored-by: olivakar <oliva.tanusree@gmail.com> Co-authored-by: Chandler Lattin <chandlerlattin@knights.ucf.edu> Co-authored-by: Chandler Lattin <chlattin@microsoft.com> Co-authored-by: Yoseph Maguire <yoseph.maguire@gmail.com> Co-authored-by: Jelani Brandon <jelanibrandon@gmail.com>
No description provided.