CloudEvents
EvidentSource uses the CloudEvents specification as its core event format. CloudEvents is a specification for describing event data in a common way, enabling interoperability across services, platforms, and systems.
Why CloudEvents?
Section titled “Why CloudEvents?”CloudEvents provides:
- Standardization: A vendor-neutral specification backed by the CNCF
- Interoperability: Easy integration with other CloudEvents-compatible systems
- Flexibility: Support for various content types and transport protocols
- Extensibility: Custom attributes for domain-specific needs
CloudEvents Structure
Section titled “CloudEvents Structure”Required Attributes
Section titled “Required Attributes”Every CloudEvent in EvidentSource must have these attributes:
| Attribute | Type | Description |
|---|---|---|
id | String | Unique identifier for the event |
source | URI-reference | Identifies the context in which the event occurred |
specversion | String | CloudEvents specification version (always “1.0”) |
type | String | Type of event related to the source |
Optional Attributes
Section titled “Optional Attributes”EvidentSource supports these optional CloudEvents attributes:
| Attribute | Type | Description |
|---|---|---|
datacontenttype | String | Content type of the data (default: “application/json”) |
dataschema | URI | Schema that the data adheres to |
subject | String | Subject of the event in the context of the source |
time | Timestamp | When the event occurred (ISO 8601) |
data | Any | The event payload |
Example CloudEvent
Section titled “Example CloudEvent”{ "specversion": "1.0", "id": "45a8b444-3d5f-4a6e-b55d-1c5e0b2e4a89", "source": "https://example.com/orders", "type": "com.example.orders.OrderCreated", "subject": "order-12345", "time": "2024-01-15T10:30:00Z", "datacontenttype": "application/json", "dataschema": "https://example.com/schemas/order-created/v1", "data": { "orderId": "12345", "customerId": "67890", "totalAmount": 99.99, "currency": "USD" }}Event Attributes in EvidentSource
Section titled “Event Attributes in EvidentSource”Source
Section titled “Source”The source attribute identifies the system or component that generated the event:
- Use URIs for global uniqueness:
https://api.example.com/order-service - Or use simple identifiers for internal systems:
order-service - Be consistent within your domain
The type attribute describes what happened:
- Use reverse-DNS notation:
com.example.orders.OrderCreated - Or use simple descriptive names:
OrderCreated - Include version if needed:
com.example.orders.OrderCreated.v2
Subject
Section titled “Subject”The subject provides additional context:
- Typically identifies the entity the event is about
- Examples:
order-12345,customer-67890,product-abc - Enables efficient filtering and indexing
The time attribute represents when the event occurred:
- Use ISO 8601 format with timezone
- Represents business time (when the event happened in the real world)
- Different from
recordedtime(when EvidentSource stored the event)
Data Formats
Section titled “Data Formats”JSON Data
Section titled “JSON Data”The most common format for event data:
{ "specversion": "1.0", "id": "...", "source": "inventory-service", "type": "InventoryUpdated", "datacontenttype": "application/json", "data": { "productId": "SKU-123", "quantity": 42, "location": "warehouse-1" }}Binary Data
Section titled “Binary Data”For binary payloads, use base64 encoding:
{ "specversion": "1.0", "id": "...", "source": "document-service", "type": "DocumentScanned", "datacontenttype": "application/pdf", "data_base64": "JVBERi0xLjQKJdPr6eEKMSAwIG9i..."}Structured vs Binary Mode
Section titled “Structured vs Binary Mode”EvidentSource stores events in structured mode:
- Events are stored as complete CloudEvents objects
- All attributes are preserved and queryable
- Enables rich filtering and indexing
Best Practices
Section titled “Best Practices”Event ID Generation
Section titled “Event ID Generation”- Use UUIDs for guaranteed uniqueness
- Never reuse event IDs
- EvidentSource enforces unique IDs per database
let event_id = Uuid::new_v4().to_string();Source Design
Section titled “Source Design”Choose meaningful source identifiers:
// Good examples"https://api.acme.com/order-service""order-service.production""acme.orders"
// Avoid"service1""backend""system"Type Naming Conventions
Section titled “Type Naming Conventions”Use consistent, descriptive event types:
// Domain.Entity.Action pattern"com.acme.orders.OrderCreated""com.acme.orders.OrderShipped""com.acme.inventory.StockDepleted"
// Simple Entity.Action pattern"Order.Created""Order.Shipped""Inventory.Depleted"Data Schema Evolution
Section titled “Data Schema Evolution”Plan for schema changes:
- Use dataschema: Reference versioned schemas
- Add, don’t remove: New fields should be optional
- Version when breaking: Create new event types for incompatible changes
- Document changes: Maintain schema documentation
Querying by CloudEvents Attributes
Section titled “Querying by CloudEvents Attributes”EvidentSource indexes events by key attributes:
// Query by sourceEventSelector { stream: Some("order-service".into()), ..Default::default() }
// Query by typeEventSelector { event_type: Some("OrderCreated".into()), ..Default::default() }
// Query by subjectEventSelector { subject: Some("order-12345".into()), ..Default::default() }
// Combine attributesEventSelector { stream: Some("order-service".into()), event_type: Some("OrderCreated".into()), subject: Some("order-12345".into()),}Integration Patterns
Section titled “Integration Patterns”Event Routing
Section titled “Event Routing”Use CloudEvents attributes for routing:
match event.ty.as_str() { "OrderCreated" => handle_order_created(&event).await?, "OrderShipped" => handle_order_shipped(&event).await?, "OrderCancelled" => handle_order_cancelled(&event).await?, _ => {}}Event Filtering
Section titled “Event Filtering”Filter events based on attributes:
let filtered: Vec<_> = events .into_iter() .filter(|event| { event.source == "order-service" && event.ty.starts_with("Order") && event.time.as_ref().map_or(false, |t| t > &start_date) }) .collect();Event Correlation
Section titled “Event Correlation”Use subject for correlation:
// All events for a specific orderlet query = EventQuery { event_selection: Some(EventSelection { selectors: vec![ EventSelector { subject: Some("order-12345".into()), ..Default::default() } ], }), ..Default::default()};
let mut stream = client.query_events(QueryEventsRequest { database_name: "mydb".into(), query: Some(query),}).await?.into_inner();CloudEvents Extensions
Section titled “CloudEvents Extensions”EvidentSource automatically adds:
recordedtime: When the event was storedrevision: The event’s revision number
These are exposed as CloudEvents extensions and can be accessed alongside standard attributes.
Next Steps
Section titled “Next Steps”- Explore Bi-Temporal Indexing using CloudEvents time attributes
- Learn about Event Sourcing patterns
- Understand State Views for processing CloudEvents
- See the API Reference for CloudEvents operations