handleLiveTestCampaign method
void
handleLiveTestCampaign(
- LiveTestInvocation invocation
Handles one campaign_test SSE event: ACKs received, then routes the
inline campaign through the same _routeStoredCampaign path an organic
CEP trigger uses.
Implementation
void handleLiveTestCampaign(LiveTestInvocation invocation) {
LiveTestAckReporter.instance.postReceived(invocation.testInvocationId);
// Rare but possible: the live-test stream can connect before the
// campaign fetch resolves. Guard like onCampaignTriggered does.
if (_sdkState != SDKState.ready) {
LiveTestAckReporter.instance.postFailed(
invocation.testInvocationId,
LiveTestFailureCode.renderError,
'SDK not ready (state=${_sdkState.name})',
);
return;
}
final campaignJson = invocation.campaign;
if (campaignJson == null) {
LiveTestAckReporter.instance.postFailed(
invocation.testInvocationId,
LiveTestFailureCode.campaignNotFound,
'campaign_test message had no usable campaign object',
);
return;
}
final campaign = CampaignModel.fromJson(campaignJson);
if (campaign == null) {
LiveTestAckReporter.instance.postFailed(
invocation.testInvocationId,
LiveTestFailureCode.templateError,
'campaign object could not be parsed into a renderable campaign',
);
return;
}
// CEPTriggerPayload.variables is Map<String, String> (every trigger path
// shares this shape); the wire payload's variables are arbitrary JSON.
final coercedVariables = <String, String>{
for (final entry in invocation.variables.entries)
entry.key: entry.value.toString(),
};
final cepCampaignId = liveTestCepId(invocation.testInvocationId);
final payload = CEPTriggerPayload(
cepCampaignId: cepCampaignId,
cepMetadata: const {},
campaignKey: campaign.campaignKey,
variables: coercedVariables,
);
// Also clears the impression dedup mark for this id — otherwise it'd
// leak one entry per live-tested inline campaign for the process's life.
void cleanUpLiveTestState() {
_liveTestContexts.remove(cepCampaignId);
_liveTestCampaigns.remove(cepCampaignId);
_events.resetImpression(cepCampaignId);
}
final testContext = LiveTestContext(
testInvocationId: invocation.testInvocationId,
onTerminal: cleanUpLiveTestState,
);
_liveTestContexts[cepCampaignId] = testContext;
_liveTestCampaigns[cepCampaignId] = campaign;
final accepted = _routeStoredCampaign(
campaign,
payload,
context: _LiveTestRoutingContext(testContext),
);
if (!accepted) {
// Drop branches already report their own failure; this just cleans up.
cleanUpLiveTestState();
}
}