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
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));
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))
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):
Put - insert a payload into another Grain's value.
MapPut - insert a payload into another Grain's map.
MapDelete - delete an entry from another Grain's map.
MapDeleteRange - delete a range of entries from another Grain's map.
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:
responseAction - the callback action to invoke on the sender Grain with the response.
This callback action will receive a GrainResponse Action from the receiver Grain.
senderCookie - a payload to identify the callback.
onErrorOnly - indicating if the callback action should be invoked only if the resulting operation resulted in a failure.
Example
SendMessage.java
publicActionResultsendMessageToUser(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);returnActionResult.success(action);}
ReceiveMessage.java
publicActionResultreceiveMessage(Action action,GrainContext context) {// The following message will contain the payload (`userMessageJson`) sent from the other grain.Value message = ((GrainRequest)action).getPayload();...}
SendMessage.py
defsend_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
defreceive_message(action: Action,context: GrainContext) -> ActionResult:assertisinstance(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
Handler.java
publicActionResultsendMessageToAnotherGrain(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);
...}publicActionResulthandleMessageCallback(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 successfulValue result =response.getResult(); // Result sent back from receiving Grain}
Handler.py
defsend_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))
...defhandle_message_callback(action: Action,context: GrainContext) -> ActionResult:assertisinstance(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
Client.java
Topic topic =client.getTopic("my_app","my_topic");// The following will append the provided Event into `my_topic`. topic.append(newEvent(Key.of(eventId),Value.of(payload)));
EventHandler.java
publicActionResulthandleTopicEvent(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
defhandle_topic_event(action: Action,context: GrainContext) -> ActionResult:assertisinstance(action, TopicEvent)# This will contain the payload sent by the client. payload = action.payload
publicActionResultappendEvent(Action action,GrainContext context) {// The following will append the provided event into a topic.context.sendToTopic("user_table",Key.of(userId),Value.of(eventPayload),newExpectAppendResponse("handleAppendFailure",Value.of(messageId));}publicActionResulthandleAppendFailure(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
defappend_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))
defhandle_append_failure(action: Action,context: GrainContext) -> ActionResult:assertisinstance(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}