Links
Comment on page

Types of Actions

1. SyncRequest

This represents a request sent by a client using the client API.
The Action Handler can return a Value as part of the response which the client can use.

Example

Java
Python
Client.java
Table table = client.getTable("my_app", "my_table");
Grain grain = table.getGrain(Key.of("u123"));
// The following will invoke the "handleUserEvents" action on the Grain.
grain.invoke("getUserAccountBalance", Value.of(userAccountId));
ActionHandler.java
public ActionResult getUserAccountBalance(Action action, GrainContext context) {
String accountID = ((SyncRequest)action).getPayload().asString();
// Get account balance...
long accountBalance = ...
return ActionResult.success(action, Value.of(accountBalance));
}
Client.py
table = client.get_table("my_app", "my_table");
grain = table.get_grain(Key("u123"))
# The following will invoke the "handle_user_events" action on the Grain.
grain.invoke("get_user_account_balance", Value(user_account_id))
ActionHandler.py
def get_user_account_balance(action: Action, context: GrainContext) -> ActionResult:
assert isinstance(action, SyncRequest)
account_ID = action.payload.as_string()
# Get account balance...
account_balance = ...
return ActionResult.Success(action, Value(account_balance))
}

2. GrainRequest

This represents a message sent by a Grain to another Grain.
This message can be an operation to either insert something into another Grain's state, or invoke an Action on it.
Here are all the supported operations (Java, Python):
  1. 1.
    Put - insert a payload into another Grain's value.
  2. 2.
    MapPut - insert a payload into another Grain's map.
  3. 3.
    MapDelete - delete an entry from another Grain's map.
  4. 4.
    MapDeleteRange - delete a range of entries from another Grain's map.
  5. 5.
    Invoke - invoke an Action on another Grain.
Optionally, a sender Grain can also choose to receive a callback once the operation has been completed by providing a ExpectGrainResponse object to the sendToGrain method (Java, Python). The ExpectGrainResponse object contains the following:
  1. 1.
    responseAction - the callback action to invoke on the sender Grain with the response.
    1. 1.
      This callback action will receive a GrainResponse Action from the receiver Grain.
  2. 2.
    senderCookie - a payload to identify the callback.
  3. 3.
    onErrorOnly - indicating if the callback action should be invoked only if the resulting operation resulted in a failure.

Example

Java
Python
SendMessage.java
public ActionResult sendMessageToUser(Action action, GrainContext context) {
// The following is being used to send a message to another Grain.
// The receving Grain's "receiveMessage" action handler will be invoked along with the userMessageJson.
GrainOp.Invoke sendMessage = new GrainOp.Invoke("receiveMessage", Value.of(userMessageJson));
context.sendToGrain("user_table", Key.of(userId), sendMessage, null);
return ActionResult.success(action);
}
ReceiveMessage.java
public ActionResult receiveMessage(Action action, GrainContext context) {
// The following message will contain the payload (`userMessageJson`) sent from the other grain.
Value message = ((GrainRequest)action).getPayload();
...
}
SendMessage.py
def send_message_to_user(action: Action, context: GrainContext) -> ActionResult:
# The following is being used to send a message to another Grain.
# The receving Grain's "receive_message" action handler will be invoked along with the user_message_json.
send_message = message.Invoke("receive_message", Value(user_message_json))
context.send_to_grain("user_table", Key(user_id), send_message)
return ActionResult.Success(action)
ReceiveMessage.py
def receive_message(action: Action, context: GrainContext) -> ActionResult:
assert isinstance(action, GrainRequest)
# The following message will contain the payload (`user_message_json`) sent from the other grain.
message = action.payload
...

3. GrainResponse

This represents a reply that a Grain receives after sending a message (GrainRequest) and expecting a response.

Example

Java
Python
Handler.java
public ActionResult sendMessageToAnotherGrain(Action action, GrainContext context) {
// The following is being used to send a message to another Grain and expects a callback once the message has been received and processed.
context.sendToGrain("user_table", Key.of(userId), sendMessageOp, new ExpectGrainResponse("handleMessageCallback", Value.of(messageId), false);
...
}
public ActionResult handleMessageCallback(Action action, GrainContext context) {
// The following method will be invoked once the userId Grain has processed the message sent from `sendMessageToAnotherGrain`.
GrainResponse response = GrainResponse(action);
String cookie = response.getCookieValue().asString();
Status status = response.getStatus(); // Status.OK if successful
Value result = response.getResult(); // Result sent back from receiving Grain
}
Handler.py
def send_message_to_another_grain(action: Action, context: GrainContext) -> ActionResult:
# The following is being used to send a message to another Grain and
# expects a callback once the message has been received and processed.
context.send_to_grain("user_table", Key(user_id), send_message_op, ExpectGrainResponse("handle_message_callback", Value(message_id), False))
...
def handle_message_callback(action: Action, context: GrainContext) -> ActionResult:
assert isinstance(action, GrainResponse)
# The following method will be invoked once the user_id Grain has processed
# the message sent from `send_message_to_another_grain`.
cookie = action.sender_cookie.as_string()
status = action.status # Status.OK if successful
result = action.result # Result sent back from receiving Grain

4. TopicEvent

This represents an event delivered to this grain as part of a Topic Subscription.

Example

Java
Python
Client.java
Topic topic = client.getTopic("my_app", "my_topic");
// The following will append the provided Event into `my_topic`.
topic.append(new Event(Key.of(eventId), Value.of(payload)));
EventHandler.java
public ActionResult handleTopicEvent(Action action, GrainContext context) {
// This will contain the payload sent by the client.
Value payload = ((TopicEvent)action).getPayload();
}
Client.py
topic = client.get_topic("my_app", "my_topic")
# The following will append the provided Event into `my_topic`.
topic.append(Event(Key(event_id), Value(payload))
EventHandler.py
def handle_topic_event(action: Action, context: GrainContext) -> ActionResult:
assert isinstance(action, TopicEvent)
# This will contain the payload sent by the client.
payload = action.payload

5. AppendResponse

This represents the response received by a Grain after appending an event to a Topic.

Example

Java
Python
Handler.java
public ActionResult appendEvent(Action action, GrainContext context) {
// The following will append the provided event into a topic.
context.sendToTopic("user_table", Key.of(userId), Value.of(eventPayload),
new ExpectAppendResponse("handleAppendFailure", Value.of(messageId));
}
public ActionResult handleAppendFailure(Action action, GrainContext context) {
// The following method will be invoked once the topic has received the event sent from `appendEvent`.
AppendResponse response = AppendResponse(action);
String cookie = response.getCookieValue().asString();
Status status = response.getStatus(); // Status.OK if successful
}
Handler.py
def append_event(action: Action, context: GrainContext) -> ActionResult:
# The following will append the provided event into a topic.
context.send_to_topic("user_table", Key(user_id), Value(event_payload), ExpectAppendResponse("handle_append_failure", Value(message_id))
def handle_append_failure(action: Action, context: GrainContext) -> ActionResult:
assert isinstance(action, AppendResponse)
# The following method will be invoked once the topic has received the event sent from `append_event`.
cookie = action.sender_cookie.as_string()
status = action.status # Status.OK if successful
}