Inventory Harvester
Owner: Org Chat / Introspection.
Apex: FMOrgInventoryHarvester (Queueable + AllowsCallouts), FMOrgInventoryScheduler (Schedulable).
Object: FM_Org_Inventory_Snapshot__c.
Cache: local.FMLLMCache (single-flight key invharvinflight, 900s TTL).
Cron: FM Org Inventory Nightly default 0 0 2 * * ? * (02:00 UTC daily).
MDT: FM_Config.orgChatInventoryCron.
What it does
Harvests org-wide component inventory into FM_Org_Inventory_Snapshot__c so Org Chat's inventory_search tool can answer "what triggers fire on Lead?" without re-querying Tooling per turn.
One execute walks 5 component types sequentially in a single transaction (refactored from chained Queueables; the original chain hit the 5-deep depth cap on PermissionSet):
ApexClass. Tooling RESTApexTrigger. Tooling REST (capturesTableEnumOrId)FlowDefinitionView. Standard SOQL underSYSTEM_MODE(NOT a Tooling sObject)ValidationRule. Tooling RESTPermissionSet. Standard SOQL underSYSTEM_MODE
Healthy steady state
System.debug([
SELECT Component_Type__c, COUNT(Id) c
FROM FM_Org_Inventory_Snapshot__c
GROUP BY Component_Type__c
]); Reference baseline (single sandbox, post 2026-04-27 enable): 570 ApexClass, 65 PermissionSet, 1 FlowDefinitionView. Triggers + validation rules counts are org-shape dependent.
List<CronTrigger> ct = [
SELECT Id, NextFireTime, State, CronExpression
FROM CronTrigger
WHERE CronJobDetail.Name = 'FM Org Inventory Nightly'
];
System.debug(ct); Expect exactly 1 row, State = WAITING, NextFireTime within 24 h.
Failure modes
F1. "sObject type 'FlowDefinitionView' is not supported"
Cause. Tooling REST doesn't expose FlowDefinitionView or PermissionSet. Both must go through standard Database.query under SYSTEM_MODE.
Fix. Already encoded in harvestType. If this surfaces, someone reverted the routing.
F2. System.AsyncException: Maximum stack depth has been reached
Cause. Old chained-Queueable harvester re-introduced. Chain depth cap is 5 in dev orgs, 100 in prod; chaining one Queueable per type hits the dev cap on type 5.
Fix. Single execute() walks all types in one transaction. Total budget is well under per-transaction cap (≤20 callouts, ≤2000 rows upserted).
F3. Schedulable blocks redeploy of FMOrgInventoryHarvester
Symptom. Deploy fails with "Cannot delete this class because it is referenced elsewhere."
Recovery:
// 1. Abort the cron
for (CronTrigger ct : [
SELECT Id FROM CronTrigger
WHERE CronJobDetail.Name = 'FM Org Inventory Nightly'
]) {
System.abortJob(ct.Id);
}
// 2. Redeploy the class
// sf project deploy start --target-org Flowmason \
// --source-dir force-app/main/default/classes/FMOrgInventoryHarvester.cls
// 3. Re-schedule
FMOrgInventoryScheduler.ensureScheduled(); F4. Inventory stale / partial run
Force a fresh harvest: FMOrgInventoryHarvester.enqueue();. Single-flight cache prevents duplicate enqueue if one is already running.
F5. Single-flight cache wedge
Symptom. enqueue() returns the same job id repeatedly even after that job finished.
Cause. finalize() threw before clearing invharvinflight. TTL is 900 s; wait it out, or evict manually:
Cache.OrgPartition p = Cache.Org.getPartition('local.FMLLMCache');
p.remove('invharvinflight'); Manual operations
Force a harvest now
String jobId = FMOrgInventoryHarvester.enqueue();
System.debug('Harvest job: ' + jobId); Re-schedule with a new cron
Update FM_Config.orgChatInventoryCron, abort the existing CronTrigger, then call FMOrgInventoryScheduler.ensureScheduled().
Disable harvest entirely
No MDT switch. Disablement is operational. Abort the cron. The inventory_search tool degrades to "inventory not yet harvested" when the table is empty.
Purge inventory + re-harvest from scratch
Database.delete([SELECT Id FROM FM_Org_Inventory_Snapshot__c LIMIT 10000], false);
FMOrgInventoryHarvester.enqueue(); Telemetry
Every run publishes one of:
org_inventory_harvest_completed.Detail__cJSON:{"runId":"r…","rows":{"ApexClass":570,…}}org_inventory_harvest_failed. Per-type error.{"runId":"r…","type":"FlowDefinitionView","error":"…"}
Subscribe via FlowMasonRun__e → FlowMasonRunSubscriber → FM_Run_Audit__c. See fmTelemetryDashboard for the rollup.
Related
- Org Introspection — INV-1 + INV-2 architecture
- Incident Response — broader operational playbook
- Admin Manual — day-to-day ops