Existing leads
Leads that arrive reach a running campaign, so a new campaign knows nothing of the leads you already have. A backfill runs them through its filter and onLead, only when you ask: never on a deploy or a resume.
It works while the campaign is paused, and nothing dials until it runs, so you can backfill, see how many enrolled, then turn it on.
const run = await hcc.campaigns.backfill('renewals');
const now = await hcc.campaigns.backfillStatus('renewals');
// { status: 'running', scanned: 40000, checked: 900, enrolled: 310, skipped: 500, failed: 0, ... }
await hcc.campaigns.cancelBackfill('renewals');
await hcc.campaigns.retryBackfill('renewals');Who it takes
- The filter comes first, then
onLead. Both are what you deployed in.enrolland.onLead: a backfill takes no filter of its own. A campaign with noonLeadtakes every lead that matches, with no call to your server. - Skips.
c.remove()here counts as a skip. A lead on your Do Not Call list stays out and counts as a skip too, whateveronLeadsays, thoughonLeadcan still be asked about it. - It's safe to repeat. A lead already in the campaign stays where it is, and your server isn't asked about it. A lead that left stays out, whatever
onLeadsays. The exception is aremovedone, whichonLeadcan bring back withc.enroll(), to start over, unless the campaign saysreenroll: false. With noonLeadit stays out. - While the campaign is running, the leads it enrolls can be dialed straight away, within calling hours and your limits.
How it runs
- The filter costs your server nothing, as a lead that doesn't match is never sent. It has no index, so a backfill reads every lead in the environment in small steps. A deploy during a run can narrow it, as a lead has to match the filter it started with and the one deployed now.
- It goes at your server's pace. At most 4 batches of 50 are unanswered at once, and the next goes when one's answered. Each lead's
ctx.eventIdis stable across this run's retries and new on the next run. - It can't pause your campaign. If your server fails it backs off for about a quarter of an hour, and carries on if it comes back. If not, the run ends as
failed, withfailuresaying why, andretryBackfillgoes on from where it stopped. - A
donerun can havefailedleads too, when your handler failed for some:retryBackfillasks about only those. - One at a time per campaign: a second
backfillgets a 409. It needscampaigns:write.
testCampaign has it too: await t.backfill([gold, silver]) says who'd be enrolled and skipped, and t.matches(lead) reads the filter just as we do.