Operations
Operations are named, structured interfaces that documents expose to the outside world. They define specific actions that can be performed on a document, complete with formal request definitions.
The Role of Operations in Blue
Blue documents interact with the world through channels, processing events that arrive through these pathways. Operations build on this foundation by creating well-defined action endpoints within a document.
When to use operations:
- To create clearly named actions that express intent (e.g.,
approvePayment,scheduleLesson) - To enforce specific input structures and validation rules
- To organize document capabilities into logical functional units
- To enable discoverability of available actions
Operations provide an organizational layer that helps structure interactions with a document. They create a clear API for document manipulation while working through the same underlying channel mechanisms that power all Blue document interactions.
Defining Operations
Operations are defined using the Operation contract:
increment:
type: Operation
request:
description: Represents a value by which counter will be incremented
type: Integer
This definition specifies:
- The operation name (
increment) - The expected input structure (
request) - A description for the request
Implementing Operations
Once defined, operations need an implementation. The most common approach is using a Sequential Workflow Operation:
incrementImpl:
type: Sequential Workflow Operation
operation: increment
steps:
- type: Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}
This implementation:
- Links to the
incrementoperation definition - Defines processing steps that execute when the operation is called
The operation's implementation can access:
- The request payload via
event.message - Timeline metadata (actor, timestamp, etc.) via
event - The current document state via
document() - Any other contextual information needed
Invoking Operations
Operations are invoked by posting a Timeline Entry whose message is an Operation Request to the document's channel:
type: Timeline Entry
timeline:
type: MyOS Timeline # Or another Timeline Provider
account: alice@example.com
message:
type: Operation Request
operation: increment # Name of the operation to call
request: 5 # The increment value
document:
blueId: 7UEBwTmRMfQ92rGt4vHkzPa8Ypd5KJsLNcA3FV6xDqbn # Target document ID
allowNewerVersion: true # Accept if document has changed
actor:
type: Principal Actor
name: Alice
Request Formats
The request field can contain:
-
Simple values for primitive types:
request: 5 # Integer -
Structured objects for complex types:
request:
a: 12
b: xyz
The request structure must match what's defined in the operation contract. If it doesn't match, the operation won't execute and will return an error.
The allowNewerVersion Flag
The allowNewerVersion flag addresses an important concern: what happens if the document changes between when you retrieve it and when you send your operation?
true: Process the operation on the latest version, even if it changedfalse: Only process if the document still has the same BlueId as specified
This gives callers control over concurrent modifications:
- Use
truewhen the operation should work regardless of other changes - Use
falsewhen the operation depends on the document being in a specific state
Complete Counter Example
Let's bring everything together with our simple counter example:
name: Simple Counter
counter: 0
contracts:
ownerChannel:
type: Timeline Channel
# Defines the increment operation interface
increment:
type: Operation
request:
description: Represents a value by which counter will be incremented
type: Integer
# Implements the increment operation
incrementImpl:
type: Sequential Workflow Operation
operation: increment
steps:
- type: Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}
When a client wants to increment the counter:
-
It posts a Timeline Entry containing an Operation Request to the document's timeline:
type: Timeline Entry
timeline:
type: MyOS Timeline
account: alice@example.com
message:
type: Operation Request
operation: increment
request: 5
document:
blueId: 7UEBwTmRMfQ92rGt4vHkzPa8Ypd5KJsLNcA3FV6xDqbn
allowNewerVersion: true
actor:
type: Principal Actor
name: Alice -
Any compliant document processor:
- Receives the Timeline Entry through the
ownerChannel - Extracts the Operation Request from
event.message - Identifies the
incrementoperation and its implementation - Executes the Update Document step, adding 5 to the counter
- Receives the Timeline Entry through the
-
The counter is now incremented by 5
Operations in MyOS
You can run the example above in MyOS.
