1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge pull request #1217 from oceanprotocol/fix/compute-jobs

Fix compute jobs
This commit is contained in:
Bogdan Fazakas 2022-04-15 11:22:22 +03:00 committed by GitHub
commit c86a9f8429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 895 additions and 1269 deletions

1773
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
"@coingecko/cryptoformat": "^0.4.4", "@coingecko/cryptoformat": "^0.4.4",
"@loadable/component": "^5.15.2", "@loadable/component": "^5.15.2",
"@oceanprotocol/art": "^3.2.0", "@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^1.0.0-next.33", "@oceanprotocol/lib": "^1.0.0-next.36",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.7", "@portis/web3": "^4.0.7",
"@tippyjs/react": "^4.2.6", "@tippyjs/react": "^4.2.6",

View File

@ -74,15 +74,14 @@ async function getAssetMetadata(
const baseQueryparams = { const baseQueryparams = {
chainIds, chainIds,
filters: [ filters: [
getFilterTerm('datatokens', queryDtList), getFilterTerm('services.datatokenAddress', queryDtList),
getFilterTerm('service.type', 'compute'), getFilterTerm('services.type', 'compute'),
getFilterTerm('metadata.type', 'dataset') getFilterTerm('metadata.type', 'dataset')
], ],
ignorePurgatory: true ignorePurgatory: true
} as BaseQueryParams } as BaseQueryParams
const query = generateBaseQuery(baseQueryparams) const query = generateBaseQuery(baseQueryparams)
const result = await queryMetadata(query, cancelToken) const result = await queryMetadata(query, cancelToken)
return result?.results return result?.results
} }
@ -215,42 +214,43 @@ async function getJobs(
assets: Asset[] assets: Asset[]
): Promise<ComputeJobMetaData[]> { ): Promise<ComputeJobMetaData[]> {
const computeJobs: ComputeJobMetaData[] = [] const computeJobs: ComputeJobMetaData[] = []
providerUrls.forEach(async (providerUrl) => { // commented loop since we decide how to filter jobs
try { // for await (const providerUrl of providerUrls) {
const providerComputeJobs = (await ProviderInstance.computeStatus( try {
providerUrl, const providerComputeJobs = (await ProviderInstance.computeStatus(
accountId providerUrls[0],
)) as ComputeJob[] accountId
)) as ComputeJob[]
if (!providerComputeJobs) { if (providerComputeJobs) {
providerComputeJobs.sort((a, b) => { providerComputeJobs.sort((a, b) => {
if (a.dateCreated > b.dateCreated) { if (a.dateCreated > b.dateCreated) {
return -1 return -1
} }
if (a.dateCreated < b.dateCreated) { if (a.dateCreated < b.dateCreated) {
return 1 return 1
} }
return 0 return 0
}) })
providerComputeJobs.forEach((job) => {
const did = job.inputDID[0]
const asset = assets.filter((x) => x.id === did)[0]
if (!asset) { providerComputeJobs.forEach((job) => {
const compJob: ComputeJobMetaData = { const did = job.inputDID[0]
...job, const asset = assets.filter((x) => x.id === did)[0]
assetName: asset.metadata.name, if (asset) {
assetDtSymbol: asset.datatokens[0].symbol, const compJob: ComputeJobMetaData = {
networkId: asset.chainId ...job,
} assetName: asset.metadata.name,
computeJobs.push(compJob) assetDtSymbol: asset.datatokens[0].symbol,
networkId: asset.chainId
} }
}) computeJobs.push(compJob)
} }
} catch (err) { })
LoggerInstance.error(err.message)
} }
}) } catch (err) {
LoggerInstance.error(err.message)
}
// }
return computeJobs return computeJobs
} }
export async function getComputeJobs( export async function getComputeJobs(
@ -274,21 +274,18 @@ export async function getComputeJobs(
user: accountId.toLowerCase() user: accountId.toLowerCase()
} }
console.log(' getComputeJobs variables ', variables)
const results = await fetchDataForMultipleChains( const results = await fetchDataForMultipleChains(
assetDTAddress ? getComputeOrdersByDatatokenAddress : getComputeOrders, assetDTAddress ? getComputeOrdersByDatatokenAddress : getComputeOrders,
variables, variables,
assetDTAddress ? [asset?.chainId] : chainIds assetDTAddress ? [asset?.chainId] : chainIds
) )
console.log(' getComputeJobs results getComputeOrders', results)
let tokenOrders: TokenOrder[] = [] let tokenOrders: TokenOrder[] = []
results.map((result) => { results.map((result) => {
result.orders.forEach((tokenOrder: TokenOrder) => result.orders.forEach((tokenOrder: TokenOrder) =>
tokenOrders.push(tokenOrder) tokenOrders.push(tokenOrder)
) )
}) })
console.log(' getComputeJobs tokenOrders ', tokenOrders)
if (tokenOrders.length === 0) { if (tokenOrders.length === 0) {
return computeResult return computeResult
} }
@ -296,6 +293,7 @@ export async function getComputeJobs(
tokenOrders = tokenOrders.sort( tokenOrders = tokenOrders.sort(
(a, b) => b.createdTimestamp - a.createdTimestamp (a, b) => b.createdTimestamp - a.createdTimestamp
) )
const datatokenAddressList = tokenOrders.map( const datatokenAddressList = tokenOrders.map(
(tokenOrder: TokenOrder) => tokenOrder.datatoken.address (tokenOrder: TokenOrder) => tokenOrder.datatoken.address
) )
@ -311,6 +309,7 @@ export async function getComputeJobs(
assets.forEach((asset: Asset) => assets.forEach((asset: Asset) =>
providerUrls.push(asset.services[0].serviceEndpoint) providerUrls.push(asset.services[0].serviceEndpoint)
) )
computeResult.computeJobs = await getJobs(providerUrls, accountId, assets) computeResult.computeJobs = await getJobs(providerUrls, accountId, assets)
computeResult.isLoaded = true computeResult.isLoaded = true

View File

@ -243,13 +243,10 @@ export async function fetchDataForMultipleChains(
let datas: any[] = [] let datas: any[] = []
try { try {
for (const chainId of chainIds) { for (const chainId of chainIds) {
// console.log('fetch chainID', chainId)
const context: OperationContext = getQueryContext(chainId) const context: OperationContext = getQueryContext(chainId)
const response = await fetchData(query, variables, context) const response = await fetchData(query, variables, context)
// console.log('fetch response', response)
if (!response || response.error) continue if (!response || response.error) continue
datas = datas.concat(response?.data) datas = datas.concat(response?.data)
// console.log('fetch datas', datas)
} }
return datas return datas
} catch (error) { } catch (error) {
@ -358,10 +355,8 @@ export async function getAccountTVLInOwnAssets(
chainIds chainIds
) )
let tvl = new Decimal(0) let tvl = new Decimal(0)
// console.log('resss', results)
for (const result of results) { for (const result of results) {
// console.log('result.poolShares', result.poolShares)
for (const poolShare of result.poolShares) { for (const poolShare of result.poolShares) {
const poolUserTvl = calculateUserTVL( const poolUserTvl = calculateUserTVL(
poolShare.shares, poolShare.shares,
@ -369,7 +364,6 @@ export async function getAccountTVLInOwnAssets(
poolShare.pool.baseTokenLiquidity poolShare.pool.baseTokenLiquidity
) )
tvl = tvl.add(new Decimal(poolUserTvl)) tvl = tvl.add(new Decimal(poolUserTvl))
// console.log('result.poolShares', tvl.toString())
} }
} }
return tvl.toDecimalPlaces(MAX_DECIMALS).toString() return tvl.toDecimalPlaces(MAX_DECIMALS).toString()

View File

@ -9,7 +9,8 @@ import {
Datatoken, Datatoken,
ProviderInstance, ProviderInstance,
ComputeAsset, ComputeAsset,
ZERO_ADDRESS ZERO_ADDRESS,
ComputeEnvironment
} from '@oceanprotocol/lib' } from '@oceanprotocol/lib'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import Price from '@shared/Price' import Price from '@shared/Price'
@ -83,6 +84,8 @@ export default function Compute({
const [isConsumablePrice, setIsConsumablePrice] = useState(true) const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true) const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true)
const [computeStatusText, setComputeStatusText] = useState('') const [computeStatusText, setComputeStatusText] = useState('')
const [computeEnv, setComputeEnv] = useState<ComputeEnvironment>()
const [computeValidUntil, setComputeValidUntil] = useState<number>()
const [datasetOrderPriceAndFees, setDatasetOrderPriceAndFees] = const [datasetOrderPriceAndFees, setDatasetOrderPriceAndFees] =
useState<OrderPriceAndFees>() useState<OrderPriceAndFees>()
const [isRequestingDataseOrderPrice, setIsRequestingDataseOrderPrice] = const [isRequestingDataseOrderPrice, setIsRequestingDataseOrderPrice] =
@ -110,28 +113,76 @@ export default function Compute({
return hasAlgoDt return hasAlgoDt
} }
async function initPriceAndFees() {
const computeEnv = await getComputeEnviroment(asset)
setComputeEnv(computeEnv)
const validUntil = getValidUntilTime(
computeEnv?.maxJobDuration,
asset.services[0].timeout,
selectedAlgorithmAsset.services[0].timeout
)
setComputeValidUntil(validUntil)
if (
asset?.accessDetails?.addressOrId !== ZERO_ADDRESS ||
asset?.accessDetails?.type !== 'free'
) {
setIsRequestingDataseOrderPrice(true)
setComputeStatusText(
getComputeFeedback(
asset.accessDetails.baseToken?.symbol,
asset.accessDetails.datatoken?.symbol,
asset.metadata.type
)[0]
)
const datasetPriceAndFees = await getOrderPriceAndFees(
asset,
accountId,
computeEnv?.id,
validUntil
)
if (!datasetPriceAndFees) {
setError('Error setting dataset price and fees!')
toast.error('Error setting dataset price and fees!')
return
}
setDatasetOrderPriceAndFees(datasetPriceAndFees)
setIsRequestingDataseOrderPrice(false)
}
if (
selectedAlgorithmAsset?.accessDetails?.addressOrId !== ZERO_ADDRESS ||
selectedAlgorithmAsset?.accessDetails?.type !== 'free'
) {
setIsRequestingAlgoOrderPrice(true)
setComputeStatusText(
getComputeFeedback(
selectedAlgorithmAsset?.accessDetails?.baseToken?.symbol,
selectedAlgorithmAsset?.accessDetails?.datatoken?.symbol,
selectedAlgorithmAsset?.metadata?.type
)[0]
)
const algorithmOrderPriceAndFees = await getOrderPriceAndFees(
selectedAlgorithmAsset,
ZERO_ADDRESS,
computeEnv?.id,
validUntil
)
if (!algorithmOrderPriceAndFees) {
setError('Error setting algorithm price and fees!')
toast.error('Error setting algorithm price and fees!')
return
}
setAlgoOrderPriceAndFees(algorithmOrderPriceAndFees)
setIsRequestingAlgoOrderPrice(false)
}
}
useEffect(() => { useEffect(() => {
if (!asset?.accessDetails || !accountId) return if (!asset?.accessDetails || !accountId) return
setIsConsumablePrice(asset?.accessDetails?.isPurchasable) setIsConsumablePrice(asset?.accessDetails?.isPurchasable)
setIsOwned(asset?.accessDetails?.isOwned) setIsOwned(asset?.accessDetails?.isOwned)
setValidOrderTx(asset?.accessDetails?.validOrderTx) setValidOrderTx(asset?.accessDetails?.validOrderTx)
async function initDatasetPriceAndFees() {
if (
asset?.accessDetails?.addressOrId === ZERO_ADDRESS ||
asset?.accessDetails?.type === 'free'
)
return
setIsRequestingDataseOrderPrice(true)
setComputeStatusText('Calculating price including fees.')
const orderPriceAndFees = await getOrderPriceAndFees(asset, accountId)
setDatasetOrderPriceAndFees(orderPriceAndFees)
setIsRequestingDataseOrderPrice(false)
}
initDatasetPriceAndFees()
}, [asset?.accessDetails]) }, [asset?.accessDetails])
useEffect(() => { useEffect(() => {
@ -143,26 +194,9 @@ export default function Compute({
selectedAlgorithmAsset?.accessDetails?.validOrderTx selectedAlgorithmAsset?.accessDetails?.validOrderTx
) )
async function initAlgoPriceAndFees() {
if (
selectedAlgorithmAsset?.accessDetails?.addressOrId === ZERO_ADDRESS ||
selectedAlgorithmAsset?.accessDetails?.type === 'free'
)
return
setIsRequestingAlgoOrderPrice(true)
setComputeStatusText('Calculating price including fees.')
const orderPriceAndFees = await getOrderPriceAndFees(
selectedAlgorithmAsset,
accountId
)
setAlgoOrderPriceAndFees(orderPriceAndFees)
setIsRequestingAlgoOrderPrice(false)
}
async function initSelectedAlgo() { async function initSelectedAlgo() {
const hasAlgoDt = await checkAssetDTBalance(selectedAlgorithmAsset) await checkAssetDTBalance(selectedAlgorithmAsset)
!hasAlgoDt && (await initAlgoPriceAndFees()) await initPriceAndFees()
} }
initSelectedAlgo() initSelectedAlgo()
@ -215,32 +249,6 @@ export default function Compute({
return return
} }
const computeEnv = await getComputeEnviroment(asset)
const validUntil = getValidUntilTime(
computeEnv?.maxJobDuration,
asset.services[0].timeout,
selectedAlgorithmAsset.services[0].timeout
)
setComputeStatusText(
getComputeFeedback(
asset.accessDetails.baseToken?.symbol,
asset.accessDetails.datatoken?.symbol,
asset.metadata.type
)[0]
)
const datasetPriceAndFees = await getOrderPriceAndFees(
asset,
accountId,
computeEnv?.id,
validUntil
)
if (!datasetPriceAndFees) {
setError('Error setting dataset price and fees!')
toast.error('Error setting dataset price and fees!')
return
}
let datasetOrderTx let datasetOrderTx
if (isOwned) { if (isOwned) {
datasetOrderTx = validOrderTx datasetOrderTx = validOrderTx
@ -266,7 +274,10 @@ export default function Compute({
return return
} }
} }
LoggerInstance.log('dataset orderPriceAndFees: ', datasetPriceAndFees) LoggerInstance.log(
'dataset orderPriceAndFees: ',
datasetOrderPriceAndFees
)
setComputeStatusText( setComputeStatusText(
getComputeFeedback( getComputeFeedback(
asset.accessDetails.baseToken?.symbol, asset.accessDetails.baseToken?.symbol,
@ -277,10 +288,10 @@ export default function Compute({
const orderTx = await order( const orderTx = await order(
web3, web3,
asset, asset,
datasetPriceAndFees, datasetOrderPriceAndFees,
accountId, accountId,
computeEnv?.id, computeEnv?.id,
validUntil, computeValidUntil,
computeEnv?.consumerAddress computeEnv?.consumerAddress
) )
if (!orderTx) { if (!orderTx) {
@ -301,26 +312,6 @@ export default function Compute({
} }
} }
setComputeStatusText(
getComputeFeedback(
selectedAlgorithmAsset.accessDetails.baseToken?.symbol,
selectedAlgorithmAsset.accessDetails.datatoken?.symbol,
selectedAlgorithmAsset.metadata.type
)[0]
)
const algorithmOrderPriceAndFees = await getOrderPriceAndFees(
selectedAlgorithmAsset,
ZERO_ADDRESS,
computeEnv?.id,
validUntil
)
if (!algorithmOrderPriceAndFees) {
setError('Error setting algorithm price and fees!')
toast.error('Error setting algorithm price and fees!')
return
}
let algorithmOrderTx let algorithmOrderTx
if (isAlgorithmOwned) { if (isAlgorithmOwned) {
algorithmOrderTx = validAlgorithmOrderTx algorithmOrderTx = validAlgorithmOrderTx
@ -362,10 +353,10 @@ export default function Compute({
const orderTx = await order( const orderTx = await order(
web3, web3,
selectedAlgorithmAsset, selectedAlgorithmAsset,
algorithmOrderPriceAndFees, algoOrderPriceAndFees,
accountId, accountId,
computeEnv?.id, computeEnv?.id,
validUntil, computeValidUntil,
computeEnv?.consumerAddress computeEnv?.consumerAddress
) )
if (!orderTx) { if (!orderTx) {

View File

@ -62,6 +62,20 @@
.assetMeta code { .assetMeta code {
color: var(--color-secondary); color: var(--color-secondary);
font-size: var(--font-size-small); font-size: var(--font-size-small);
overflow: hidden;
width: 100%;
flex: 6;
text-overflow: ellipsis;
white-space: nowrap;
}
.assetMeta span {
flex: 1;
}
.assetMeta {
display: flex;
flex-wrap: wrap;
} }
.meta { .meta {

View File

@ -33,7 +33,8 @@ function Asset({
</a> </a>
</h3> </h3>
<p className={styles.assetMeta}> <p className={styles.assetMeta}>
{symbol} | <code>{did}</code> <span className={styles.assetMeta}> {`${symbol} | `}</span>
<code className={styles.assetMeta}>{did}</code>
</p> </p>
</div> </div>
) )
@ -97,7 +98,7 @@ export default function Details({
/> />
)} )}
<MetaItem title="Job ID" content={<code>{job.jobId}</code>} /> <MetaItem title="Job ID" content={<code>{job.jobId}</code>} />
{/* {job.resultsDid && ( {/* {job.results[0]. && (
<MetaItem <MetaItem
title="Published Results DID" title="Published Results DID"
content={<code>{job.resultsDid}</code>} content={<code>{job.resultsDid}</code>}

View File

@ -3,6 +3,10 @@
border-bottom-left-radius: var(--border-radius) !important; border-bottom-left-radius: var(--border-radius) !important;
} }
.results li {
list-style-type: none;
}
.help { .help {
margin-top: calc(var(--spacer) / 3); margin-top: calc(var(--spacer) / 3);
} }

View File

@ -1,90 +1,106 @@
import { LoggerInstance } from '@oceanprotocol/lib' import {
import React, { ReactElement, useState } from 'react' ComputeResultType,
import Loader from '@shared/atoms/Loader' downloadFileBrowser,
LoggerInstance,
Provider
} from '@oceanprotocol/lib'
import React, { ReactElement, useEffect, useState } from 'react'
import { ListItem } from '@shared/atoms/Lists' import { ListItem } from '@shared/atoms/Lists'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import styles from './Results.module.css' import styles from './Results.module.css'
import FormHelp from '@shared/FormInput/Help' import FormHelp from '@shared/FormInput/Help'
import content from '../../../../../content/pages/history.json' import content from '../../../../../content/pages/history.json'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { useCancelToken } from '@hooks/useCancelToken'
import { retrieveAsset } from '@utils/aquarius'
export default function Results({ export default function Results({
job job
}: { }: {
job: ComputeJobMetaData job: ComputeJobMetaData
}): ReactElement { }): ReactElement {
const { accountId } = useWeb3() const providerInstance = new Provider()
const { accountId, web3 } = useWeb3()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [hasFetched, setHasFetched] = useState(false)
const isFinished = job.dateFinished !== null const isFinished = job.dateFinished !== null
async function getResults() { const [datasetProvider, setDatasetProvider] = useState<string>()
const newCancelToken = useCancelToken()
useEffect(() => {
async function getAssetMetadata() {
const ddo = await retrieveAsset(job.inputDID[0], newCancelToken())
setDatasetProvider(ddo.services[0].serviceEndpoint)
}
getAssetMetadata()
}, [job.inputDID[0]])
function getDownloadButtonValue(type: ComputeResultType): string {
let buttonName
switch (type) {
case 'output':
buttonName = 'Download results'
break
case 'algorithmLog':
buttonName = 'Download algorithm logs'
break
case 'configrationLog':
buttonName = 'Download configuration logs'
break
case 'publishLog':
buttonName = 'Download publish logs'
break
default:
buttonName = 'Download results'
break
}
return buttonName
}
async function downloadResults(resultIndex: number) {
if (!accountId || !job) return if (!accountId || !job) return
try { try {
setIsLoading(true) setIsLoading(true)
// const jobStatus = await ocean.compute.status( const jobResult = await providerInstance.getComputeResultUrl(
// account, datasetProvider,
// job.did, web3,
// undefined, accountId,
// undefined, job.jobId,
// job.jobId resultIndex
// ) )
// if (jobStatus?.length > 0) { await downloadFileBrowser(jobResult)
// job.algorithmLogUrl = jobStatus[0].algorithmLogUrl
// job.resultsUrl = jobStatus[0].resultsUrl
// }
} catch (error) { } catch (error) {
LoggerInstance.error(error.message) LoggerInstance.error(error.message)
} finally { } finally {
setIsLoading(false) setIsLoading(false)
setHasFetched(true)
} }
} }
return ( return (
<div className={styles.results}> <div className={styles.results}>
{hasFetched ? ( {isFinished ? (
<ul> <ul>
<ListItem> {job.results &&
{/* {job.algorithmLogUrl ? ( Array.isArray(job.results) &&
<a href={job.algorithmLogUrl} target="_blank" rel="noreferrer"> job.results.map((jobResult, i) =>
View Log jobResult.filename ? (
</a> <ListItem key={i}>
) : ( <Button
'No logs found.' style="primary"
)} */} size="small"
</ListItem> onClick={() => downloadResults(i)}
disabled={isLoading || !isFinished}
{/* {job.resultsUrl && >
Array.isArray(job.resultsUrl) && {getDownloadButtonValue(jobResult.type)}
job.resultsUrl.map((url, i) => </Button>
url ? (
<ListItem key={job.jobId}>
<a href={url} target="_blank" rel="noreferrer">
View Result {i + 1}
</a>
</ListItem> </ListItem>
) : ( ) : (
<ListItem>No results found.</ListItem> <ListItem>No results found.</ListItem>
) )
)} */} )}
</ul> </ul>
) : ( ) : (
<Button <p> Waiting for results...</p>
style="primary"
size="small"
onClick={() => getResults()}
disabled={isLoading || !isFinished}
>
{isLoading ? (
<Loader />
) : !isFinished ? (
'Waiting for results...'
) : (
'Get Results'
)}
</Button>
)} )}
<FormHelp className={styles.help}>{content.compute.storage}</FormHelp> <FormHelp className={styles.help}>{content.compute.storage}</FormHelp>
</div> </div>