Event
Events provide a publish-subscribe mechanism for decoupling business logic in FlowOn Logic. Instead of directly calling flows from other flows or creating tight dependencies between components, you can publish an event and let interested handlers respond to it. This creates a flexible, loosely-coupled architecture where publishers don't need to know about subscribers.
The Challenge: Tightly Coupled Logic
As business logic grows, components often become tightly intertwined. A flow that processes an order might directly call:
- A flow to send confirmation emails
- A flow to update inventory
- A flow to notify the warehouse
- A flow to sync with the ERP system
- A flow to update analytics
This creates several problems:
- Rigid Dependencies: The order flow must know about all downstream processes
- Difficult Changes: Adding a new action (like loyalty points) requires modifying the order flow
- Testing Complexity: You can't test the order flow without triggering all downstream effects
- Performance Impact: Synchronous calls to multiple flows slow down the main process
- Single Point of Failure: If one downstream flow fails, the entire chain may fail
The Solution: Event-Driven Architecture
Events introduce a publish-subscribe pattern that decouples publishers from subscribers:
- Publishers announce that something happened (e.g., "an order was placed")
- Subscribers independently listen for events they care about and react accordingly
- Publishers don't know who is listening or what actions will be taken
- Subscribers don't know who published the event or why
This decoupling allows you to add, remove, or modify subscribers without changing the publisher.
Event System Components
The FlowOn Logic event system consists of three components:
| Component | Purpose | Created By |
|---|---|---|
| Event Definition | Defines the event structure (name and properties) | Developer at design time |
| Event Handler | Subscribes to an event and specifies how to respond | Developer at design time |
| Event Instance | The actual event occurrence with data | System at runtime (via Publish Event step) |
Event Definition
An Event Definition declares that a particular type of event exists in your system. It defines what data (properties) the event carries. Think of it as a contract: anyone publishing this event must provide these properties, and any handler can expect to receive them.
Structure
| Property | Required | Description |
|---|---|---|
| Name | Yes | Unique identifier for the event (e.g., "OrderPlaced", "CustomerCreated") |
| Project | Yes | The FlowOn Project this event belongs to |
| Description | No | Documentation explaining when this event is published |
| Properties | Yes | List of data properties the event carries |
Event Properties
Properties are like inputs—they define what data accompanies the event:
| Property Attribute | Description |
|---|---|
| Name | Unique identifier for the property |
| Type | Data type (String, Integer, Money, Entity Reference, etc.) |
| Required | Whether the property must be provided when publishing |
| Description | Documentation explaining what the property represents |
Example: Order Placed Event Definition
Event Definition: OrderPlaced
Project: E-Commerce
Description: "Published when a new order is successfully created"
Properties:
┌─────────────────────┬──────────────────┬──────────┬────────────────────────┐
│ Property Name │ Type │ Required │ Description │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderId │ Entity Reference │ Yes │ Reference to the Order │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ CustomerId │ Entity Reference │ Yes │ Reference to Customer │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderNumber │ String │ Yes │ Human-readable order # │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ TotalAmount │ Money │ Yes │ Order total value │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderDate │ DateTime │ Yes │ When order was placed │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ IsFirstOrder │ Boolean │ No │ Is this customer's │
│ │ │ │ first order? │
└─────────────────────┴──────────────────┴──────────┴────────────────────────┘
Event Handler
An Event Handler subscribes to an Event Definition and specifies what happens when that event is published. It connects the event to a Logic Flow that contains the actual business logic to execute.
Structure
| Property | Required | Description |
|---|---|---|
| Name | Yes | Unique identifier for the handler |
| Project | Yes | The FlowOn Project this handler belongs to |
| Event Definition | Yes | The event this handler subscribes to |
| Logic Flow | Yes | The flow to execute when the event is published |
| Execution Mode | Yes | Synchronous or Asynchronous |
| Input Bindings | Yes | Mapping between event properties and flow inputs |
Execution Mode
| Mode | Behavior | Use When |
|---|---|---|
| Synchronous | Publisher waits for handler to complete; handler runs in same transaction | Handler must complete before publisher continues; data integrity required |
| Asynchronous | Publisher continues immediately; handler runs in background | Non-critical processing; long-running operations; external integrations |
Input Bindings
Input bindings map event properties to flow inputs. When the event is published, the handler passes the event data to the flow using these bindings.
Event Property → Flow Input
─────────────────────────────
OrderId → OrderReference
CustomerId → CustomerReference
TotalAmount → Amount
OrderDate → PlacedOn
Example: Send Order Confirmation Handler
Event Handler: SendOrderConfirmation
Project: E-Commerce
Event Definition: OrderPlaced
Logic Flow: SendOrderConfirmationEmail
Execution Mode: Asynchronous
Input Bindings:
┌─────────────────────┬─────────────────────┬─────────────────────────────┐
│ Event Property │ Flow Input │ Description │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ OrderId │ OrderReference │ Order to include in email │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ CustomerId │ CustomerReference │ Customer to send email to │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ OrderNumber │ OrderNum │ For email subject line │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ TotalAmount │ OrderTotal │ For email body │
└─────────────────────┴─────────────────────┴─────────────────────────────┘
Multiple Handlers for One Event
A single Event Definition can have multiple handlers. When the event is published, all registered handlers are triggered:
Event: OrderPlaced
│
├──► Handler: SendOrderConfirmation (Async)
│ └──► Flow: SendOrderConfirmationEmail
│
├──► Handler: DeductInventoryOnOrder (Sync)
│ └──► Flow: DeductOrderInventory
│
├──► Handler: NotifyWarehouse (Async)
│ └──► Flow: SendWarehouseNotification
│
├──► Handler: UpdateAnalytics (Async)
│ └──► Flow: RecordOrderAnalytics
│
└──► Handler: AwardLoyaltyPoints (Async)
└──► Flow: CalculateAndAwardPoints
Event Instance
An Event Instance is created at runtime when the Publish Event step executes in a Logic Flow. It represents a specific occurrence of the event with actual data values.
Characteristics
| Characteristic | Description |
|---|---|
| Immutable | Once created, the event instance cannot be modified |
| Read-Only | Handlers can read event data but cannot change it |
| Timestamped | System records when the event was published |
| Traceable | Event instances can be tracked for auditing and debugging |
Event Lifecycle
┌─────────────────────────────────────────────────────────────────────┐
│ EVENT INSTANCE LIFECYCLE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. PUBLISH │
│ └── Flow executes "Publish Event" step │
│ └── Provides values for event properties │
│ │
│ 2. CREATE │
│ └── System creates immutable Event Instance │
│ └── Instance contains snapshot of provided data │
│ │
│ 3. DISPATCH │
│ └── System identifies all registered handlers │
│ └── Synchronous handlers execute first (in order) │
│ └── Asynchronous handlers queued for background execution │
│ │
│ 4. HANDLE │
│ └── Each handler's flow executes │
│ └── Event data passed via input bindings │
│ └── Flow performs its business logic │
│ │
│ 5. COMPLETE │
│ └── All handlers have executed (or been queued) │
│ └── Publisher flow continues (if sync handlers done) │
│ │
└─────────────────────────────────────────────────────────────────────┘
Publishing Events
Events are published using the Publish Event step in a Logic Flow:
Publish Event Step
| Parameter | Description |
|---|---|
| Event Definition | The event type to publish |
| Event Properties Binding | Values to assign to each event property |
Example: Publishing OrderPlaced Event
Flow: CreateOrder
Steps:
1. [Validation] - Validate order data
2. [Save Entity] - Save the Order record
3. [Loop] - For each line item
└── [Save Entity] - Save Order Line record
4. [Publish Event] ◄── PUBLISH EVENT
- Event Definition: OrderPlaced
- Property Bindings:
- OrderId: Order.Id
- CustomerId: Order.CustomerId
- OrderNumber: Order.OrderNumber
- TotalAmount: Order.TotalAmount
- OrderDate: Now()
- IsFirstOrder: CustomerOrderCount = 1
5. [Set Output] - Return Order ID
When step 4 executes:
- An immutable Event Instance is created with the bound values
- All synchronous handlers execute (e.g., DeductInventoryOnOrder)
- Asynchronous handlers are queued (e.g., SendOrderConfirmation)
- The flow continues to step 5
Best Practices
Design Events Around Business Moments: Events should represent meaningful business occurrences ("OrderPlaced", "PaymentReceived", "CustomerUpgraded") not technical operations ("RecordSaved", "FieldUpdated").
Include Sufficient Context: Event properties should contain enough information for handlers to do their work without querying for additional data. Include IDs, key values, and relevant context.
Keep Events Focused: Each event should represent one thing that happened. Don't create "OrderPlacedAndPaymentProcessed"—create two separate events.
Use Sync Handlers Sparingly: Synchronous handlers block the publisher. Reserve them for operations that must complete before the publisher continues (e.g., inventory deduction before order confirmation).
Design for Handler Failure: Asynchronous handlers can fail independently. Design handlers to be idempotent (safe to retry) and implement error handling.
Document Event Contracts: Clearly document when each event is published, what properties it contains, and what handlers should expect.
Avoid Circular Events: Be careful not to create event chains where Handler A publishes an event that triggers Handler B, which publishes an event that triggers Handler A.
Version Events Carefully: If you need to change an event's properties, consider creating a new event version rather than modifying existing handlers.
Use Meaningful Names: Event names should be past tense and describe what happened: "OrderPlaced" not "PlaceOrder", "CustomerCreated" not "CreateCustomer".
Consider Event Ordering: When multiple handlers exist, synchronous handlers run first (in registration order), then asynchronous handlers are queued. Design accordingly.