rspec/rules/S5526/apex/rule.adoc
Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
Inline adoc files when they are included exactly once.

Also fix language tags because this inlining gives us better information
on what language the code is written in.
2023-05-25 14:18:12 +02:00

91 lines
3.0 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

== Why is this an issue?
There are three limits related to methods annotated with the ``++@future++`` keyword:
* There is a maximum number of ``++@future++`` calls allowed per transaction.
* There is a maximum number of ``++@future++`` calls allowed per organization and per a 24-hour period.
* Salesforce protects its infrastructure from organizations calling too many ``++@future++`` methods: if more than 2000 ``++@future++`` requests are queued, any additional request https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_invoking_future_methods.htm[will be delayed].
Thus it is a best practice to avoid calling ``++@future++`` methods in loops and instead call it once with all the necessary data.
See https://developer.salesforce.com/docs/atlas.en-us.222.0.apexcode.meta/apexcode/apex_gov_limits.htm[Execution Governors and Limits] for the exact number of ``++@future++`` calls allowed in each context.
This rule raises an issue when a method annotated with the ``++@future++`` keyword is called in a loop.
=== Noncompliant code example
[source,apex]
----
public class FutureClass {
@future
public static void processTaskFuture(ID taskId) {
Task task = [SELECT Id, Subject FROM Task WHERE Task.Id = :taskId];
task.Subject = 'new task subject';
update task;
}
public static void updateUserTasks(ID ownerID) {
List<Task> tasks = [SELECT Id, Subject FROM Task WHERE Task.ownerid = :ownerID];
for (Task task: tasks) {
processTaskFuture(task.Id); // Noncompliant
}
}
----
=== Compliant solution
[source,apex]
----
public class FutureClass {
@future
public static void processTasksFuture(List<ID> taskIds) {
List<Task> tasks = [SELECT Id, Subject FROM Task WHERE Task.Id IN :taskIds];
for (Task task : tasks) {
task.Subject = 'new task subject';
}
update tasks;
}
public static void updateUserTasks(ID ownerID) {
List<Task> tasks = [SELECT Id, Subject FROM Task WHERE Task.ownerid = :ownerID];
List<Id> ids = new List<ID>();
for (Task task: tasks) {
ids.add(task.Id);
}
processTasksFuture(ids);
}
----
== Resources
* https://developer.salesforce.com/page/Apex_Code_Best_Practices[Apex Code Best Practices]
* https://developer.salesforce.com/docs/atlas.en-us.222.0.apexcode.meta/apexcode/apex_gov_limits.htm[Execution Governors and Limits]
* https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_invoking_future_methods.htm[Future Methods]
* https://trailhead.salesforce.com/content/learn/modules/asynchronous_apex/async_apex_future_methods[Use Future Methods]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Move this "@future" method call out of the loop
=== Highlighting
Primary location: the call to the @future method.
Secondary location: the "do", "while" or "for" keyword of the loop.
endif::env-github,rspecator-view[]