Interest Manager Batch Jobs

Prev Next

Interest Manager Batch Jobs

Last Updated: Oct 2, 2026
Operational guide for the scheduled/batch Apex jobs shipped with Interest Manager.

Class Type Purpose Default schedule Batch size
FPMRuleRecalcBatch Batchable + Schedulable Re-evaluates research eligibility on Preference Rules Daily 01:00 200
FPMPreferenceSearchStorageBatchDelete Batchable (Stateful) Purges old Search Result rows from FPM_Log__c Run through the cleaner below 2000
FPMPreferenceSearchStorageCleaner Schedulable (wrapper) Schedules/launches the purge batch with a retention period and an optional key filter Daily 02:00 (all results, 7 days), daily 03:00 (UI cache, 1 day) 2000

1. FPMRuleRecalcBatch – Research Eligibility Recalculation

Purpose

Makes sure a Preference Rule's research access matches the Contact's current eligibility. A rule's eligibility can change with no edit to the rule itself, for example when:

  • A Contact or Account attribute used by a research validation rule changes (e.g. Account Tier).
  • The rule's configuration changes indirectly (e.g. delivery options removed or added outside the Rule Builder).
  • A temporary research approval starts or ends its effective date range (Start_Date__c / End_Date__c).

What it processes

Preference_Rule__c records where:

  • Is_Active__c = true
  • Research_Status__c != 'Pending for Approval'
  • Contact__c != null

Each rule is checked with FPMResearchRuleValidationService.validatePreferenceRuleEligibility(...).

Outcome per record

Current state Evaluation Action
Not Inactive Not eligible Set Research_Status__c = Inactive, set Research_Inactive_Rule__c to the first failing rule
Inactive Eligible Clear research status (FPMRuleController.clearResearchStatus)
Not Inactive Delivery_Options__c blank Set to Inactive (no failing rule name)
Anything else – No change (record is not updated)

Only changed records are updated. Each chunk gets its own FPMTransactionContext.batchId, so the audit log can group the changes made by one run.

How to run

Schedule (recommended) – Developer Console › Execute Anonymous:

String cron = '0 0 1 * * ?'; // 01:00 daily
System.schedule('FPM Rule Research Recalc - Daily', cron, new FPMRuleRecalcBatch());

Run once on demand (e.g. after a bulk Account/Contact data load or a change to research validation rules):

Database.executeBatch(new FPMRuleRecalcBatch(), 200);

Running it on demand is the only way to use a batch size other than 200; the scheduled entry point always uses 200.

Recommendations

  • Frequency: Daily. It is safe to run more often (e.g. every 4–6 hours) if temporary approvals need to take effect within the same day. Running it less than daily means research access can stay wrong for more than a day after the effective date passes.
  • Time window: Off-hours, before the business day starts and after the nightly data loads/integrations that update Contact/Account attributes.
  • Running user: The job evaluates eligibility as the user who scheduled it (UserInfo.getUserId()), and records that user as the acting user in the audit log. Schedule it as a dedicated admin/integration user who can see all Contacts, Accounts and Preference Rules. A user with limited visibility can produce wrong eligibility results.
  • Expected duration: Runtime grows with the number of active Preference Rules (one validation call per rule). As a rule of thumb, plan for minutes for tens of thousands of rules. Check the actual runtime in your org (Setup › Apex Jobs) after the first run and keep it well inside the off-hours window.
  • Batch size: Keep the default of 200. If you see CPU time or SOQL limit errors (orgs with many research validation rules), run on demand with 50–100.
  • Monitoring: Errors are only written to the debug log. When a DML failure happens, the whole chunk of up to 200 records is not updated and the job still reports success. Check Setup › Apex Jobs for failures, and if research status looks stale, run the job on demand with debug logging turned on for the running user.

2. FPMPreferenceSearchStorageBatchDelete / FPMPreferenceSearchStorageCleaner – Search Result Storage Cleanup

Purpose

Interest Manager search stores result snapshots in FPM_Log__c with Log_Type__c = 'Search Result'. They come from two sources:

Source Job_Key__c value Growth rate
Asynchronous / API search jobs 18‑character Apex Job Id (never contains :) Low
Synchronous UI list pagination cache (ACE List / Interest Manager Search) Composite key <aceListId>:<userId>:<criteriaHash>:<nonce> (always contains :) High – one per search/paging session

If they are never removed, these rows use up data storage. The cleanup batch hard-deletes Search Result rows older than a retention period. It can also be limited to one family of keys with a SOQL LIKE pattern, so the fast-growing UI cache can be purged on a shorter schedule without affecting API results.

