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

feat(azure-iot-device): adds emit to connect #819

Merged
merged 8 commits into from
Jun 24, 2020

Conversation

YoDaMa
Copy link
Contributor

@YoDaMa YoDaMa commented Jun 10, 2020

No description provided.

// MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message.
});
async function disconnectHandler () {
clearInterval(sendInterval);
Copy link
Contributor

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);
Copy link
Contributor

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.

Copy link
Contributor

@anthonyvercolano anthonyvercolano left a 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'));
Copy link
Member

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.

  1. 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 the setDisconnectHandler callback gets called.

Then, in the client:

  1. 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.

  2. 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.

Copy link
Contributor

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)

@YoDaMa
Copy link
Contributor Author

YoDaMa commented Jun 23, 2020

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

  1. As it relates to this PR, I do not want to touch disconnect. I think that is another PR if we are to reconsider how the event invocation operates. As such for this PR I'm inclined to box up your comments and move them into a conversation about reworking disconnect in another PR. I hope you are ok with this logic. I'm disinclined toward creating large, expansive PRs that have multiple goals :) simple is better.

  2. connect event.

@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 connect should be emitted to the user?

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 connect event. We would also have to make sure if we do start getting clever that we document the h*ll out of how it works. We can do that! But historically documentation falls apart... intuitive APIs seem like the best choice.

Finally, @anthonyvercolano, ur comment:

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?

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 disconnect/connect cycle, then the connect event will not be emitted.

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)

@BertKleewein
Copy link
Member

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 :))

@YoDaMa
Copy link
Contributor Author

YoDaMa commented Jun 23, 2020

@BertKleewein

Disconnect/reconnect because of SAS renewal? My intuition says to shield the user from this, but I'm not sure.

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 connected seems to match the intuitive way a connect event would function.

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".

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');
Copy link
Contributor

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?

@anthonyvercolano
Copy link
Contributor

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.

Copy link
Contributor

@anthonyvercolano anthonyvercolano left a comment

Choose a reason for hiding this comment

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

:shipit:

@YoDaMa YoDaMa merged commit 9713b2f into Azure:master Jun 24, 2020
@YoDaMa YoDaMa deleted the connect_event branch June 24, 2020 20:45
jebrando added a commit that referenced this pull request Jul 20, 2020
* 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>
anthonyvercolano added a commit that referenced this pull request Jul 27, 2020
* 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>
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.

3 participants