Small refactors & optimizations (#863)

* proper cancelation

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* fix more leaks

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* remove redundant check

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* fix consume

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* fix assetactions

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* fix consume

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* remove unnecessary usage of ocean

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* small fixed in profile

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* fix
This commit is contained in:
mihaisc 2021-09-24 14:56:42 +03:00 committed by GitHub
parent aee246cf7a
commit fdac6d8039
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 205 additions and 175 deletions

View File

@ -9,6 +9,7 @@ import { getAssetsFromDidList } from '../../utils/aquarius'
import { getAssetsBestPrices, AssetListPrices } from '../../utils/subgraph'
import axios, { CancelToken } from 'axios'
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
import { useCancelToken } from '../../hooks/useCancelToken'
async function getAssetsBookmarked(
bookmarks: string[],
@ -60,12 +61,10 @@ export default function Bookmarks(): ReactElement {
const [pinned, setPinned] = useState<AssetListPrices[]>()
const [isLoading, setIsLoading] = useState<boolean>()
const { chainIds } = useUserPreferences()
const newCancelToken = useCancelToken()
useEffect(() => {
if (!appConfig?.metadataCacheUri || bookmarks === []) return
const source = axios.CancelToken.source()
async function init() {
if (!bookmarks?.length) {
setPinned([])
@ -78,7 +77,7 @@ export default function Bookmarks(): ReactElement {
const resultPinned = await getAssetsBookmarked(
bookmarks,
chainIds,
source.token
newCancelToken()
)
const pinnedAssets: AssetListPrices[] = await getAssetsBestPrices(
resultPinned?.results
@ -91,11 +90,7 @@ export default function Bookmarks(): ReactElement {
setIsLoading(false)
}
init()
return () => {
source.cancel()
}
}, [bookmarks, chainIds, appConfig?.metadataCacheUri])
}, [appConfig?.metadataCacheUri, bookmarks, chainIds, newCancelToken])
return (
<Table

View File

@ -8,15 +8,16 @@ import { InputProps } from '../../../atoms/Input'
import { fileinfo } from '../../../../utils/provider'
import { useWeb3 } from '../../../../providers/Web3'
import { getOceanConfig } from '../../../../utils/ocean'
import { useCancelToken } from '../../../../hooks/useCancelToken'
export default function FilesInput(props: InputProps): ReactElement {
const [field, meta, helpers] = useField(props.name)
const [isLoading, setIsLoading] = useState(false)
const [fileUrl, setFileUrl] = useState<string>()
const { chainId } = useWeb3()
const newCancelToken = useCancelToken()
function loadFileInfo() {
const source = axios.CancelToken.source()
const config = getOceanConfig(chainId || 1)
async function validateUrl() {
@ -25,7 +26,7 @@ export default function FilesInput(props: InputProps): ReactElement {
const checkedFile = await fileinfo(
fileUrl,
config?.providerUri,
source.token
newCancelToken()
)
checkedFile && helpers.setValue([checkedFile])
} catch (error) {
@ -37,10 +38,6 @@ export default function FilesInput(props: InputProps): ReactElement {
}
fileUrl && validateUrl()
return () => {
source.cancel()
}
}
useEffect(() => {

View File

@ -40,6 +40,8 @@ import { getPreviousOrders, getPrice } from '../../../../utils/subgraph'
import AssetActionHistoryTable from '../../AssetActionHistoryTable'
import ComputeJobs from '../../../pages/Profile/History/ComputeJobs'
import { BestPrice } from '../../../../models/BestPrice'
import { useCancelToken } from '../../../../hooks/useCancelToken'
import { useIsMounted } from '../../../../hooks/useIsMounted'
const SuccessAction = () => (
<Button style="text" to="/profile?defaultTab=ComputeJobs" size="small">
@ -72,8 +74,6 @@ export default function Compute({
const [ddoAlgorithmList, setDdoAlgorithmList] = useState<DDO[]>()
const [selectedAlgorithmAsset, setSelectedAlgorithmAsset] = useState<DDO>()
const [hasAlgoAssetDatatoken, setHasAlgoAssetDatatoken] = useState<boolean>()
const [datasetMaxDT, setDatasetMaxDT] = useState<number>(1)
const [algoMaxDT, setAlgoMaxDT] = useState<number>(1)
const [isPublished, setIsPublished] = useState(false)
const [hasPreviousDatasetOrder, setHasPreviousDatasetOrder] = useState(false)
const [previousDatasetOrderId, setPreviousDatasetOrderId] = useState<string>()
@ -85,15 +85,19 @@ export default function Compute({
useState<string>()
const [datasetTimeout, setDatasetTimeout] = useState<string>()
const [algorithmTimeout, setAlgorithmTimeout] = useState<string>()
const newCancelToken = useCancelToken()
const hasDatatoken = Number(dtBalance) >= 1
const isMounted = useIsMounted()
const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true)
const isComputeButtonDisabled =
isJobStarting === true ||
file === null ||
!ocean ||
(!hasPreviousDatasetOrder && !hasDatatoken && !(datasetMaxDT >= 1)) ||
(!hasPreviousAlgorithmOrder && !hasAlgoAssetDatatoken && !(algoMaxDT >= 1))
(!hasPreviousDatasetOrder && !hasDatatoken && !isConsumablePrice) ||
(!hasPreviousAlgorithmOrder &&
!hasAlgoAssetDatatoken &&
!isAlgoConsumablePrice)
async function checkPreviousOrders(ddo: DDO) {
const { timeout } = (
@ -105,6 +109,8 @@ export default function Compute({
timeout.toString()
)
const assetType = ddo.findServiceByType('metadata').attributes.main.type
if (!isMounted()) return
if (assetType === 'algorithm') {
setPreviousAlgorithmOrderId(orderId)
setHasPreviousAlgorithmOrder(!!orderId)
@ -123,22 +129,6 @@ export default function Compute({
setHasAlgoAssetDatatoken(Number(AssetDtBalance) >= 1)
}
async function checkAssetDTMaxBuyQuantity(
price: BestPrice,
assetType: string
) {
if (!ocean || !price || !assetType) return
const maxTokensInPool =
price.type === 'pool'
? await ocean.pool.getDTMaxBuyQuantity(price.address)
: 1
if (assetType === 'algorithm') {
setAlgoMaxDT(Number(maxTokensInPool))
} else {
setDatasetMaxDT(Number(maxTokensInPool))
}
}
function getQuerryString(
trustedAlgorithmList: publisherTrustedAlgorithm[],
chainId?: number
@ -188,12 +178,36 @@ export default function Compute({
algorithmSelectionList = await transformDDOToAssetSelection(
datasetComputeService?.serviceEndpoint,
gueryResults.results,
[]
[],
newCancelToken()
)
}
return algorithmSelectionList
}
const initMetadata = useCallback(async (ddo: DDO): Promise<void> => {
if (!ddo) return
const price = await getPrice(ddo)
setAlgorithmPrice(price)
}, [])
useEffect(() => {
if (!algorithmPrice) return
setIsAlgoConsumablePrice(
algorithmPrice.isConsumable !== undefined
? algorithmPrice.isConsumable === 'true'
: true
)
}, [algorithmPrice])
useEffect(() => {
if (!price) return
setIsConsumablePrice(
price.isConsumable !== undefined ? price.isConsumable === 'true' : true
)
}, [price])
useEffect(() => {
const { timeout } = (
ddo.findServiceByType('access') || ddo.findServiceByType('compute')
@ -201,17 +215,6 @@ export default function Compute({
setDatasetTimeout(secondsToString(timeout))
}, [ddo])
const initMetadata = useCallback(async (ddo: DDO): Promise<void> => {
if (!ddo) return
const price = await getPrice(ddo)
setAlgorithmPrice(price)
ocean &&
checkAssetDTMaxBuyQuantity(
price,
ddo.findServiceByType('metadata').attributes.main.type
)
}, [])
useEffect(() => {
if (!ddo) return
getAlgorithmList().then((algorithms) => {
@ -222,10 +225,6 @@ export default function Compute({
useEffect(() => {
if (!ocean || !accountId) return
checkPreviousOrders(ddo)
checkAssetDTMaxBuyQuantity(
price,
ddo.findServiceByType('metadata').attributes.main.type
)
}, [ocean, ddo, accountId])
useEffect(() => {
@ -442,7 +441,7 @@ export default function Compute({
hasPreviousOrder={hasPreviousDatasetOrder}
hasDatatoken={hasDatatoken}
dtBalance={dtBalance}
datasetLowPoolLiquidity={!(datasetMaxDT >= 1)}
datasetLowPoolLiquidity={!isConsumablePrice}
assetType={type}
assetTimeout={datasetTimeout}
hasPreviousOrderSelectedComputeAsset={hasPreviousAlgorithmOrder}
@ -451,7 +450,7 @@ export default function Compute({
selectedAlgorithmAsset?.dataTokenInfo?.symbol
}
dtBalanceSelectedComputeAsset={algorithmDTBalance}
selectedComputeAssetLowPoolLiquidity={!(algoMaxDT >= 1)}
selectedComputeAssetLowPoolLiquidity={!isAlgoConsumablePrice}
selectedComputeAssetType="algorithm"
selectedComputeAssetTimeout={algorithmTimeout}
stepText={pricingStepText || 'Starting Compute Job...'}

View File

@ -17,7 +17,7 @@ import ButtonBuy from '../../atoms/ButtonBuy'
import { secondsToString } from '../../../utils/metadata'
import AlgorithmDatasetsListForCompute from '../AssetContent/AlgorithmDatasetsListForCompute'
import styles from './Consume.module.css'
import { BestPrice } from '../../../models/BestPrice'
import { useIsMounted } from '../../../hooks/useIsMounted'
const previousOrderQuery = gql`
query PreviousOrder($id: String!, $account: String!) {
@ -61,10 +61,10 @@ export default function Consume({
const { consumeStepText, consume, consumeError, isLoading } = useConsume()
const [isDisabled, setIsDisabled] = useState(true)
const [hasDatatoken, setHasDatatoken] = useState(false)
const [maxDt, setMaxDT] = useState<number>(1)
const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [assetTimeout, setAssetTimeout] = useState('')
const [data, setData] = useState<OrdersData>()
const isMounted = useIsMounted()
useEffect(() => {
if (!ddo || !accountId) return
@ -74,18 +74,9 @@ export default function Consume({
account: accountId?.toLowerCase()
}
fetchData(previousOrderQuery, variables, context).then((result: any) => {
setData(result.data)
isMounted() && setData(result.data)
})
}, [ddo, accountId, hasPreviousOrder])
async function checkMaxAvaialableTokens(price: BestPrice) {
if (!ocean || !price) return
const maxTokensInPool =
price.type === 'pool'
? await ocean.pool.getDTMaxBuyQuantity(price.address)
: 1
setMaxDT(Number(maxTokensInPool))
}
}, [ddo, accountId, hasPreviousOrder, isMounted])
useEffect(() => {
if (!data || !assetTimeout || data.tokenOrders.length === 0 || !accountId)
@ -118,7 +109,6 @@ export default function Consume({
setIsConsumablePrice(
price.isConsumable !== undefined ? price.isConsumable === 'true' : true
)
checkMaxAvaialableTokens(price)
}, [price])
useEffect(() => {
@ -134,7 +124,7 @@ export default function Consume({
!isAssetNetwork ||
typeof consumeStepText !== 'undefined' ||
pricingIsLoading ||
(!hasPreviousOrder && !hasDatatoken && !(maxDt >= 1)) ||
(!hasPreviousOrder && !hasDatatoken) ||
!isConsumablePrice) &&
!hasPreviousOrder &&
!hasDatatoken)
@ -184,7 +174,7 @@ export default function Consume({
hasDatatoken={hasDatatoken}
dtSymbol={ddo.dataTokenInfo?.symbol}
dtBalance={dtBalance}
datasetLowPoolLiquidity={!(maxDt >= 1)}
datasetLowPoolLiquidity={!isConsumablePrice}
onClick={handleConsume}
assetTimeout={secondsToString(parseInt(assetTimeout))}
assetType={type}

View File

@ -15,6 +15,7 @@ import { publisherTrustedAlgorithm as PublisherTrustedAlgorithm } from '@oceanpr
import axios from 'axios'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import FormActions from './FormActions'
import { useCancelToken } from '../../../../hooks/useCancelToken'
export default function FormEditComputeDataset({
data,
@ -29,14 +30,13 @@ export default function FormEditComputeDataset({
const { ddo } = useAsset()
const { values }: FormikContextType<ComputePrivacyForm> = useFormikContext()
const [allAlgorithms, setAllAlgorithms] = useState<AssetSelectionAsset[]>()
const newCancelToken = useCancelToken()
const { publisherTrustedAlgorithms } =
ddo?.findServiceByType('compute').attributes.main.privacy
async function getAlgorithmList(
publisherTrustedAlgorithms: PublisherTrustedAlgorithm[]
): Promise<AssetSelectionAsset[]> {
const source = axios.CancelToken.source()
const query = {
query: {
query_string: {
@ -45,12 +45,13 @@ export default function FormEditComputeDataset({
},
sort: { created: 'desc' }
}
const querryResult = await queryMetadata(query, source.token)
const querryResult = await queryMetadata(query, newCancelToken())
const datasetComputeService = ddo.findServiceByType('compute')
const algorithmSelectionList = await transformDDOToAssetSelection(
datasetComputeService?.serviceEndpoint,
querryResult.results,
publisherTrustedAlgorithms
publisherTrustedAlgorithms,
newCancelToken()
)
return algorithmSelectionList
}

View File

@ -86,7 +86,6 @@ export default function Pool(): ReactElement {
const content = data.content.edges[0].node.childContentJson.pool
const { accountId } = useWeb3()
const { ocean } = useOcean()
const [dtSymbol, setDtSymbol] = useState<string>()
const [oceanSymbol, setOceanSymbol] = useState<string>()
const { isInPurgatory, ddo, owner, price, refreshInterval, isAssetNetwork } =
@ -151,7 +150,7 @@ export default function Pool(): ReactElement {
queryVariables,
queryContext
)
return queryResult?.data.pool.shares[0].balance
return queryResult?.data.pool.shares[0]?.balance
}
function refetchLiquidity() {
@ -483,11 +482,9 @@ export default function Pool(): ReactElement {
<Token symbol="% swap fee" balance={swapFee} noIcon />
</TokenList>
{ocean && (
<div className={styles.update}>
Fetching every {refreshInterval / 1000} sec.
</div>
)}
<div className={styles.update}>
Fetching every {refreshInterval / 1000} sec.
</div>
<div className={stylesActions.actions}>
{!isInPurgatory && (

View File

@ -12,9 +12,11 @@ import { useAsset } from '../../../providers/Asset'
import { useOcean } from '../../../providers/Ocean'
import { useWeb3 } from '../../../providers/Web3'
import Web3Feedback from '../../molecules/Web3Feedback'
import { getFileInfo } from '../../../utils/provider'
import { fileinfo, getFileInfo } from '../../../utils/provider'
import axios from 'axios'
import { getOceanConfig } from '../../../utils/ocean'
import { useCancelToken } from '../../../hooks/useCancelToken'
import { useIsMounted } from '../../../hooks/useIsMounted'
export default function AssetActions(): ReactElement {
const { accountId, balance } = useWeb3()
@ -29,7 +31,8 @@ export default function AssetActions(): ReactElement {
const [isConsumable, setIsConsumable] = useState<boolean>(true)
const [consumableFeedback, setConsumableFeedback] = useState<string>('')
const newCancelToken = useCancelToken()
const isMounted = useIsMounted()
useEffect(() => {
if (!ddo || !accountId || !ocean || !isAssetNetwork) return
@ -50,36 +53,26 @@ export default function AssetActions(): ReactElement {
const oceanConfig = getOceanConfig(ddo.chainId)
if (!oceanConfig) return
const source = axios.CancelToken.source()
async function initFileInfo() {
setFileIsLoading(true)
try {
const fileInfo = await getFileInfo(
const fileInfoResponse = await getFileInfo(
DID.parse(`${ddo.id}`),
oceanConfig.providerUri,
source.token
newCancelToken()
)
setFileMetadata(fileInfo.data[0])
fileInfoResponse && setFileMetadata(fileInfoResponse[0])
isMounted() && setFileIsLoading(false)
} catch (error) {
Logger.error(error.message)
} finally {
// this triggers a memory leak warning, no idea how to fix
setFileIsLoading(false)
}
}
initFileInfo()
return () => {
source.cancel()
}
}, [ddo])
}, [ddo, isMounted, newCancelToken])
// Get and set user DT balance
useEffect(() => {
if (!ocean || !accountId) return
if (!ocean || !accountId || !isAssetNetwork) return
async function init() {
try {
const dtBalance = await ocean.datatokens.balance(

View File

@ -5,6 +5,7 @@ import { AssetSelectionAsset } from '../../molecules/FormFields/AssetSelection'
import AssetComputeList from '../../molecules/AssetComputeList'
import { useAsset } from '../../../providers/Asset'
import { DDO } from '@oceanprotocol/lib'
import { useCancelToken } from '../../../hooks/useCancelToken'
export default function AlgorithmDatasetsListForCompute({
algorithmDid,
@ -16,7 +17,7 @@ export default function AlgorithmDatasetsListForCompute({
const { type } = useAsset()
const [datasetsForCompute, setDatasetsForCompute] =
useState<AssetSelectionAsset[]>()
const newCancelToken = useCancelToken()
useEffect(() => {
async function getDatasetsAllowedForCompute() {
const isCompute = Boolean(dataset?.findServiceByType('compute'))
@ -26,7 +27,8 @@ export default function AlgorithmDatasetsListForCompute({
const datasets = await getAlgorithmDatasetsForCompute(
algorithmDid,
datasetComputeService?.serviceEndpoint,
dataset?.chainId
dataset?.chainId,
newCancelToken()
)
setDatasetsForCompute(datasets)
}

View File

@ -7,6 +7,7 @@ import classNames from 'classnames/bind'
import { getAssetsBestPrices, AssetListPrices } from '../../utils/subgraph'
import Loader from '../atoms/Loader'
import { useUserPreferences } from '../../providers/UserPreferences'
import { useIsMounted } from '../../hooks/useIsMounted'
const cx = classNames.bind(styles)
@ -42,14 +43,19 @@ const AssetList: React.FC<AssetListProps> = ({
const { chainIds } = useUserPreferences()
const [assetsWithPrices, setAssetWithPrices] = useState<AssetListPrices[]>()
const [loading, setLoading] = useState<boolean>(true)
const isMounted = useIsMounted()
useEffect(() => {
if (!assets) return
isLoading && setLoading(true)
getAssetsBestPrices(assets).then((asset) => {
async function fetchPrices() {
const asset = await getAssetsBestPrices(assets)
if (!isMounted()) return
setAssetWithPrices(asset)
setLoading(false)
})
}
fetchPrices()
}, [assets])
// // This changes the page field inside the query

View File

@ -4,6 +4,7 @@ import rbacRequest from '../../utils/rbac'
import Alert from '../atoms/Alert'
import Loader from '../atoms/Loader'
import appConfig from '../../../app.config'
import { useIsMounted } from '../../hooks/useIsMounted'
export default function Permission({
eventType,
@ -18,14 +19,17 @@ export default function Permission({
const [messageState, updateMessageState] =
useState<'error' | 'warning' | 'info' | 'success'>()
const { accountId } = useWeb3()
const isMounted = useIsMounted()
useEffect(() => {
if (url === undefined) return
const controller = new AbortController()
const getData = async () => {
if (accountId === undefined) {
updateError('Please make sure your wallet is connected to proceed.')
updateMessageState('info')
} else {
const data = await rbacRequest(eventType, accountId)
const data = await rbacRequest(eventType, accountId, controller.signal)
if (!isMounted()) return
updateData(data)
if (data === 'ERROR') {
updateError(
@ -46,7 +50,10 @@ export default function Permission({
}
}
getData()
}, [eventType, accountId, url])
return () => {
controller.abort()
}
}, [eventType, accountId, url, isMounted])
if (url === undefined || data === true) {
return <>{children}</>

View File

@ -3,7 +3,6 @@ import AssetList from '../organisms/AssetList'
import { SearchQuery } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import Button from '../atoms/Button'
import Bookmarks from '../molecules/Bookmarks'
import axios from 'axios'
import {
queryMetadata,
transformChainIdsListToQuery
@ -14,6 +13,8 @@ import { DDO, Logger } from '@oceanprotocol/lib'
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../providers/UserPreferences'
import styles from './Home.module.css'
import { useIsMounted } from '../../hooks/useIsMounted'
import { useCancelToken } from '../../hooks/useCancelToken'
async function getQueryHighest(
chainIds: number[]
@ -70,10 +71,10 @@ function SectionQueryResult({
const { chainIds } = useUserPreferences()
const [result, setResult] = useState<any>()
const [loading, setLoading] = useState<boolean>()
const isMounted = useIsMounted()
const newCancelToken = useCancelToken()
useEffect(() => {
if (!appConfig.metadataCacheUri) return
const source = axios.CancelToken.source()
async function init() {
if (chainIds.length === 0) {
@ -88,9 +89,9 @@ function SectionQueryResult({
} else {
try {
setLoading(true)
const result = await queryMetadata(query, source.token)
if (queryData && result.totalResults > 0) {
const result = await queryMetadata(query, newCancelToken())
if (!isMounted()) return
if (queryData && result?.totalResults > 0) {
const searchDIDs = queryData.split(' ')
const sortedAssets = sortElements(result.results, searchDIDs)
const overflow = sortedAssets.length - 9
@ -105,11 +106,14 @@ function SectionQueryResult({
}
}
init()
return () => {
source.cancel()
}
}, [appConfig.metadataCacheUri, query, queryData])
}, [
appConfig.metadataCacheUri,
chainIds.length,
isMounted,
newCancelToken,
query,
queryData
])
return (
<section className={styles.section}>

View File

@ -9,6 +9,7 @@ import { ReactComponent as External } from '../../../../../images/external.svg'
import { retrieveDDO } from '../../../../../utils/aquarius'
import Results from './Results'
import styles from './Details.module.css'
import { useCancelToken } from '../../../../../hooks/useCancelToken'
import { useSiteMetadata } from '../../../../../hooks/useSiteMetadata'
function Asset({
@ -44,12 +45,10 @@ function DetailsAssets({ job }: { job: ComputeJobMetaData }) {
const { appConfig } = useSiteMetadata()
const [algoName, setAlgoName] = useState<string>()
const [algoDtSymbol, setAlgoDtSymbol] = useState<string>()
const newCancelToken = useCancelToken()
useEffect(() => {
async function getAlgoMetadata() {
const source = axios.CancelToken.source()
const ddo = await retrieveDDO(job.algoDID, source.token)
const ddo = await retrieveDDO(job.algoDID, newCancelToken())
setAlgoDtSymbol(ddo.dataTokenInfo.symbol)
const { attributes } = ddo.findServiceByType('metadata')

View File

@ -16,6 +16,7 @@ import NetworkName from '../../../../atoms/NetworkName'
import { getComputeJobs } from '../../../../../utils/compute'
import styles from './index.module.css'
import { useAsset } from '../../../../../providers/Asset'
import { useIsMounted } from '../../../../../hooks/useIsMounted'
export function Status({ children }: { children: string }): ReactElement {
return <div className={styles.status}>{children}</div>
@ -79,6 +80,7 @@ export default function ComputeJobs({
const [isLoading, setIsLoading] = useState(true)
const { chainIds } = useUserPreferences()
const [jobs, setJobs] = useState<ComputeJobMetaData[]>([])
const isMounted = useIsMounted()
const columnsMinimal = [columns[4], columns[5], columns[3]]
@ -101,7 +103,7 @@ export default function ComputeJobs({
try {
setIsLoading(true)
const jobs = await getComputeJobs(chainIds, config, ocean, account, ddo)
setJobs(jobs)
isMounted() && setJobs(jobs)
} catch (error) {
Logger.error(error.message)
} finally {

View File

@ -11,12 +11,13 @@ import web3 from 'web3'
import Token from '../../../organisms/AssetActions/Pool/Token'
import { calculateUserLiquidity } from '../../../../utils/subgraph'
import NetworkName from '../../../atoms/NetworkName'
import axios, { CancelToken } from 'axios'
import { CancelToken } from 'axios'
import { retrieveDDO } from '../../../../utils/aquarius'
import { isValidNumber } from '../../../../utils/numberValidations'
import Decimal from 'decimal.js'
import { useProfile } from '../../../../providers/Profile'
import { DDO } from '@oceanprotocol/lib'
import { useCancelToken } from '../../../../hooks/useCancelToken'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
@ -163,7 +164,7 @@ export default function PoolShares({
const [assets, setAssets] = useState<Asset[]>()
const [loading, setLoading] = useState<boolean>(false)
const [dataFetchInterval, setDataFetchInterval] = useState<NodeJS.Timeout>()
const newCancelToken = useCancelToken()
const fetchPoolSharesAssets = useCallback(
async (cancelToken: CancelToken) => {
if (!poolShares || isPoolSharesLoading) return
@ -179,16 +180,15 @@ export default function PoolShares({
)
useEffect(() => {
const cancelTokenSource = axios.CancelToken.source()
const cancelToken = newCancelToken()
async function init() {
setLoading(true)
await fetchPoolSharesAssets(cancelTokenSource.token)
await fetchPoolSharesAssets(cancelToken)
setLoading(false)
if (dataFetchInterval) return
const interval = setInterval(async () => {
await fetchPoolSharesAssets(cancelTokenSource.token)
await fetchPoolSharesAssets(cancelToken)
}, REFETCH_INTERVAL)
setDataFetchInterval(interval)
}
@ -196,9 +196,8 @@ export default function PoolShares({
return () => {
clearInterval(dataFetchInterval)
cancelTokenSource.cancel()
}
}, [dataFetchInterval, fetchPoolSharesAssets])
}, [dataFetchInterval, fetchPoolSharesAssets, newCancelToken])
return accountId ? (
<Table

View File

@ -6,7 +6,7 @@ import { getPublishedAssets } from '../../../../utils/aquarius'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../../../providers/UserPreferences'
import styles from './PublishedList.module.css'
import axios from 'axios'
import { useCancelToken } from '../../../../hooks/useCancelToken'
export default function PublishedList({
accountId
@ -20,19 +20,18 @@ export default function PublishedList({
const [isLoading, setIsLoading] = useState(false)
const [page, setPage] = useState<number>(1)
const [service, setServiceType] = useState('dataset OR algorithm')
const newCancelToken = useCancelToken()
useEffect(() => {
if (!accountId) return
const cancelTokenSource = axios.CancelToken.source()
async function getPublished() {
try {
setIsLoading(true)
const result = await getPublishedAssets(
accountId,
chainIds,
cancelTokenSource.token,
newCancelToken(),
page - 1,
service
)
@ -44,11 +43,14 @@ export default function PublishedList({
}
}
getPublished()
return () => {
cancelTokenSource.cancel()
}
}, [accountId, page, appConfig.metadataCacheUri, chainIds, service])
}, [
accountId,
page,
appConfig.metadataCacheUri,
chainIds,
service,
newCancelToken
])
return accountId ? (
<>

View File

@ -122,12 +122,11 @@ export default function PublishPage({
nextState?: Partial<FormikState<Partial<MetadataPublishFormDataset>>>
) => void
): Promise<void> {
const metadata = transformPublishFormToMetadata(values)
const timeout = mapTimeoutStringToSeconds(values.timeout)
const serviceType = values.access === 'Download' ? 'access' : 'compute'
try {
const metadata = transformPublishFormToMetadata(values)
const timeout = mapTimeoutStringToSeconds(values.timeout)
const serviceType = values.access === 'Download' ? 'access' : 'compute'
Logger.log(
'Publish with ',
metadata,

View File

@ -7,9 +7,8 @@ import Sort from './sort'
import { getResults } from './utils'
import { navigate } from 'gatsby'
import { updateQueryStringParameter } from '../../../utils'
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
import { useUserPreferences } from '../../../providers/UserPreferences'
import axios from 'axios'
import { useCancelToken } from '../../../hooks/useCancelToken'
import styles from './index.module.css'
export default function SearchPage({
@ -21,7 +20,6 @@ export default function SearchPage({
setTotalResults: (totalResults: number) => void
setTotalPagesNumber: (totalPagesNumber: number) => void
}): ReactElement {
const { appConfig } = useSiteMetadata()
const parsed = queryString.parse(location.search)
const { text, owner, tags, page, sort, sortOrder, serviceType, accessType } =
parsed
@ -34,23 +32,19 @@ export default function SearchPage({
const [sortDirection, setSortDirection] = useState<string>(
sortOrder as string
)
const newCancelToken = useCancelToken()
useEffect(() => {
const source = axios.CancelToken.source()
async function initSearch() {
setLoading(true)
setTotalResults(undefined)
const queryResult = await getResults(parsed, chainIds, source.token)
const queryResult = await getResults(parsed, chainIds, newCancelToken())
setQueryResult(queryResult)
setTotalResults(queryResult.totalResults)
setTotalPagesNumber(queryResult.totalPages)
setLoading(false)
}
initSearch()
return () => {
source.cancel()
}
}, [
text,
owner,
@ -60,7 +54,8 @@ export default function SearchPage({
serviceType,
accessType,
sortOrder,
chainIds
chainIds,
newCancelToken
])
function setPage(page: number) {

View File

@ -0,0 +1,18 @@
import { useRef, useEffect, useCallback } from 'react'
import axios, { CancelToken } from 'axios'
export const useCancelToken = (): (() => CancelToken) => {
const axiosSource = useRef(null)
const newCancelToken = useCallback(() => {
axiosSource.current = axios.CancelToken.source()
return axiosSource.current.token
}, [])
useEffect(
() => () => {
if (axiosSource.current) axiosSource.current.cancel()
},
[]
)
return newCancelToken
}

14
src/hooks/useIsMounted.ts Normal file
View File

@ -0,0 +1,14 @@
import { useCallback, useEffect, useRef } from 'react'
export function useIsMounted(): () => boolean {
const isMountedRef = useRef(true)
const isMounted = useCallback(() => isMountedRef.current, [])
useEffect(() => {
return () => {
isMountedRef.current = false
}
}, [])
return isMounted
}

View File

@ -17,6 +17,7 @@ import { MetadataMarket } from '../@types/MetaData'
import { useWeb3 } from './Web3'
import { useSiteMetadata } from '../hooks/useSiteMetadata'
import { BestPrice } from '../models/BestPrice'
import { useCancelToken } from '../hooks/useCancelToken'
interface AssetProviderValue {
isInPurgatory: boolean
@ -61,7 +62,7 @@ function AssetProvider({
const [type, setType] = useState<MetadataMain['type']>()
const [loading, setLoading] = useState(false)
const [isAssetNetwork, setIsAssetNetwork] = useState<boolean>()
const newCancelToken = useCancelToken()
const fetchDdo = async (token?: CancelToken) => {
Logger.log('[asset] Init asset, get DDO')
setLoading(true)
@ -92,11 +93,10 @@ function AssetProvider({
useEffect(() => {
if (!asset || !appConfig.metadataCacheUri) return
const source = axios.CancelToken.source()
let isMounted = true
async function init() {
const ddo = await fetchDdo(source.token)
const ddo = await fetchDdo(newCancelToken())
if (!isMounted) return
Logger.debug('[asset] Got DDO', ddo)
setDDO(ddo)
@ -105,7 +105,6 @@ function AssetProvider({
init()
return () => {
isMounted = false
source.cancel()
}
}, [asset, appConfig.metadataCacheUri])

View File

@ -146,9 +146,9 @@ export async function getAssetsNames(
export async function transformDDOToAssetSelection(
datasetProviderEndpoint: string,
ddoList: DDO[],
selectedAlgorithms?: PublisherTrustedAlgorithm[]
selectedAlgorithms?: PublisherTrustedAlgorithm[],
cancelToken?: CancelToken
): Promise<AssetSelectionAsset[]> {
const source = axios.CancelToken.source()
const didList: string[] = []
const priceList: PriceList = await getAssetsPriceList(ddoList)
const symbolList: any = {}
@ -160,7 +160,7 @@ export async function transformDDOToAssetSelection(
algoComputeService?.serviceEndpoint &&
(didProviderEndpointMap[ddo.id] = algoComputeService?.serviceEndpoint)
}
const ddoNames = await getAssetsNames(didList, source.token)
const ddoNames = await getAssetsNames(didList, cancelToken)
const algorithmList: AssetSelectionAsset[] = []
didList?.forEach((did: string) => {
if (
@ -197,12 +197,12 @@ export async function transformDDOToAssetSelection(
export async function getAlgorithmDatasetsForCompute(
algorithmId: string,
datasetProviderUri: string,
datasetChainId?: number
datasetChainId?: number,
cancelToken?: CancelToken
): Promise<AssetSelectionAsset[]> {
const source = axios.CancelToken.source()
const computeDatasets = await queryMetadata(
getQueryForAlgorithmDatasets(algorithmId, datasetChainId),
source.token
cancelToken
)
const computeDatasetsForCurrentAlgorithm: DDO[] = []
computeDatasets.results.forEach((data: DDO) => {
@ -219,7 +219,8 @@ export async function getAlgorithmDatasetsForCompute(
const datasets = await transformDDOToAssetSelection(
datasetProviderUri,
computeDatasetsForCurrentAlgorithm,
[]
[],
cancelToken
)
return datasets
}

View File

@ -62,21 +62,30 @@ export async function getFileInfo(
url: string | DID,
providerUri: string,
cancelToken: CancelToken
): Promise<AxiosResponse> {
): Promise<any> {
let postBody
try {
if (url instanceof DID)
postBody = {
did: url.getDid(),
cancelToken
did: url.getDid()
}
else
postBody = {
url,
cancelToken
url
}
return await axios.post(`${providerUri}/api/v1/services/fileinfo`, postBody)
const response = await axios.post(
`${providerUri}/api/v1/services/fileinfo`,
postBody,
{ cancelToken }
)
if (!response || response.status !== 200 || !response.data) return
return response.data
} catch (error) {
Logger.error(error.message)
if (axios.isCancel(error)) {
Logger.log(error.message)
} else {
Logger.error(error.message)
}
}
}

View File

@ -3,7 +3,8 @@ import appConfig from '../../app.config'
export default async function rbacRequest(
eventType: string,
address: string
address: string,
signal?: AbortSignal
): Promise<boolean | 'ERROR'> {
const url = appConfig.rbacUrl
if (url === undefined) {
@ -23,7 +24,8 @@ export default async function rbacRequest(
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
body: JSON.stringify(data),
signal: signal
})
return await response.json()
} catch (error) {