deliver method
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;
}