Skip to main content

Speculative Execution

Speculative execution runs commands against temporal state without persisting results. The aggregate state remains unchanged after speculative execution.


Use Cases

Use CaseDescription
Form Validation"Will this order succeed?" before user commits
Preview"What events would this command produce?"
TestingVerify business logic without polluting event store
Dry RunCheck if command would be accepted before executing

SpeculativeClient

The SpeculativeClient provides speculative execution across all coordinator types:

MethodDescription
aggregate()Test commands against aggregate state
projector()Test projections against events
saga()Test saga execution against events
process_manager()Test PM execution

Aggregate Speculative Execution

Test a command against temporal state (existing events + hypothetical events):

use angzarr_client::SpeculativeClient;
use angzarr_client::proto::SpeculateAggregateRequest;

// Connect to speculative client
let client = SpeculativeClient::connect("http://localhost:1310").await?;

// Build speculative request with temporal state
let request = SpeculateAggregateRequest {
command: Some(command_book),
events: prior_events, // Events to apply before command
};

// Execute without persistence
let response = client.aggregate(request).await?;

// Inspect what events WOULD be produced
for page in response.events.as_ref().unwrap().pages.iter() {
println!("Would produce: {}", page.event.as_ref().unwrap().type_url);
}

// Original aggregate is unchanged!

Form Validation Example

Validate a user action before they commit:

User fills out order form:
- Product: Widget (ID: widget-123)
- Quantity: 100
- Payment: Credit Card ending 4242

Before "Place Order" button is enabled:

1. Client sends speculative command to Order aggregate
2. Order aggregate checks:
- Does product exist? ✓
- Is quantity available? ✓
- Is payment method valid? ✓
3. Returns projected OrderCreated event

If speculative execution succeeds → Enable "Place Order" button
If speculative execution fails → Show validation error

No events persisted, no side effects!

Saga Speculative Execution

Test how a saga would react to events:

use angzarr_client::proto::SpeculateSagaRequest;

let request = SpeculateSagaRequest {
events: source_events, // Events the saga would receive
destination: Some(destination_event_book), // Target aggregate state
};

let response = client.saga(request).await?;

// Inspect what commands the saga WOULD emit
for command in response.commands.iter() {
println!("Would send command to: {}", command.cover.domain);
}

Projector Speculative Execution

Test how a projector would process events:

use angzarr_client::proto::SpeculateProjectorRequest;

let request = SpeculateProjectorRequest {
events: events_to_project,
};

let response = client.projector(request).await?;

// Inspect the projection result
println!("Projection: {:?}", response);

Testing with Speculative Execution

Speculative execution is excellent for integration tests:

def test_order_creation_produces_correct_events():
client = SpeculativeClient.connect("localhost:1310")

# Create order command
command = build_create_order_command(
customer_id="cust-123",
items=[{"product": "widget", "quantity": 5}]
)

request = SpeculateAggregateRequest(command=command, events=[])
response = client.aggregate(request)

# Verify the projected events
assert len(response.events.pages) == 1
assert response.events.pages[0].event.type_url.endswith("OrderCreated")

# No state changed - can run this test repeatedly!
client.close()

Next Steps

  • Error Handling — Error types and introspection methods
  • Clients — Client types and connection patterns
  • Builders — Fluent API for commands and queries