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

GraphQL does not retrieve all items #12668

Closed rexwreyes closed 7 months ago

rexwreyes commented 9 months ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

GraphQL API

Amplify Categories

api

Environment information

# Put output below this line System: OS: macOS 13.6.1 CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz Memory: 1.26 GB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 18.17.1 - /usr/local/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 9.6.7 - /usr/local/bin/npm Browsers: Chrome: 119.0.6045.199 Firefox: 118.0.2 Safari: 17.1 npmPackages: @aws-amplify/ui-react: ^0.0.0-next-8dddcc3-20220916215824 => 0.0.0-next-8dddcc3-20220916215824 @aws-amplify/ui-react-internal: undefined () @aws-amplify/ui-react-legacy: undefined () @emotion/react: ^11.11.1 => 11.11.1 @emotion/styled: ^11.11.0 => 11.11.0 @mui/icons-material: ^5.14.0 => 5.14.0 @mui/material: ^5.14.0 => 5.14.0 @tanstack/react-query: ^4.29.23 => 4.29.23 @wojtekmaj/react-timerange-picker: ^3.5.0 => 3.5.0 aws-amplify: ^4.3.17 => 4.3.35 aws-sdk: ^2.1216.0 => 2.1218.0 axios: ^0.27.2 => 0.27.2 (0.26.0) bootstrap: ^5.1.3 => 5.2.1 lodash: ^4.17.21 => 4.17.21 material-react-table: ^1.14.0 => 1.14.0 mdb-react-admin-templates: 1.6.0 mdb-react-ui-kit: git+https://oauth2:NsCbBPtxFB22-bfPZojx@git.mdbootstrap.com/mdb/react/mdb5/prd/mdb5-react-ui-kit-pro-advanced => 4.2.0 moment: ^2.29.2 => 2.29.4 react: ^18.2.0 => 18.2.0 (18.1.0) react-bootstrap: ^2.2.1 => 2.5.0 react-bootstrap/AbstractModalHeader: undefined () react-bootstrap/Accordion: undefined () react-bootstrap/AccordionBody: undefined () react-bootstrap/AccordionButton: undefined () react-bootstrap/AccordionCollapse: undefined () react-bootstrap/AccordionContext: undefined () react-bootstrap/AccordionHeader: undefined () react-bootstrap/AccordionItem: undefined () react-bootstrap/AccordionItemContext: undefined () react-bootstrap/Alert: undefined () react-bootstrap/Anchor: undefined () react-bootstrap/Badge: undefined () react-bootstrap/BootstrapModalManager: undefined () react-bootstrap/Breadcrumb: undefined () react-bootstrap/BreadcrumbItem: undefined () react-bootstrap/Button: undefined () react-bootstrap/ButtonGroup: undefined () react-bootstrap/ButtonToolbar: undefined () react-bootstrap/Card: undefined () react-bootstrap/CardGroup: undefined () react-bootstrap/CardHeader: undefined () react-bootstrap/CardHeaderContext: undefined () react-bootstrap/CardImg: undefined () react-bootstrap/Carousel: undefined () react-bootstrap/CarouselCaption: undefined () react-bootstrap/CarouselItem: undefined () react-bootstrap/CloseButton: undefined () react-bootstrap/Col: undefined () react-bootstrap/Collapse: undefined () react-bootstrap/Container: undefined () react-bootstrap/Dropdown: undefined () react-bootstrap/DropdownButton: undefined () react-bootstrap/DropdownContext: undefined () react-bootstrap/DropdownItem: undefined () react-bootstrap/DropdownMenu: undefined () react-bootstrap/DropdownToggle: undefined () react-bootstrap/ElementChildren: undefined () react-bootstrap/Fade: undefined () react-bootstrap/Feedback: undefined () react-bootstrap/Figure: undefined () react-bootstrap/FigureCaption: undefined () react-bootstrap/FigureImage: undefined () react-bootstrap/FloatingLabel: undefined () react-bootstrap/Form: undefined () react-bootstrap/FormCheck: undefined () react-bootstrap/FormCheckInput: undefined () react-bootstrap/FormCheckLabel: undefined () react-bootstrap/FormContext: undefined () react-bootstrap/FormControl: undefined () react-bootstrap/FormFloating: undefined () react-bootstrap/FormGroup: undefined () react-bootstrap/FormLabel: undefined () react-bootstrap/FormRange: undefined () react-bootstrap/FormSelect: undefined () react-bootstrap/FormText: undefined () react-bootstrap/Image: undefined () react-bootstrap/InputGroup: undefined () react-bootstrap/InputGroupContext: undefined () react-bootstrap/ListGroup: undefined () react-bootstrap/ListGroupItem: undefined () react-bootstrap/Modal: undefined () react-bootstrap/ModalBody: undefined () react-bootstrap/ModalContext: undefined () react-bootstrap/ModalDialog: undefined () react-bootstrap/ModalFooter: undefined () react-bootstrap/ModalHeader: undefined () react-bootstrap/ModalTitle: undefined () react-bootstrap/Nav: undefined () react-bootstrap/NavContext: undefined () react-bootstrap/NavDropdown: undefined () react-bootstrap/NavItem: undefined () react-bootstrap/NavLink: undefined () react-bootstrap/Navbar: undefined () react-bootstrap/NavbarBrand: undefined () react-bootstrap/NavbarCollapse: undefined () react-bootstrap/NavbarContext: undefined () react-bootstrap/NavbarOffcanvas: undefined () react-bootstrap/NavbarToggle: undefined () react-bootstrap/Offcanvas: undefined () react-bootstrap/OffcanvasBody: undefined () react-bootstrap/OffcanvasHeader: undefined () react-bootstrap/OffcanvasTitle: undefined () react-bootstrap/OffcanvasToggling: undefined () react-bootstrap/Overlay: undefined () react-bootstrap/OverlayTrigger: undefined () react-bootstrap/PageItem: undefined () react-bootstrap/Pagination: undefined () react-bootstrap/Placeholder: undefined () react-bootstrap/PlaceholderButton: undefined () react-bootstrap/Popover: undefined () react-bootstrap/PopoverBody: undefined () react-bootstrap/PopoverHeader: undefined () react-bootstrap/ProgressBar: undefined () react-bootstrap/Ratio: undefined () react-bootstrap/Row: undefined () react-bootstrap/SSRProvider: undefined () react-bootstrap/Spinner: undefined () react-bootstrap/SplitButton: undefined () react-bootstrap/Stack: undefined () react-bootstrap/Switch: undefined () react-bootstrap/Tab: undefined () react-bootstrap/TabContainer: undefined () react-bootstrap/TabContent: undefined () react-bootstrap/TabPane: undefined () react-bootstrap/Table: undefined () react-bootstrap/Tabs: undefined () react-bootstrap/ThemeProvider: undefined () react-bootstrap/Toast: undefined () react-bootstrap/ToastBody: undefined () react-bootstrap/ToastContainer: undefined () react-bootstrap/ToastContext: undefined () react-bootstrap/ToastFade: undefined () react-bootstrap/ToastHeader: undefined () react-bootstrap/ToggleButton: undefined () react-bootstrap/ToggleButtonGroup: undefined () react-bootstrap/Tooltip: undefined () react-bootstrap/TransitionWrapper: undefined () react-bootstrap/createChainedFunction: undefined () react-bootstrap/createUtilityClasses: undefined () react-bootstrap/createWithBsPrefix: undefined () react-bootstrap/divWithClassName: undefined () react-bootstrap/getTabTransitionComponent: undefined () react-bootstrap/helpers: undefined () react-bootstrap/safeFindDOMNode: undefined () react-bootstrap/transitionEndListener: undefined () react-bootstrap/triggerBrowserReflow: undefined () react-bootstrap/types: undefined () react-bootstrap/useOverlayOffset: undefined () react-bootstrap/usePlaceholder: undefined () react-bootstrap/useWrappedRefWithWarning: undefined () react-dom: ^18.2.0 => 18.2.0 react-redux: ^7.2.6 => 7.2.8 react-router-dom: ^6.2.2 => 6.4.0 react-scripts: 5.0.1 => 5.0.1 react-select: ^5.4.0 => 5.4.0 web-vitals: ^2.1.4 => 2.1.4 npmGlobalPackages: @aws-amplify/cli: 12.8.2 corepack: 0.18.0 n: 9.1.0 npm: 9.6.7

