openwallet-foundation / credo-ts

Typescript framework for building decentralized identity and verifiable credential solutions
https://credo.js.org
Apache License 2.0
273 stars 200 forks source link

Connection state is stuck at "Requested". #599

Closed afrisalyp closed 9 months ago

afrisalyp commented 2 years ago

Hi,

We're building a React Native app based on the AFJ framework.

Generally, after first install, the connection invitation flow works properly. We test by scanning QR Invitation from Trinsic organization, the device is listed in the Trinsic web and the record state is changed from Invited into Requested then to Responded.

But after some points, the functionality doesn't work anymore. Accepting the invitation (agent.connections.acceptInvitation(id)) is stuck at Requested while the device is actually added in the Trinsic web. The app is also not able to receive credential offers.

Has anyone experienced and has solution for this problem?

afrisalyp commented 2 years ago

It seems the app doesn't receive any message anymore from the mediator via websocket connection.

This reconnecting mechanism seems not working on react native.

https://github.com/hyperledger/aries-framework-javascript/blob/v0.1.0/packages/core/src/modules/routing/RecipientModule.ts#L132

Also, there is no event received to notify that the websocket is closed.

agent.events.on<OutboundWebSocketClosedEvent>(
  TransportEventTypes.OutboundWebSocketClosedEvent,
  event => {
    console.log(event);
  }
);
TimoGlastra commented 2 years ago

Thanks for opening this issue @afrisalyp!

What mediator are you using? Is it an ACA-Py mediator? What are you using in the startup config for MediatorPickupStrategy? Have you set up the web socket outbound transport on the mobile agnet?

standlove commented 2 years ago

Here is our code to initialize the agent. We are using the public indiciotech mediator http://mediator3.test.indiciotech.io:3000, and use MediatorPickupStrategy.Implicit in startup config. @TimoGlastra

