aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Hub listener datastore networkStatus event isn't triggered on Chrome, but is on Firefox. #9035

Closed duckbytes closed 2 years ago

duckbytes commented 2 years ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

DataStore

Amplify Categories

api

Environment information

``` # Put output below this line System: OS: Linux 5.14 Arch Linux CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz Memory: 827.50 MB / 15.35 GB Container: Yes Shell: 5.8 - /bin/zsh Binaries: Node: 16.11.1 - /usr/bin/node Yarn: 1.22.15 - /usr/bin/yarn npm: 8.0.0 - /usr/bin/npm Browsers: Firefox: 93.0 npmPackages: @aws-amplify/ui-react: ^1.2.11 => 1.2.11 @date-io/date-fns: ^2.11.0 => 2.11.0 (1.1.0) @date-io/moment: ^2.11.0 => 2.11.0 @emotion/react: ^11.4.1 => 11.4.1 @emotion/styled: ^11.3.0 => 11.3.0 @mui/icons-material: ^5.0.3 => 5.0.3 @mui/lab: ^5.0.0-alpha.50 => 5.0.0-alpha.50 @mui/material: ^5.0.3 => 5.0.3 @mui/styled-engine-sc: ^5.0.3 => 5.0.3 @reduxjs/toolkit: ^1.6.1 => 1.6.1 @reduxjs/toolkit-query: 1.0.0 @reduxjs/toolkit-query-react: 1.0.0 @testing-library/jest-dom: ^5.11.4 => 5.14.1 @testing-library/react: ^11.1.0 => 11.2.7 @testing-library/user-event: ^12.1.10 => 12.8.3 autosuggest-highlight: ^3.1.1 => 3.1.1 aws-amplify: ^4.2.5 => 4.3.2 axios: ^0.21.1 => 0.21.4 date-fns: ^2.23.0 => 2.25.0 (2.0.0-alpha.27) downshift: ^6.1.7 => 6.1.7 framer-motion: ^4.1.17 => 4.1.17 immutability-helper: ^3.1.1 => 3.1.1 libphonenumber-js: ^1.9.25 => 1.9.25 libphonenumber-js-core: 1.0.0 libphonenumber-js-max: 1.0.0 libphonenumber-js-min: 1.0.0 libphonenumber-js-mobile: 1.0.0 lodash: ^4.17.21 => 4.17.21 (3.10.1) match-sorter: ^6.3.0 => 6.3.0 material-table: ^1.69.3 => 1.69.3 moment: ^2.29.1 => 2.29.1 moment-timezone: ^0.5.33 => 0.5.33 notistack: ^1.0.10 => 1.0.10 prop-types: ^15.7.2 => 15.7.2 (15.6.2) react: ^17.0.2 => 17.0.2 react-cropper: ^2.1.8 => 2.1.8 react-dom: ^17.0.2 => 17.0.2 react-helmet: ^6.1.0 => 6.1.0 react-idle-timer: ^4.6.4 => 4.6.4 react-linkify: ^1.0.0-alpha => 1.0.0-alpha react-moment: ^1.1.1 => 1.1.1 react-notifications-component: ^3.1.0 => 3.1.0 react-redux: ^7.2.4 => 7.2.4 react-router: ^5.2.0 => 5.2.0 react-router-dom: ^5.2.0 => 5.2.0 react-scripts: ^4.0.3 => 4.0.3 react-waypoint: ^10.1.0 => 10.1.0 redux: ^4.1.1 => 4.1.1 redux-saga: ^1.1.3 => 1.1.3 redux-saga/effects: undefined () redux-toolkit: ^1.1.2 => 1.1.2 seedrandom: ^3.0.5 => 3.0.5 socket.io-client: ^4.1.3 => 4.1.3 styled-components: ^5.3.1 => 5.3.1 styled-components/macro: undefined () styled-components/native: undefined () styled-components/primitives: undefined () typeface-roboto: ^1.1.13 => 1.1.13 uuid: ^8.3.2 => 8.3.2 (3.4.0, 3.3.2) uuid-base62: ^0.1.0 => 0.1.0 web-vitals: ^1.0.1 => 1.1.2 npmGlobalPackages: @aws-amplify/cli: 5.2.1 acorn: 8.5.0 asar: 3.1.0 eslint: 8.0.1 graphql-language-service-cli: 3.1.13 node-gyp: 8.2.0 nopt: 5.0.0 npm: 8.0.0 semver: 7.3.5 serve: 12.0.1 yarn: 1.22.15 ```

Describe the bug

When listening for datastore events with Hub.listen, the networkStatus event is never emitted even if the user goes offline or online. This problem happens using Chrome or Edge, but in Firefox it works fine.

I am using redux-saga and a channel to monitor network status.

