0

I am trying to implement a progress bar indicator for APEX Jobs that are running in the background, however when I call the APEX method through the setInterval method, it is returning the same values again, and the values are not getting updated. Every 4 Seconds it gives the same output.

    import { LightningElement, wire,api } from 'lwc';
    import {subscribe, MessageContext} from 'lightning/messageService';
    import recordSelected from '@salesforce/messageChannel/unrelatedcomponent__c';
    import getJobDetails from '@salesforce/apex/GetJobDetailForProgressbar.getJobDetails';


    export default class Progressbarlms extends LightningElement {

    subscription = null;
    // @api result = [];
    @api progress = 0;
    @api progressresult;

    @api c = 10;
   
    @api batchidd = '';
    @wire(MessageContext)
    selectedrecord;

    connectedCallback(){
        this.subscribeToMessageChannel();
    }

    subscribeToMessageChannel(){
        this.subscription = subscribe(
            this.selectedrecord, 
            recordSelected, 
            (record)=>this.handleRecordSelected(record)
        );
        console.log('Inside unrelatedcomponent');
    }

    handleRecordSelected(record){
        this.batchidd = record.Batchid;
        console.log('Inside unrelatedcomponent selectedRecords', this.batchidd);
        if(this.c==10){
            console.log('inside if statement');
            this._interval = setInterval(()=>{this.getprogress()}, 4000);
        }

    }

    getprogress(){
        getJobDetails({Jobid: this.batchidd}).then((result) => {
            console.log(result);
        });
    }



    }

Output : data {JobItemsProcessed: 8, TotalJobItems: 300, Id: '7079I000001e13FQAQ'}

public class GetJobDetailForProgressbar {

     @AuraEnabled(cacheable=true)
         public static sObject getJobDetails(String Jobid){
        sObject jobDetail = [SELECT JobItemsProcessed, TotalJobItems FROM AsyncApexJob WHERE ID =: Jobid];
        // SELECT Status, NumberOfErrors,JobItemsProcessed,TotalJobItems FROM AsyncApexJob WHERE Id = :jobID
        return jobDetail;
    }

}

I've tried wiring the apex method and using refresh apex, but when I wire the Apex method, it only return the output as : data {JobItemsProcessed: 0, TotalJobItems: 0, Id: '7079I000001e13FQAQ'}

5
  • 1
    Post the apex code for it, I'm especially interested if you have @auraenabled(cache able=true) Commented Sep 20, 2022 at 16:22
  • Yes I've included @auraenabled(cacheable=true) Apex code: justpaste.it/9oefy Commented Sep 20, 2022 at 17:18
  • 1
    remove the cacheable, make it pure @AuraEnabled, should be better. I'll try to dig up my progress bar thing later this evening Commented Sep 20, 2022 at 17:26
  • Thank you so much, that worked, was it caching the values? And Showing the stored for better performance? Commented Sep 20, 2022 at 17:32
  • 1
    Yes, developer.salesforce.com/docs/component-library/documentation/…. It had no reason to "think" something changed server-side. Same input (in your case - batch job's id) -> same output. There are ways to have cacheable and force refresh too but sounds like overcomplicating it. What you need is simply no cache Commented Sep 20, 2022 at 17:34

1 Answer 1

1

No promises it'll work but here are relevant, anonymised bits of my old progress bar. It refreshes every 2 seconds

html

<template>
      Status: {job.Status}
      <lightning-progress-bar value={progress}></lightning-progress-bar>

      <lightning-button variant="success" label="Process" icon-name="utility:process" title="(Re) run the job"
          onclick={handleProcess}>
      </lightning-button>
</template>

js

import { LightningElement, wire } from 'lwc';
import getJobStatus from '@salesforce/apex/SomeClass.getJobStatus';
import processData from '@salesforce/apex/SomeClass.processData';

export default class someComponent extends LightningElement {
    progress = 0;
    job = {};
    timeout;

    handleProcess(event) {
        processData()
            .then(result => {
                this.job = result;
                this.updateProgress();
            });
    }

    updateProgress() {
        this.progress = Math.round((this.job.JobItemsProcessed * 100) / this.job.TotalJobItems);
        if (this.job.Status == 'Completed') {
            clearTimeout(this.timeout);
        } else {
            this.timeout = setTimeout(() => {
                getJobStatus({ i: this.job.Id })
                    .then(result => {
                        this.job = result;
                        this.updateProgress();
                    });
            }, 2000);
        }
    }
}

apex

public with sharing class SomeClass{

    @AuraEnabled
    public static AsyncApexJob processData(){
        return getJobStatus(Database.executeBatch(new SomeBatch()));
    }

    @AuraEnabled
    public static AsyncApexJob getJobStatus(Id i){
        return [SELECT Id, Status, JobItemsProcessed, TotalJobItems
            FROM AsyncApexJob
            WHERE Id = :i];
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.