deliver method

  1. @override
CampaignPresentation deliver(
  1. CEPTriggerPayload trigger
)
override

Delivers a CEP trigger into the Digia engine.

A total function: it never throws, and always returns a handle. A synchronous rejection — unknown key, invalid config, missing anchor — returns an already settled presentation, so the caller has one code path either way.

Returns synchronously, and must keep doing so: the handle is a receipt, not an answer. The answer arrives later on CampaignPresentation.outcome. A plugin needs its synchronous grip on the handle because a CEP can close a template milliseconds after presenting it — without it, cancel() would be racy and the plugin would need a side-map to correlate CEP context with a handle that arrives later.

Implementation

@override
CampaignPresentation deliver(CEPTriggerPayload trigger) {
  final plugin = _activePlugin;
  final controller = _coordinator.open(
    trigger,
    owner: plugin?.id ?? '<detached>',
  );
  // Before the state gate, so a trigger that is refused outright still shows
  // up on the timeline as having arrived. "Nothing happened at all" and "it
  // arrived and we turned it away" are the two answers a campaign creator
  // most needs to tell apart.
  observeDelivery(controller);
  if (plugin == null) {
    // A CEP callback that outlived its plugin. Settling immediately is what
    // makes the handle total: the caller awaits the same outcome it would
    // for any other rejection.
    controller.settle(const PresentationDropped(
      reason: DropReason.pluginDetached,
      detail: 'no plugin is attached',
    ));
    return controller.presentation;
  }
  // Nothing is held before ready (startup plan SP5): the trigger settles at
  // once, which hands the CEP its slot back. The reason tells apart
  // "never called", "still fetching" and "the fetch failed".
  final (DropReason, String)? drop = switch (_sdkState) {
    SDKState.notInitialized => (
        DropReason.notInitialized,
        'Digia.initialize() has not been called',
      ),
    SDKState.initializing => (
        DropReason.notReady,
        'Campaigns are still loading; trigger dropped',
      ),
    SDKState.failed => (
        DropReason.initializationFailed,
        'Campaign fetch failed; trigger dropped',
      ),
    SDKState.ready => null,
  };
  if (drop == null) {
    _routeDelivered(controller);
  } else {
    final (reason, detail) = drop;
    _log.w('Dropped — $detail', campaign: trigger.campaignKey);
    controller.settle(PresentationDropped(reason: reason, detail: detail));
  }
  return controller.presentation;
}