deltaDAO / nautilus

The Data Economy TypeScript Toolkit
https://nautilus.delta-dao.com
Apache License 2.0
4 stars 2 forks source link

[BUG] GetComputeResult return before finishing the job #147

Open freevedo33 opened 2 months ago

freevedo33 commented 2 months ago

Summary

I tried to perform a compute flow with nautilus. When calling the getComputeResult in my function, it doesn't finish the job and return. I implemented a polling system which works fine, but is not nice to have. I hard coded the status 70 which refers to a finished job.

Current Behavior

Before implementing the polling system I tried to update the examples provided here to fit to my application. When not using the Polling system, the application will send me back:

[compute] Retrieve results: job does not exist or is not yet finished.

Here the code:

export async function computeDataset(req : Request, res : Response){
    const { datasetId, algorithmId} = req.body;
    try{
        const nautilus = await Nautilus.create(wallet, networkConfig);
        const dataset = {
            did : datasetId
        }
        const algorithm = {
            did : algorithmId
        }
        const computeJob = await nautilus.compute({
            dataset,
            algorithm
        });
        console.log("Compute result", computeJob)
        const computeResult = Array.isArray(computeJob) ? computeJob[0] : computeJob
        const { jobId } = computeResult;
        console.log(jobId);
        await getComputeStatus(nautilus, networkConfig.providerUri, jobId);
        const result = await retrieveComputeResult(nautilus, networkConfig.providerUri, jobId);

        console.log(result)

        // const data = computeResultUrl && await fetch(computeResultUrl)
        // console.log(data)
        //res.status(200).json({message : "Compute results", computeResult, computeJobStatus})
    }catch(error){
        console.error(error);
        res.status(500).json({ message : "Problem occured"})
    }
}

async function getComputeStatus(
    nautilus : Nautilus,
    providerUri: string,
    jobId: string){

    const computeJobStatus = await nautilus.getComputeStatus({
        jobId: jobId,
        providerUri
    });

    console.log(computeJobStatus);

}

async function retrieveComputeResult(
    nautilus : Nautilus,
    providerUri : string,
    jobId:  string
) {
  return  await nautilus.getComputeResult({
    jobId: jobId,
    providerUri
  });
}

Here my code with the polling system:

async function getComputeStatus(nautilus: Nautilus, providerUri: string, jobId: string) {
    const computeJobStatus = await nautilus.getComputeStatus({ jobId, providerUri });
    console.log(computeJobStatus);
    return computeJobStatus;
}

async function waitForComputeCompletion(nautilus: Nautilus, providerUri: string, jobId: string) {
    const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

    while (true) {
        const status = await getComputeStatus(nautilus, providerUri, jobId);

        if (status.status === 70) {
            break;
        }

        console.log(`Current status: ${status.status}. Waiting...`);
        await delay(5000); // Wait for 5 seconds before checking again
    }
}

async function retrieveComputeResult(nautilus: Nautilus, providerUri: string, jobId: string) {
    return await nautilus.getComputeResult({ jobId, providerUri });
}

Is there a better solution to handle the Promises instead of doing the polling system ?

I call these functions in another function which I then exposed to the routes of my API.

export async function computeDataset(req: Request, res: Response) {
    const { datasetId, algorithmId } = req.body;
    try {
        const nautilus = await Nautilus.create(wallet, networkConfig);
        const dataset = { did: datasetId };
        const algorithm = { did: algorithmId };

        const computeJob = await nautilus.compute({ dataset, algorithm });
        console.log("Compute result", computeJob);

        const computeResult = Array.isArray(computeJob) ? computeJob[0] : computeJob;
        const { jobId } = computeResult;
        console.log(jobId);

        await waitForComputeCompletion(nautilus, networkConfig.providerUri, jobId);

        const result = await retrieveComputeResult(nautilus, networkConfig.providerUri, jobId);
        console.log(result);

        res.status(200).json({ message: "Compute results", result });
    } catch (error) {
        console.error(error);
        res.status(500).json({ message: "Problem occurred" });
    }
}

Expected Behavior

I think it should work fine as in the example provided here . The compute job should completed before the results are sent back.

Steps to Reproduce

I am using Express to expose an API. I stored my network configuration in a variable but you can call it directly.

Environment

Anything else