const initAgent = async () => {
    if (agent && agent.isInitialized) {
      await agent.shutdown();
    }
    const newAgent = new Agent(
      {
        indyLedgers:
          Config.MULTIPLE_LEDGERS === 'true'
            ? indyLedgersNetworks
            : [indyLedgersNetworks[selectedNetwork]],
        label: walletName || getDeviceNameSync(),
        mediatorConnectionsInvite: MEDIATOR_URL,
        mediatorPickupStrategy: MediatorPickupStrategy.Implicit,
        walletConfig: {id: 'di-wallet', key: 'kj65fd'},
        autoAcceptCredentials: AutoAcceptCredential.ContentApproved,
        logger: new ConsoleLogger(LogLevel.trace),
        useLegacyDidSovPrefix: true,
      },
      agentDependencies,
    );

    const wsTransport = new WsOutboundTransport();
    const httpTransport = new HttpOutboundTransport();

    newAgent.registerOutboundTransport(wsTransport);
    newAgent.registerOutboundTransport(httpTransport);

    await newAgent.initialize();
TimoGlastra commented 2 years ago

Which version of AFJ are you using?

standlove commented 2 years ago

we are using 0.1.0

"@aries-framework/core": "0.1.0",
"@aries-framework/react-hooks": "^0.1.2",
"@aries-framework/react-native": "0.1.0",
standlove commented 2 years ago

We are still experience this ...

Is there any workaround for this? e.g. send a new request to get the updates?

@TimoGlastra Thanks

TimoGlastra commented 2 years ago

Can you create a repo that reproduces this issue?

standlove commented 2 years ago

This cannot be reproduced consistently, it only happens intermittently ...

And does the protocol expects the messages are always delivered successful between the mobile app and the mediator server? What if some messages are not received in the mobile app, is there any fallback plan?

Thanks.

@TimoGlastra

TimoGlastra commented 2 years ago

If you reopen the application, will it be able to finish the connection afterwards? Is it a connection issue with the mediator, or are the actually messages getting lost?

standlove commented 2 years ago

That particular connection stays in connecting state even after re-open the application.

Looks the websocket connection is fine, as I still see many messages sent and received successfully. It's likely the message is lost ... but how does this happen? and what to do in this case?

Thanks.

@TimoGlastra

standlove commented 2 years ago

Hi, @TimoGlastra

Do you think it's a mediator server configuration issue?

Thanks

itsdheerajbudhiraja commented 2 years ago

Hi @standlove , Did you found any solution to this problem?

I am also facing this similar issue and inconsistency in AFJ 2.0 - With AFJ 1.0 it was working fine for me but After upgrading framework and stress testing App, I am facing this.

Connection fails intermittently - Payload is received from mediator but not processed by Agent message subscription.

After that all messages from mediator remain unprocessed for some time until ws restarts or App is forced stop and restart.

swcurran commented 2 years ago

I'm wondering if this is related to this PR/issue that @dbluhm opened against ACA-Py -- https://github.com/hyperledger/aries-cloudagent-python/pull/1851. Given the intermittent nature of what you are seeing, it's possible this is the issue. The Indicio Mediator is built on ACA-Py.

itsdheerajbudhiraja commented 2 years ago

@swcurran Great PR, I will test this PR as mediator and will try to see if connection issue still persist.

TimoGlastra commented 2 years ago

Thanks for this insight @swcurran. @itsdheerajbudhiraja & @standlove I just ran into this issue myself since a few days when I started connecting two mobile devices instead of a cloud agent to a mobile device. What I think might the issue here is that when connecting with a cloud agent you're using return routing for creating the connection so there's less of a race condition (as there's more time to process). When connecting two mobile devices the mediator will be used immediately, which means there may not be enough time to register the key. Just guessing here.

@itsdheerajbudhiraja @standlove to verify, are you trying to connect two mobile devices?

I'll make sure to also update AFJ to wait for the keylist update response, that's a great find @dbluhm! 👍

TimoGlastra commented 2 years ago

After looking at the mediation implementation in AFJ it is already waiting for the response, so that can't be the cause here. As the client determines whether to wait and AFJ does wait I don't think this is related to @dbluhm fix's after all

itsdheerajbudhiraja commented 2 years ago

@TimoGlastra The exact issue which I am facing right now is - Asynchronously errors are being thrown by AFJ in react native env.

When autoAcceptInvitation is enabled - [AriesFrameworkError: Connection record is in invalid state response-received. Valid states are: response-sent.] (State is changing to response-sent before auto accept invitation flow even executes)

This is crashing the connection flow and connection is not reaching to completed state.

Is it because same message is received from mediator multiple times?

Can it be the possibility - AFJ is adding connection record into storage as response-received earlier than mediator message is received?

In release mode this error thrown is crashing the app also, Hence now we are integrating some global error handler to catch async errors - As this is not simply catched in try-catch.

genaris commented 2 years ago

@TimoGlastra The exact issue which I am facing right now is - Asynchronously errors are being thrown by AFJ in react native env.

When autoAcceptInvitation is enabled - [AriesFrameworkError: Connection record is in invalid state response-received. Valid states are: response-sent.] (State is changing to response-sent before auto accept invitation flow even executes)

This is crashing the connection flow and connection is not reaching to completed state.

Is it because same message is received from mediator multiple times?

Can it be the possibility - AFJ is adding connection record into storage as response-received earlier than mediator message is received?

In release mode this error thrown is crashing the app also, Hence now we are integrating some global error handler to catch async errors - As this is not simply catched in try-catch.

We were experiencing similar issues, with React Native in particular (especially when using real mobile devices). I was blaming our code or AFJ's mediator socket handling (as we are using AFJ in both sides), but it seems that it's something on the client/mediatee side. And it's worth noting that we don't have this problem with agents based in NodeJS.

BTW @itsdheerajbudhiraja what's the global error handler are you using in React Native? It could help us to better catch this error and improve debugging.

itsdheerajbudhiraja commented 2 years ago

@genaris I used react-native-exception-handler to handle app crashes for now. https://www.npmjs.com/package/react-native-exception-handler

But connection once failed will remain failed - And after connection similar issues are faced in Credentials issuance also.

I tries NodeJS env - Working without issues. So hard to say issue in AFJ framework. But at same time there is nothing much we can do in react-native. We are calling same function of framework as in nodeJS test (Same mediator I used). So mediator doesn;t seems to be an issue @swcurran .

TimoGlastra commented 9 months ago

Closing due to inactivity. If there's any issues you're still running into please open a new issue with a more recent version