Describe the bug

I have a table with roughly 20K items. i do a graphQL call using nextToken and cant ever seem to get all the items. It seems like the most i can get are around half or 10K. This is using pagination and a limit of 100.

Expected behavior

To retrieve the data that im calling and know that it is there.

Reproduction steps

run the app

Code Snippet

// Put your code below this line.
  useEffect(() => {
        const fetch = async (load) => {
            setIsLoading(true)
            try {
                const variables = {
                    nextToken,
                    limit : 100, 
                }
                const result = await API.graphql({ query: queries.listAlerts, variables })
                setNextToken(result.data.listAlerts.nextToken)
                var alerts = result.data.listAlerts.items
                alerts = _.orderBy(alerts, ['createdAt'], ['desc'])
                var newLoad = pagination.loadedRows + alerts.length
                if (load === 1) {
                    setAlertData(alerts)
                } else {
                    setAlertData([...alertData, ...alerts])                
                }               
            } catch (err) {
                console.log(err)
            } finally {
                setIsLoading(false)
                setPagination({ ...pagination, pageIndex: paged, loadedRows: newLoad });
            }
        }
        var paged = pagination.pageIndex
        if (pagination.loadedRows === 0) {
            fetch(1)
            return
        } else if (pagination.pageIndex * pagination.pageSize + pagination.pageSize !== pagination.loadedRows) {
            return
        }
        fetch(0)
    }, [nextToken, pagination.pageIndex, pagination.pageSize])

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

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

