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

fix(ktabledata): fetcher cache key should respect fetcher params #2531

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/components/KTableData/KTableData.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -709,12 +709,13 @@ describe('KTableData', () => {
cy.get('.table tbody').find('tr').should('have.length', 2)
cy.get('.table tbody').should('contain.text', 'row10')
cy.get('@fetcher')
.should('have.callCount', 3)
// TODO: Investigate why fetcher is called twice here
.should('have.callCount', 4)
.its('lastCall')
.should('have.been.calledWith', { pageSize: 10, page: 2, offset: '10', query: '', sortColumnKey: '', sortColumnOrder: 'desc' })
.then(() => cy.wrap(Cypress.vueWrapper.setProps({ fetcherCacheKey: '2' }))) // manually trigger refetch
.get('@fetcher')
.should('have.callCount', 4)
.should('have.callCount', 5)
.its('lastCall')
.should('have.been.calledWith', { pageSize: 10, page: 2, offset: '10', query: '', sortColumnKey: '', sortColumnOrder: 'desc' })
})
Expand Down Expand Up @@ -767,19 +768,20 @@ describe('KTableData', () => {
cy.get('.table tbody').find('tr').should('have.length', 2)
cy.get('.table tbody').should('contain.text', 'row10')
cy.get('@fetcher')
.should('have.callCount', 3)
// TODO: Investigate why fetcher is called twice here
Copy link
Contributor

Choose a reason for hiding this comment

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

I did some debugging and it turns out when switching to next page, besides the request fired by swrv triggered by the change of fetcherParams, this line watch([query, page, pageSize], async (newData, oldData) => in KTableData already implements the debounced refetch strategy when any of query, page, pageSize is changing. I think you can either exclude these params from identifierKey or remove the current watcher of these params by replacing its functionality with swrv

.should('have.callCount', 4)
.its('lastCall')
.should('have.been.calledWith', { pageSize: 10, page: 2, offset: null, query: '', sortColumnKey: '', sortColumnOrder: 'desc' })
.then(() => cy.wrap(Cypress.vueWrapper.setProps({ fetcherCacheKey: '2' }))) // manually trigger refetch
.get('@fetcher')
.should('have.callCount', 4)
.should('have.callCount', 5)
.its('lastCall')
.should('have.been.calledWith', { pageSize: 10, page: 2, offset: null, query: '', sortColumnKey: '', sortColumnOrder: 'desc' })
})
})

describe('misc', () => {
it('triggers the internal search and revalidate after clearing the search input', () => {
it('triggers the internal search and show cached results after clearing the search input', () => {
const fns = {
fetcher: ({ query }: { query: string }) => {
return { data: [{ query }] }
Expand Down Expand Up @@ -815,10 +817,9 @@ describe('KTableData', () => {
.should('returned', { data: [{ query: 'some-keyword' }] })
.then(() => cy.wrap(Cypress.vueWrapper.setProps({ searchInput: '' })))

// fetcher should be called immediately (< 350ms for search func)
cy.get('@fetcher', { timeout: 350 })
.should('have.callCount', 3) // fetcher's 3rd call
.should('returned', { data: [{ query: '' }] })
// fetcher should not be called as this state is already cached
cy.get('@fetcher', { timeout: 1000 })
.should('have.callCount', 2) // fetcher's 3rd call
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.should('have.callCount', 2) // fetcher's 3rd call
.should('have.callCount', 2) // fetcher's 2nd call

})
})
})
23 changes: 14 additions & 9 deletions src/components/KTableData/KTableData.vue
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,18 @@ const getCellSlots = computed((): string[] => {
return Object.keys(slots).filter((slot) => tableHeaders.value.some((header) => header.key === slot))
})

const fetcherParams = computed(() => ({
pageSize: pageSize.value,
page: page.value,
query: props.searchInput || filterQuery.value,
sortColumnKey: sortColumnKey.value,
sortColumnOrder: sortColumnOrder.value,
offset: offset.value,
}))

const isInitialFetch = ref<boolean>(true)
const fetchData = async () => {
// @ts-ignore - fetcher is required and will always be defined
const res = await props.fetcher({
pageSize: pageSize.value,
page: page.value,
query: props.searchInput || filterQuery.value,
sortColumnKey: sortColumnKey.value,
sortColumnOrder: sortColumnOrder.value,
offset: offset.value,
})
const res = await props.fetcher(fetcherParams.value)
tableData.value = res.data as Record<string, any>[]
total.value = props.paginationAttributes?.totalCount || res.total || res.data?.length || 0

Expand Down Expand Up @@ -389,6 +390,8 @@ const tableFetcherCacheKey = computed((): string => {
identifierKey = props.cacheIdentifier
}

identifierKey += `-${JSON.stringify(fetcherParams.value)}`

if (props.fetcherCacheKey) {
identifierKey += `-${props.fetcherCacheKey}`
}
Expand Down Expand Up @@ -551,6 +554,8 @@ watch([stateData, tableState], (newState) => {
state: newTableState,
hasData: newStateData.hasData,
})

console.log(state, tableFetcherCacheKey.value)
})

// handles debounce of search query
Expand Down