Skip to content

Commit

Permalink
Merge pull request #1393 from edenia/perf/endpoints-page-speed-1383
Browse files Browse the repository at this point in the history
fix(webapp): improve page load speed for endpoints page
  • Loading branch information
xavier506 committed Nov 27, 2023
2 parents d687b9b + 1199e29 commit 2ebfbc7
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 37 deletions.
14 changes: 10 additions & 4 deletions webapp/src/gql/producer.gql.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ export const NODES_BY_PRODUCER_SUBSCRIPTION = gql`
}
`

export const NODES_SUBSCRIPTION = gql`
subscription ($offset: Int = 0, $limit: Int = 21, $where: producer_bool_exp) {
const NODES_OPERATION = type => gql`
${type} ($offset: Int = 0, $limit: Int = 21, $where: producer_bool_exp) {
producers: producer(
where: $where
limit: $limit
Expand Down Expand Up @@ -171,8 +171,11 @@ export const NODES_SUBSCRIPTION = gql`
}
`

export const ENDPOINTS_SUBSCRIPTION = gql`
subscription (
export const NODES_SUBSCRIPTION = NODES_OPERATION('subscription')
export const NODES_QUERY = NODES_OPERATION('query')

const ENDPOINTS_OPERATION = type => gql`
${type} (
$offset: Int = 0
$limit: Int = 21
$where: producer_bool_exp
Expand All @@ -198,6 +201,9 @@ export const ENDPOINTS_SUBSCRIPTION = gql`
}
`

export const ENDPOINTS_SUBSCRIPTION = ENDPOINTS_OPERATION('subscription')
export const ENDPOINTS_QUERY = ENDPOINTS_OPERATION('query')

export const NODE_CPU_BENCHMARK = gql`
query ($account: String) {
cpu(
Expand Down
56 changes: 39 additions & 17 deletions webapp/src/hooks/customHooks/useEndpointsState.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useState, useEffect, useCallback } from 'react'
import { useState, useEffect, useCallback, useRef } from 'react'
import { useSubscription, useLazyQuery } from '@apollo/client'

import { ENDPOINTS_SUBSCRIPTION, PRODUCERS_COUNT_QUERY } from '../../gql'
import {
ENDPOINTS_SUBSCRIPTION,
ENDPOINTS_QUERY,
PRODUCERS_COUNT_QUERY,
} from '../../gql'

import useSearchState from './useSearchState'

Expand All @@ -15,23 +19,11 @@ const useEndpointsState = () => {
nodes: { endpoints: { value: { _gt: '' } } },
},
}
const [variables, setVariables] = useState(defaultVariables)
const [loadProducers, { data: { info } = {} }] = useLazyQuery(PRODUCERS_COUNT_QUERY)
const { data, loading } = useSubscription(ENDPOINTS_SUBSCRIPTION, { variables })

const [items, setItems] = useState()
const [textLists, setTextLists] = useState()

const [
{ filters, pagination },
{ handleOnSearch, handleOnPageChange, setPagination },
] = useSearchState({
loadProducers,
info,
variables,
setVariables,
})

useEffect(() => {
const handleSubscriptionData = data => {
if (!data) return

const { newItems, workingEndpoints } = data.producers.reduce(
Expand Down Expand Up @@ -93,7 +85,37 @@ const useEndpointsState = () => {
return { ...state, [type]: endpointsList }
}, {}),
)
}, [data, info])
}

const isQueryExecuted = useRef(false)
const [loadProducers, { data: { info } = {} }] = useLazyQuery(PRODUCERS_COUNT_QUERY)
const [
{ filters, pagination, variables },
{ handleOnSearch, handleOnPageChange, setPagination },
] = useSearchState({
loadProducers,
info,
defaultVariables,
})
const { loading } = useSubscription(ENDPOINTS_SUBSCRIPTION, {
variables,
onSubscriptionData: ({ subscriptionData }) => {
handleSubscriptionData(subscriptionData.data)
},
})

const [loadEndpoints] = useLazyQuery(ENDPOINTS_QUERY, {
onCompleted: (data) => {
handleSubscriptionData(data)
},
})

useEffect(() => {
if (!variables || isQueryExecuted.current) return

loadEndpoints({ variables })
isQueryExecuted.current = true
}, [variables, loadEndpoints])

const handleFilter = useCallback(value => {
const filter = value
Expand Down
31 changes: 21 additions & 10 deletions webapp/src/hooks/customHooks/useNodeState.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useRef } from 'react'
import { useSubscription, useLazyQuery } from '@apollo/client'

import { NODES_SUBSCRIPTION, PRODUCERS_COUNT_QUERY } from '../../gql'
import {
NODES_SUBSCRIPTION,
NODES_QUERY,
PRODUCERS_COUNT_QUERY,
} from '../../gql'
import { eosConfig } from '../../config'
import sortNodes from 'utils/sort-nodes'

Expand All @@ -17,21 +21,28 @@ const useNodeState = () => {
nodes: { type: { _neq: [] } },
},
}
const [variables, setVariables] = useState(defaultVariables)
const [loadProducers, { data: { info } = {} }] = useLazyQuery(
PRODUCERS_COUNT_QUERY,
)
const { data, loading } = useSubscription(NODES_SUBSCRIPTION, { variables })
const isQueryExecuted = useRef(false)
const [items, setItems] = useState([])
const [
{ filters, pagination },
{ filters, pagination, variables },
{ handleOnSearch, handleOnPageChange, setPagination },
] = useSearchState({
loadProducers,
info,
variables,
setVariables,
defaultVariables,
})
const { data, loading } = useSubscription(NODES_SUBSCRIPTION, { variables })
const [loadNodes, { data: queryData }] = useLazyQuery(NODES_QUERY)

useEffect(() => {
if (!variables || isQueryExecuted.current) return

loadNodes({ variables })
isQueryExecuted.current = true
}, [variables, loadNodes])

const chips = [{ name: 'all' }, ...eosConfig.nodeChips]

Expand Down Expand Up @@ -65,9 +76,9 @@ const useNodeState = () => {
}, [filters.name, setPagination])

useEffect(() => {
if (!data) return
if (!data && !queryData) return

const { producers } = data
const { producers } = data || queryData
const isFilterByFeature = isFeature(filters.name)

const list = producers.flatMap((producer) => {
Expand All @@ -92,7 +103,7 @@ const useNodeState = () => {
})

setItems(list)
}, [filters.name, data])
}, [filters.name, data, queryData])

return [
{ filters, chips, loading, items, pagination },
Expand Down
24 changes: 18 additions & 6 deletions webapp/src/hooks/customHooks/useSearchState.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { useState, useEffect, useCallback } from 'react'
import { useLocation } from 'react-router-dom'
import queryString from 'query-string'

const useSearchState = ({ loadProducers, info, variables, setVariables }) => {
import isTheSameObject from 'utils/is-same-object'

const useSearchState = ({ loadProducers, info, defaultVariables }) => {
const [variables, setVariables] = useState()
const location = useLocation()
const [pagination, setPagination] = useState({
page: 1,
pages: 1,
...variables,
})
const [filters, setFilters] = useState({ name: 'all', owner: '' })

Expand All @@ -33,16 +35,21 @@ const useSearchState = ({ loadProducers, info, variables, setVariables }) => {
}

useEffect(() => {
if (!pagination.where || !pagination.limit) return

const variables = {
limit: pagination.limit,
offset: (pagination.page - 1) * pagination.limit,
endpointFilter: pagination.endpointFilter,
where: pagination.where,
}

loadProducers({ variables: { where: pagination.where } })
setVariables(prev => {
if (isTheSameObject(prev, variables)) return prev

setVariables(variables)
loadProducers({ variables: { where: pagination.where } })
return variables
})
}, [
pagination.where,
pagination.page,
Expand All @@ -56,9 +63,14 @@ const useSearchState = ({ loadProducers, info, variables, setVariables }) => {
useEffect(() => {
const params = queryString.parse(location.search)

if (!params.owner) return
if (!params.owner) {
setPagination(prev => ({ ...prev, ...defaultVariables }))

return
}

setPagination(prev => ({
...defaultVariables,
...prev,
page: 1,
where: { owner: { _like: `%${params.owner}%` } },
Expand All @@ -78,7 +90,7 @@ const useSearchState = ({ loadProducers, info, variables, setVariables }) => {
}, [info, pagination.limit])

return [
{ filters, pagination },
{ filters, pagination, variables, setVariables },
{
handleOnSearch,
handleOnPageChange,
Expand Down
14 changes: 14 additions & 0 deletions webapp/src/utils/is-same-object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const isTheSameObject = (obj1, obj2) => {
if (typeof obj1 === 'object' && typeof obj2 === 'object') {
if (Object.keys(obj1 || {}).length !== Object.keys(obj2 || {}).length)
return false

return Object.keys(obj1 || {}).every((key) => {
return isTheSameObject(obj1[key], obj2[key])
})
}

return obj1 === obj2
}

export default isTheSameObject

0 comments on commit 2ebfbc7

Please sign in to comment.