Skip to content
Andrey Sibiryov edited this page Aug 3, 2013 · 6 revisions

Common types

Object      ::= <Number> | <String> | <Tuple> | <Map>
Tuple       ::= ([<Object> [, <Object>]...])

General format

Every message is a MessagePack-ed tuple of three fields:

SlotID      ::= <Number>
ChannelID   ::= <Number>
Message     ::= (<SlotID>, <ChannelID>, <Tuple>)

Slot ID is a service slot number you're going to call. Every service has its own set of slots which can be inspected by resolving this service via the Locator. Channel ID is a way to multiplex multiple dataflows inside a single TCP session. Channel ID is generated by the caller. Tuple is a slot-specific payload.

Locator protocol

I'll explain the messaging in detail using the Locator protocol, which is one of the key protocols to know when using the Cocaine Services. This service has a public slot named %%resolve%%, which searches for a specified service name and returns you the information about it, if available. This slot's payload tuple is as follows:

0, Resolve  ::= (<String>)

Every call results in a stream, which yields you response chunks and errors and is always closed in the end. Stream is implemented as a protocol, too:

4, Chunk    ::= (<String>)
5, Error    ::= (<Number>, <String>)
6, Choke    ::= ()

When a remote server yields a new response chunk, it's returned with a Chunk message. Chunks are serialized MessagePack objects, too. The exact object type is determined by the service protocol. In our case, the Resolve method returns the following object and then closes the stream:

Address     ::= <String>
Port        ::= <Number>
Endpoint    ::= (<Address>, <Port>)
Version     ::= <Number>
DispatchMap ::= {<SlotID> => <String> [, <SlotID> => <String>]...}
Response    ::= (<Endpoint>, <Version>, <DispatchMap>)

If a remote service fails, it's signaled with an Error message. Error tuple consists of a service-specific error code and error message. For example, the Locator service could return the following error if no service is found with the specified name:

(ENOENT, "the specified service is not available")

When there's no more data in the stream, a Choke message is sent. A stream is always closed with a Choke message, either after all the chunks are sent, or after an error occured. Also, after an Error message is received, the next single valid message is Choke.

Example

For example, if we want to resolve a local Logging service, it would be something like that on the wire:

-> (0, 1, ("logging")
<- (4, 1, (("localhost", 12345), 1, {0 => "emit"}))
<- (6, 1, ())

That means that the Logging service can be reached at port 12345 locally, its protocol version is 1, and it has one slot number 0, which maps to a method named 'emit'.

Clone this wiki locally