FPMPreferenceSearchStorageCleaner is the Schedulable wrapper: it passes the retention period and pattern through and runs the batch with a scope of 2000.

Retention behaviour

  • Cutoff = midnight (00:00) of today − retentionDays. Rows are deleted based on CreatedDate, so the time a row is actually kept is between retentionDays and retentionDays + 1 days.
  • The minimum retentionDays is 1. Values below 1 are treated as 1.
  • Pattern null = all Search Result rows (API and UI cache).
  • Pattern FPMPreferenceSearchStorageCleaner.UI_CACHE_JOB_ID_PATTERN ('%:%') = UI cache rows only.
  • Partial success is allowed. A row that cannot be deleted is skipped and does not stop the rest of the chunk. Errors are not logged.
  • Cleanup does not decide whether a cached snapshot is still served. The UI cache stops using a snapshot after SyncSearchCacheStalenessMinutes (AFR feature attribute, default 30 minutes), whatever its physical retention. Any UI cache row older than that is just using storage.

How to run

Recommended setup – two schedules (Execute Anonymous):

// 1) All search results (API + UI) – keep 7 days, daily 02:00
System.schedule('FPMPreferenceSearchStorageCleaner_Daily',
    '0 0 2 * * ?', new FPMPreferenceSearchStorageCleaner(7));

// 2) UI paging cache only – keep 1 day, daily 03:00
System.schedule('FPMPreferenceSearchStorageCleaner_UICache',
    '0 0 3 * * ?',
    new FPMPreferenceSearchStorageCleaner(1, FPMPreferenceSearchStorageCleaner.UI_CACHE_JOB_ID_PATTERN));

Helper method (the job name is generated as FPM Preference Search Storage Cleaner plus (<pattern>) when a pattern is given):

FPMPreferenceSearchStorageCleaner.schedule('0 0 2 * * ?', 7);
FPMPreferenceSearchStorageCleaner.schedule('0 0 3 * * ?', 1, FPMPreferenceSearchStorageCleaner.UI_CACHE_JOB_ID_PATTERN);

Job names must be unique. Calling the helper again with the same pattern fails until the existing scheduled job is deleted (Setup › Scheduled Jobs).

Run once on demand (e.g. to free storage right away):

Database.executeBatch(new FPMPreferenceSearchStorageBatchDelete(7), 2000);
// UI cache only
Database.executeBatch(new FPMPreferenceSearchStorageBatchDelete(1, '%:%'), 2000);

Recommendations

Sweep Retention Frequency Notes
All search results 7 days (increase if API consumers need to fetch results later) Daily API callers must retrieve async job results within this window
UI cache only 1 day (the minimum) Daily; can be scheduled several times a day in high-volume orgs Snapshots are stale after 30 min anyway, so shorter retention has no functional impact
  • Time window: Off-hours, after FPMRuleRecalcBatch has finished, so the jobs don't compete for async capacity. Stagger the two cleaner schedules (e.g. 02:00 and 03:00).
  • Expected duration: Usually short (a delete with scope 2000). The first run in an org that has built up a large backlog can take much longer. Consider running it on demand outside business hours before you enable the schedule.
  • Storage: Deleted rows go to the Recycle Bin first and are permanently removed by Salesforce later. Expect the storage numbers in Setup › Storage Usage to drop with some delay.
  • Running user: Must have delete access to FPM_Log__c. Use the same admin/integration user as the recalc job.

3. Suggested nightly schedule

Time Job Scheduled job name
01:00 FPMRuleRecalcBatch FPM Rule Research Recalc - Daily
02:00 FPMPreferenceSearchStorageCleaner(7) FPMPreferenceSearchStorageCleaner_Daily
03:00 FPMPreferenceSearchStorageCleaner(1, '%:%') FPMPreferenceSearchStorageCleaner_UICache

Times are in the timezone of the user who schedules the job. Change them to suit your nightly integration window.

4. Operations checklist

  • Check status: Setup › Apex Jobs (each run) and Setup › Scheduled Jobs (schedules).
  • Stop or reschedule: Delete the schedule in Setup › Scheduled Jobs, or run System.abortJob(<CronTrigger Id>), then schedule it again.
  • Deployments: Scheduled Apex locks the class. Delete the schedules before deploying changes to these classes, and schedule them again afterwards (or allow deployments with Apex jobs in Setup › Deployment Settings).
  • Sandbox refresh: Scheduled jobs are not copied to a refreshed sandbox. Schedule them again after each refresh.