rexwreyes commented 9 months ago

Maybe i did not post correctly? Anyway my issue is this:

I have a table with roughly 20K items. i do a graphQL call using nextToken and cant ever seem to get all the items. It seems like the most i can get are around half or 10K. This is using pagination and a limit of 100.

stocaaro commented 9 months ago

Reviewing your code, I think there are issues here around setting multiple useState's which are triggering parallel useEffect. It looks like isLoading is intended to work like a lock preventing multiple updates from happening in parallel, but I don't think it's enforced. Looking at this, I would expect setAlertData to be called in ways where data is overwritten / lost during the load process.

To fix this, I would recommend performing the load inside of a single useEffect run without anything in the dependency array. Something like the following.

function App() {
    const [alertData, setAlertData] = useState([]);

    useEffect(() => {
        const fetch = async (nextToken) => {
            const variables = {
                nextToken,
                limit : 100, 
            }
            return await API.graphql({ query: queries.listAlerts, variables });
        }

        const fetchAll = async () => {
            let result = await fetch(undefined);
            const allAlerts = [...result.data.listAlerts.items];
            setAlertData(allAlerts); // We can assign alerts incrementally to see updates during the load.
            while(result.data.listAlerts.nextToken) {
                result = await fetch(result.data.listAlerts.nextToken);
                allAlerts.push(...result.data.listAlerts.items);
                setAlertData(allAlerts);
            }
        }

    fetchAll();
    }, []);

    return <>...</>
}

Can you try this approach to the data loading and let us know if you are able to retrieve all of the data you expect to?

rexwreyes commented 9 months ago

ok but i get the same results using the AWS App Sync console.

chrisbonifacio commented 9 months ago

@rexwreyes in that case, this doesn't seem to be an Amplify library issue but I'd be curious to see how you're querying in the AppSync console.

Please provide reproduction steps and/or some example queries and responses that demonstrate where the cutoff seems to happen during pagination.

cwomack commented 9 months ago

@rexwreyes, just want to confirm that this is happening on v4.x of Amplify (and not more recent versions like v5 or v6) right? If so, do you have the ability to upgrade to v6 and let us know if the issue persists? Additionally, if we could see your schema and associated auth modes, that would be very helpful! Thanks.

rexwreyes commented 9 months ago

yes, sorry. this is on v4, but I don't have the option of updating it as the client can't afford all that work ATM.

I got to the point of figuring out that I can use a sortKey and the index it builds will get all the records.