The extension SPI lets libraries compose SDK primitives under their own operation subtypes without depending on internal implementation details.
Obtain the active extension context and reserve identities before executing the operations:
auto extension = aws::durable_execution::get_extension_context();
auto load = extension.reserve("load");
auto pause = extension.reserve(
"pause", std::string_view{"stable-pause-id"});
const auto value = load.step(
[] { return load_from_service(); },
"AcmeLoad");
pause.wait(std::chrono::seconds{5}, "AcmePause");Reservations are move-only and one-shot. Sequential reservations preserve
their IDs even when execution order changes. A local_operation_id derives an
ID independent of reservation order and must be unique within its durable
context.
Custom subtype strings must be nonblank and must not reuse SDK-owned subtype
tokens such as Step, Wait, or RunInChildContext.
extension_operation delegates to the same implementation used by normal SDK
operations:
stepstateful_stepwaitinvokecreate_callbackrun_in_child_context
This preserves retry, replay, checkpoint, serialization, plugin, and parent-child behavior while substituting the pre-reserved identity and custom subtype.
Stateful steps return extension_step_result<State>:
const int final_state = extension.reserve("poll").stateful_step<int>(
[](const std::optional<int>& state) {
const int current = state.value_or(0);
return current < 3
? aws::durable_execution::extension_step_result<int>::retry(
current + 1, std::chrono::seconds{1})
: aws::durable_execution::extension_step_result<int>::succeed(
current);
},
"AcmePoll",
0);The state is serialized into each retry checkpoint and restored on the next invocation. An optional exception retry strategy may replace the state before retrying.
A reservation can only be claimed in the durable context where it was created. Using a captured extension context or reservation from inside a durable step is rejected because durable operations cannot be nested inside step user code.