Expected behavior

When the user goes offline I expect a networkStatus event to be emitted from Hub.listen.

Reproduction steps

Code Snippet

// Put your code below this line.
import * as actions from "./awsHubListenerActions";
import { takeLatest } from "@redux-saga/core/effects";
import { Hub } from "aws-amplify";
import { call, take, put } from "redux-saga/effects";
import { eventChannel } from "redux-saga";

function listener() {
    return eventChannel((emitter) => {
        const listener = Hub.listen("datastore", async (hubData) => {
            emitter(hubData);
        });
        return () => {
            listener();
        };
    });
}
function* initialiseDataStoreListener(action) {
    const channel = yield call(listener);
    try {
        while (true) {
            const hubData = yield take(channel);
            const { event, data } = hubData.payload;
            if (event === "networkStatus") {
                yield put(actions.setNetworkStatus(data.active));
                console.log(`User has a network connection: ${data.active}`);
             }
        }
    } finally {
        console.log("stop DataStore listener");
    }
}

export function* watchInitialiseDataStoreListener() {
    yield takeLatest(
        actions.initialiseAwsDataStoreListenerAction,
        initialiseDataStoreListener
    );
}

Log output

``` // Put your logs below this line ​// On Chrome there is no output at all from DEBUG // On Firefox this is the DEBUG output [DEBUG] 21:28.365 Hub - Dispatching to datastore with Object { event: "networkStatus", data: {…} } ConsoleLogger.ts:125 User has a network connection: false awsHubListenerSagas.js:35 [DEBUG] 21:29.376 AWSAppSyncRealTimeProvider - closing WebSocket... ConsoleLogger.ts:115 ```

aws-exports.js

/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "eu-west-1",
    "aws_cognito_identity_pool_id": "eu-west-1:58cf357f-88c4-401a-8f62-5fe23f393b22",
    "aws_cognito_region": "eu-west-1",
    "aws_user_pools_id": "eu-west-1_idpa4Q7kv",
    "aws_user_pools_web_client_id": "7aaqfpqu7vjp997ihqosdno4io",
    "oauth": {},
    "aws_appsync_graphqlEndpoint": "https://euhguoft5fae5fztl2yckpt4eu.appsync-api.eu-west-1.amazonaws.com/graphql",
    "aws_appsync_region": "eu-west-1",
    "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
    "aws_appsync_apiKey": "****"
};

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

chrisbonifacio commented 2 years ago

Hi @duckbytes 👋 thanks for raising this issue. Unfortunately, I was not able to reproduce this behavior on the latest version of aws-amplify on Chrome or Edge. Both worked as well as Firefox. Are you still experiencing this behavior?

code

  const [todos, setTodos] = useState([]);

  async function fetchTodos() {
    try {
      const todos = await DataStore.query(Todo);

      setTodos(todos);
    } catch (error) {
      console.log(error);
    }
  }

  useEffect(() => {
    const dataStoreListener = async (capsule) => {
      const { channel, payload, source } = capsule;

      console.log({ channel, payload, source });
    };

    Hub.listen("datastore", dataStoreListener);

    fetchTodos();

    return () => Hub.remove("datastore", dataStoreListener);
  }, []);

Edge

Screen Shot 2022-03-29 at 12 37 08 PM

Chrome

Screen Shot 2022-03-29 at 12 34 02 PM

Firefox

Screen Shot 2022-03-29 at 12 35 12 PM
duckbytes commented 2 years ago

Hi @chrisbonifacio

I put together a minimal reproduction in React:

import "./App.css";
import Amplify, { DataStore, Hub } from "aws-amplify";
import { withAuthenticator } from "@aws-amplify/ui-react";
import { useEffect } from "react";
import { useState } from "react";
import awsconfig from "./aws-exports";
import * as models from "./models";

Amplify.configure(awsconfig);

function App() {
  const [message, setMessage] = useState("unknown");
  useEffect(() => {
    DataStore.start();
    Hub.listen("datastore", (hubData) => {
      const { event, data } = hubData.payload;
      console.log("datastore event", data, event);
      if (event === "networkStatus") {
        const result = data.active ? "online" : "offline";
        setMessage(`User is ${result}`);
      }
    });
  }, []);

  return <div className="App">{message}</div>;
}

export default withAuthenticator(App);

and published it for more testing. It looks like the problem is platform specific.

With Chrome on macOS and Windows the message changes to "User is offline" as expected when the network interface is disabled. On Linux and Android the message initially says "User is online" but does not change to offline when the interface is disabled or airplane mode is enabled. An initial online event is sent but not offline events. I couldn't test on iOS.

It would be helpful for this to work at least on Android devices as I'd like to distribute it as a PWA and let the user know when they have lost their connection.

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server amplify-help forum.