handleLiveTestCampaign method

void handleLiveTestCampaign(
  1. 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();
  }
}