Notify LWC when Queueable Job finishes

Notify LWC when Queueable job finishes becomes important in many use cases. However, when calling this with Lightning Web Components, a common challenge is how to notify LWC when the job finishes. This blog will walk you through the process of setting up a notification system for LWCs when a queueable job completes, ensuring a seamless user experience using platform events.

Architecture Overview

The overall solution involves the following components:

  1. Queueable Apex Class: Executes the background process.
  2. Platform Event: Triggers when the job completes to notify subscribers.
  3. LWC: Subscribes to the platform event and displays a notification to the user.

Implementation Steps for Notify LWC

Set Up Platform Event

Create a platform event Queueable_Event__e with fields to hold relevant information about the job completion.
Label: Queueable Event
API Name: Queueable_Event__e
Fields: Job_Id__c (Text)

Notify LWC when Queueable job finishes using Platform events. it becomes important in many use cases

Create the Queueable Class

Create an Apex queueable class with name QueueableRecipes that performs the update on account records. Once the job finishes, it fires a platform event with job id of the queueable job to notify LWC. executeQueueable method will invoke from button click in LWC. This will schedule the queueable class to execute and returns job id back to lwc.

public with sharing class QueueableRecipes implements Queueable {
    public static void execute(QueueableContext qc) {
        List<Account> accounts = [
            SELECT Id, Type
            FROM Account
            LIMIT 1000
        ];
        for (Account acct : accounts) {
            acct.Type = 'Prospect';
        }
        try {
            update accounts;
            Queueable_Event__e event = new Queueable_Event__e(Job_Id__c = qc.getJobId());
            EventBus.publish(event);
        } catch (DmlException dmle) {
            System.debug(dmle);
        }
    }

    @auraEnabled
    public static String executeQueueable() {
        return System.enqueueJob(new QueueableRecipes());
    }
}

Lightning Web Component – QueueableTracker

QueueableTracker.html

Execute Queueable button will fire the apex method which will schedule the queueable job to execute. The spinner will be shown up and message will be displayed about job status.

<template>
	<div class="slds-card">
		<div class="slds-notify_container slds-is-relative">
			<div class="slds-notify slds-notify_toast slds-theme_success" role="status">
				<div class="slds-notify__content">
                    <lightning-spinner alternative-text="Loading" size="large" lwc:if={executionInProgress}></lightning-spinner>
					<h2 class="slds-text-heading_small ">{executionMessage}</h2>
				</div>                
			</div>
		</div> 
        <div class="slds-align_absolute-center" >
            <lightning-button label="Execute Queueable" variant="brand" onclick={handleExecute}></lightning-button>
        </div>       
	</div>
</template>
QueueableTracker.js

empApi module allows to subscribe to platform events directly in LWC. Subscriber callback checks for response matching with queueable job id and display results based on it. Platform event fired from Queueable class notify LWC about its running status.

import { LightningElement } from 'lwc';
import executeQueueable from '@salesforce/apex/QueueableRecipes.executeQueueable';
import {
    subscribe,
    unsubscribe,
    onError
} from 'lightning/empApi';
export default class QueueableTracker extends LightningElement {
    executionMessage = 'Job has not started yet';
    executionInProgress;
    queueableJobId;
    channelName = '/event/Queueable_Event__e';
    subscription = {};

    async handleExecute(){                
        try{
            this.executionMessage = 'Queueable job is executing now';
            this.executionInProgress = true;
            this.queueableJobId = await executeQueueable();
            console.log('this.queueableJobId ',this.queueableJobId);
        }catch(error){
            console.log(error);
            this.executionInProgress = false;
        }        
    }

    // Initializes the component
    connectedCallback() {
        // Register error listener
        this.registerErrorListener();
        this.handleSubscribe();
    }

    // Handles subscribe button click
    handleSubscribe() {
        // Callback invoked whenever a new event message is received
        const messageCallback = function (response) {
            console.log('New message received: ', JSON.stringify(response));
            console.log('New message received: ', response.data.payload.Job_Id__c, this.queueableJobId);
            // Response contains the payload of the new message received
            if(response && response.data && response.data.payload && response.data.payload.Job_Id__c && response.data.payload.Job_Id__c == this.queueableJobId){
                this.executionMessage = 'Queueable job is finished now';
                this.executionInProgress = false;
            }
        };

        // Invoke subscribe method of empApi. Pass reference to messageCallback
        subscribe(this.channelName, -1, messageCallback.bind(this)).then((response) => {
            // Response contains the subscription information on subscribe call
            console.log(
                'Subscription request sent to: ',
                JSON.stringify(response.channel)
            );
            this.subscription = response;
        });
    }

    // Handles unsubscribe button click
    disconnectedCallback() {
        // Invoke unsubscribe method of empApi
        unsubscribe(this.subscription, (response) => {
            console.log('unsubscribe() response: ', JSON.stringify(response));
            // Response is true for successful unsubscribe
        });
    }

    registerErrorListener() {
        // Invoke onError empApi method
        onError((error) => {
            console.log('Received error from server: ', JSON.stringify(error));
            // Error contains the server-side error
        });
    }
}
QueueableTracker.js-meta.xml

We exposed the component for home page. You can deploy and place this component on home page for demo.

<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>57.0</apiVersion>
	<isExposed>true</isExposed>
	<targets>
		<target>lightning__HomePage</target>
	</targets>
</LightningComponentBundle>

Demo – Notify LWC when Queueable job is finished

Do you need help?

Are you stuck while working on this requirement? Do you want to get review of your solution? Now, you can book dedicated 1:1 with me on Lightning Web Component completely free.

GET IN TOUCH

Schedule a 1:1 Meeting with me

Also checkout this https://salesforcediaries.com/category/lightning-web-component

Leave a Reply