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

Compute job history (#462)

* get compute orders query

* wip on getting compute jobs

* wip refcatoring

* get compute history refactored

* small refactor

* loop fixes

* display jobs refactor changes

* display jobs fix

* early output of assets

* query tweak

* quick fix

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

* live update for testing

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

* fix load time

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

* temp refactor

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

* cleanup

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

* lib bump

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

* fix status args

* remove metadata json

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

* fix item duplication

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

* check if wallet connected

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

* debug logs

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

* lib bump

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

* fix service grouping

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

* added sorting

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

Co-authored-by: claudia.holhos <claudia.holhos@hpm.ro>
Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro>
This commit is contained in:
claudiaHash 2021-04-14 12:01:37 +03:00 committed by GitHub
parent b87d50aa09
commit fc6b029118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 168 additions and 51 deletions

2
.gitignore vendored
View File

@ -12,5 +12,5 @@ public/storybook
.artifacts .artifacts
.vercel .vercel
repo-metadata.json repo-metadata.json
networks-metadata.json content/networks-metadata.json
src/@types/apollo src/@types/apollo

8
package-lock.json generated
View File

@ -3625,9 +3625,9 @@
"integrity": "sha512-0dasqU7PL8xZOxvn6ID2IJ6TgQZbkcwtZqiMiYvtsv9+fQr/n13qXYXwkmNEjQb3YL4IeSVUnHehk5KpGRPFWA==" "integrity": "sha512-0dasqU7PL8xZOxvn6ID2IJ6TgQZbkcwtZqiMiYvtsv9+fQr/n13qXYXwkmNEjQb3YL4IeSVUnHehk5KpGRPFWA=="
}, },
"@oceanprotocol/lib": { "@oceanprotocol/lib": {
"version": "0.14.0", "version": "0.14.1",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.0.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.1.tgz",
"integrity": "sha512-0CxrhQuu9tA4HNzytPDEGd+8ceCdFDSPuQJivvnuOH3GWtZNgfJb9wyQnl0YHQgdtWWHkIcnnPL0NsAXKLF+ew==", "integrity": "sha512-NnMt5une64e/ZTEvUQeSs9E9s0Y6TgVni7T/Vhfhnubjrfn/dKkidRYpPpuUr18T2PHfmLtghBlhRLixoYkWKg==",
"requires": { "requires": {
"@ethereum-navigator/navigator": "^0.5.2", "@ethereum-navigator/navigator": "^0.5.2",
"@oceanprotocol/contracts": "^0.5.10", "@oceanprotocol/contracts": "^0.5.10",
@ -16704,7 +16704,7 @@
} }
}, },
"ethereumjs-abi": { "ethereumjs-abi": {
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1a27c59c15ab1e95ee8e5c4ed6ad814c49cc439e", "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
"requires": { "requires": {
"bn.js": "^4.11.8", "bn.js": "^4.11.8",

View File

@ -27,7 +27,7 @@
"@coingecko/cryptoformat": "^0.4.2", "@coingecko/cryptoformat": "^0.4.2",
"@loadable/component": "^5.14.1", "@loadable/component": "^5.14.1",
"@oceanprotocol/art": "^3.0.0", "@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.14.0", "@oceanprotocol/lib": "^0.14.1",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^3.0.3", "@portis/web3": "^3.0.3",
"@sindresorhus/slugify": "^1.0.0", "@sindresorhus/slugify": "^1.0.0",

View File

@ -5,11 +5,34 @@ import Button from '../../atoms/Button'
import ComputeDetails from './ComputeDetails' import ComputeDetails from './ComputeDetails'
import { ComputeJobMetaData } from '../../../@types/ComputeJobMetaData' import { ComputeJobMetaData } from '../../../@types/ComputeJobMetaData'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import { Logger } from '@oceanprotocol/lib' import { DDO, Logger, ServiceCommon, ServiceCompute } from '@oceanprotocol/lib'
import Dotdotdot from 'react-dotdotdot' import Dotdotdot from 'react-dotdotdot'
import Table from '../../atoms/Table' import Table from '../../atoms/Table'
import { useOcean } from '../../../providers/Ocean' import { useOcean } from '../../../providers/Ocean'
import { gql, useQuery } from '@apollo/client'
import { useWeb3 } from '../../../providers/Web3'
import { queryMetadata } from '../../../utils/aquarius'
import axios, { CancelToken } from 'axios'
import { ComputeOrders } from '../../../@types/apollo/ComputeOrders'
import web3 from 'web3'
import AssetTitle from '../../molecules/AssetListTitle'
const getComputeOrders = gql`
query ComputeOrders($user: String!) {
tokenOrders(
orderBy: timestamp
orderDirection: desc
where: { payer: $user }
) {
id
serviceId
datatokenId {
address
}
tx
timestamp
}
}
`
function DetailsButton({ row }: { row: ComputeJobMetaData }): ReactElement { function DetailsButton({ row }: { row: ComputeJobMetaData }): ReactElement {
const [isDialogOpen, setIsDialogOpen] = useState(false) const [isDialogOpen, setIsDialogOpen] = useState(false)
@ -34,7 +57,7 @@ export function Status({ children }: { children: string }): ReactElement {
const columns = [ const columns = [
{ {
name: 'Data Set', name: 'Data Set',
selector: function getAssetRow(row: ComputeJobMetaData) { selector: function getAssetRow(row: ComputeAsset) {
return ( return (
<Dotdotdot clamp={2}> <Dotdotdot clamp={2}>
<Link to={`/asset/${row.did}`}>{row.assetName}</Link> <Link to={`/asset/${row.did}`}>{row.assetName}</Link>
@ -44,84 +67,178 @@ const columns = [
}, },
{ {
name: 'Created', name: 'Created',
selector: function getTimeRow(row: ComputeJobMetaData) { selector: function getTimeRow(row: ComputeAsset) {
return <Time date={row.dateCreated} isUnix relative /> return <Time date={row.dateCreated} isUnix relative />
} }
}, },
{ {
name: 'Finished', name: 'Finished',
selector: function getTimeRow(row: ComputeJobMetaData) { selector: function getTimeRow(row: ComputeAsset) {
return <Time date={row.dateFinished} isUnix relative /> return <Time date={row.dateFinished} isUnix relative />
} }
}, },
{ {
name: 'Status', name: 'Status',
selector: function getStatus(row: ComputeJobMetaData) { selector: function getStatus(row: ComputeAsset) {
return <Status>{row.statusText}</Status> return <Status>{row.statusText}</Status>
} }
}, },
{ {
name: 'Actions', name: 'Actions',
selector: function getActions(row: ComputeJobMetaData) { selector: function getActions(row: ComputeAsset) {
return <DetailsButton row={row} /> return <DetailsButton row={row} />
} }
} }
] ]
async function getAssetMetadata(
queryDtList: string,
metadataCacheUri: string,
cancelToken: CancelToken,
timestamps: number[]
): Promise<DDO[]> {
const queryDid = {
page: 1,
offset: 100,
query: {
query_string: {
query: `(${queryDtList}) AND service.attributes.main.type:dataset AND service.type:compute`,
fields: ['dataToken']
}
}
}
const result = await queryMetadata(queryDid, metadataCacheUri, cancelToken)
return result.results
}
interface ComputeAsset extends ComputeJobMetaData {
did: string
assetName: string
timestamp: number
type: string
}
export default function ComputeJobs(): ReactElement { export default function ComputeJobs(): ReactElement {
const { ocean, account } = useOcean() const { ocean, account, config } = useOcean()
const [jobs, setJobs] = useState<ComputeJobMetaData[]>() const { accountId } = useWeb3()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [jobs, setJobs] = useState<ComputeAsset[]>([])
const { data } = useQuery<ComputeOrders>(getComputeOrders, {
variables: {
user: accountId?.toLowerCase()
}
})
useEffect(() => { useEffect(() => {
async function getTitle(did: string) { if (data === undefined || !config?.metadataCacheUri) return
const ddo = await ocean.metadataCache.retrieveDDO(did)
const metadata = ddo.findServiceByType('metadata')
return metadata.attributes.main.name
}
async function getJobs() { async function getJobs() {
if (!ocean || !account) return if (!ocean || !account) return
setIsLoading(true)
try {
const orderHistory = await ocean.assets.getOrderHistory(
account,
'compute',
100
)
const jobs: ComputeJobMetaData[] = []
for (let i = 0; i < orderHistory.length; i++) { setIsLoading(true)
const assetName = await getTitle(orderHistory[i].did)
const dtList = []
const dtTimestamps = []
const computeJobs: ComputeAsset[] = []
for (let i = 0; i < data.tokenOrders.length; i++) {
dtList.push(data.tokenOrders[i].datatokenId.address)
dtTimestamps.push(data.tokenOrders[i].timestamp)
}
const queryDtList = JSON.stringify(dtList)
.replace(/,/g, ' ')
.replace(/"/g, '')
.replace(/(\[|\])/g, '')
try {
const source = axios.CancelToken.source()
const assets = await getAssetMetadata(
queryDtList,
config.metadataCacheUri,
source.token,
dtTimestamps
)
const providers: ServiceCompute[] = []
for (let i = 0; i < data.tokenOrders.length; i++) {
try {
const did = web3.utils
.toChecksumAddress(data.tokenOrders[i].datatokenId.address)
.replace('0x', 'did:op:')
const ddo = assets.filter((x) => x.id === did)[0]
if (!ddo) continue
const service = ddo.service.filter(
(x: ServiceCommon) => x.index === data.tokenOrders[i].serviceId
)[0]
if (!service || service.type !== 'compute') continue
const { serviceEndpoint } = service
const wasProviderQueried =
providers.filter((x) => x.serviceEndpoint === serviceEndpoint)
.length > 0
if (wasProviderQueried) continue
providers.push(service as ServiceCompute)
// eslint-disable-next-line no-empty
} catch (err) {
console.log(err)
}
}
for (let i = 0; i < providers.length; i++) {
const computeJob = await ocean.compute.status( const computeJob = await ocean.compute.status(
account, account,
orderHistory[i].did,
undefined, undefined,
undefined, undefined,
orderHistory[i].transactionHash, providers[i],
undefined,
undefined, undefined,
false false
) )
computeJob.forEach((item) => { computeJob.sort((a, b) => {
jobs.push({ if (a.dateCreated > b.dateCreated) {
did: orderHistory[i].did, return -1
jobId: item.jobId, }
dateCreated: item.dateCreated, if (a.dateCreated < b.dateCreated) {
dateFinished: item.dateFinished, return 1
assetName: assetName,
status: item.status,
statusText: item.statusText,
algorithmLogUrl: '',
resultsUrls: []
})
})
} }
const jobsSorted = jobs.sort((a, b) => {
if (a.dateCreated > b.dateCreated) return -1
if (a.dateCreated < b.dateCreated) return 1
return 0 return 0
}) })
setJobs(jobsSorted) for (let j = 0; j < computeJob.length; j++) {
const job = computeJob[j]
const did = job.inputDID[0]
const ddo = assets.filter((x) => x.id === did)[0]
if (!ddo) continue
const serviceMetadata = ddo.service.filter(
(x: any) => x.type === 'metadata'
)[0]
const compJob = {
did: did,
jobId: job.jobId,
dateCreated: job.dateCreated,
dateFinished: job.dateFinished,
assetName: serviceMetadata.attributes.main.name,
status: job.status,
statusText: job.statusText,
algorithmLogUrl: '',
resultsUrls: [],
timestamp: data.tokenOrders[i].timestamp,
type: ''
} as ComputeAsset
computeJobs.push(compJob)
}
}
setJobs(computeJobs)
} catch (error) { } catch (error) {
Logger.log(error.message) Logger.log(error.message)
} finally { } finally {
@ -129,7 +246,7 @@ export default function ComputeJobs(): ReactElement {
} }
} }
getJobs() getJobs()
}, [ocean, account]) }, [ocean, account, data, config?.metadataCacheUri])
return ( return (
<Table <Table