I have a queueable class that is triggered from a trigger that makes a callout. I wanted to use Queueable for scenarios where I need to insert 3-5k of records and eventually make 3-5k callouts. But the queueable goes into a loop even when I insert only 5 records and it takes so long to abort the job once it's started. any help is appreciated

trigger LeadTrigger on Lead (before insert, before update) {
    List<Id> userIds =  new List<Id>();
    for (Lead objLead : Trigger.new) {
        if(!System.isFuture() || !System.isQueueable()){
        if (userIds != null && (!System.isFuture() || !System.isQueueable())) {
            System.enqueueJob(new KeyApiQueueable (userIds));


public with sharing class KeyApiQueueable implements Queueable, Database.AllowsCallouts {
    public List<Id> recordIds;

    public KeyApiQueueable (list<id> ids){
        this.recordIds = ids;

    public void execute(QueueableContext context) {
        Lead[] leadsToUpdate = new lead[0];
        while(recordIds.size() > 0 && leadsToUpdate.size() < 100) { // Max 100 callouts allowed here
            Id nextId = recordIds.remove(0);
        update leadsToUpdate;

        if(recordIds.size() > 0) {

    public static Lead processPayload(Id recordId){
        List<Lead> leadAccount = [SELECT Id, deger1__c, deger2__c FROM Lead WHERE Id =: recordId];
        Lead leadAccounts = leadAccount[0];
        Integer Value2;
        Integer Value3;

        HttpRequest request= new HttpRequest();

            Http http=new Http();
            HttpResponse response=http.send(request);

            if (response.getStatusCode() == 200) {
                Map<String,Object> results = (Map<String,Object>)Json.deserializeUntyped(response.getBody());
                Value2= Integer.valueof(results.get('sweetness'));
                Value3 = Integer.valueof(results.get('saltiness'));
            leadAccounts.deger1__c = Value3;
            leadAccounts.deger2__c = Value2;  
        catch(System.CalloutException e){
            system.debug('Error-' + e.getMessage());  
        return leadAccounts;

1 Answer 1

if (userIds != null && (!System.isFuture() || !System.isQueueable())) {

Is incorrect. If you're in a future call, you won't be in a queueable call, and if you're in a queueable call, you won't be in a future call. Both TRUE || FALSE and FALSE || TRUE will result in a TRUE result every time. You meant to use &&, instead:

if (userIds.size() > 0 && !System.isFuture() && !System.isQueueable()) {

I know this tends to confuse newer programmers, since in normal English, we often say "or" instead of "and" in some places. You may want to refresh your memory on how && and || work with some truth tables. Once you get used to it, you'll hardly ever make that mistake.

Also, note that userIds can't be null, no need to check for that here, but you probably want to check if the list is empty first.

  • I will go over the logical operators once again, Thank you @sfdcfox that fixed the issue.
    – kkJhn
    Sep 30, 2022 at 16:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .