├── README.md └── spec.md /README.md: -------------------------------------------------------------------------------- 1 | This is the repository for the version 3 of the RESP protocol. 2 | RESP (REdis Serialization Protocol) is the protocol used in the [Redis](http://github.com/antirez/redis) database, however the protocol is designed to be used by other projects. With the version 3 of the protocol, currently a work in progress design, the protocol aims to become even more generally useful to other systems that want to implement a protocol which is simple, efficient, and with a very large landscape of client libraries implementations. 3 | 4 | Here you can find the [current RESP3 specification](spec.md). 5 | 6 | In the future this repository may add additional resources, such as example implementations of RESP or other resources. 7 | -------------------------------------------------------------------------------- /spec.md: -------------------------------------------------------------------------------- 1 | # RESP3 specification 2 | 3 | Versions history: 4 | * 1.0, 2 May 2018, Initial draft to get community feedbacks. 5 | * 1.1, 5 Nov 2018, Leave CRLF as terminators + improved "hello reply" section. 6 | * 1.2, 5 Nov 2018, A few things are now better specified in the document thanks 7 | to developers reading the specification and sending their 8 | feedbacks. No actual change to the protocol was made. 9 | 10 | ## Background 11 | 12 | The Redis protocol has served us well in the past years, showing that, if carefully designed, a simple human readable protocol is not the bottleneck in the client server communication, and that the simplicity of the design is a major advantage in creating a healthy client libraries ecosystem. 13 | 14 | Yet the Redis experience has shown that after about six years from its introduction (when it replaced the initial Redis protocol), the current RESP protocol could be improved, especially in order to make client implementations simpler and to support new features. 15 | 16 | At the same time the basic structure is tested and sounding, and there are several things to save from the old design: 17 | 18 | * RESP is human readable. This confers to the protocol the important quality of being simple to observe and debug. 19 | * Despite being human readable, RESP is no slower than a binary protocol with fixed length fields, and in many cases can be more compact. Often Redis commands have few arguments composed of few bytes each. Similarly many replies are short. The protocol prefixed lengths represented as decimal digits will save space on the wire, compared to 64 bit integers, and will not be slower to parse. It is possible to design a more efficient binary protocol only introducing the complexity of a variable length encoding, defeating the goal of simplicity. 20 | * The design is very simple: this makes the specification and the resulting implementations short and easy to understand. 21 | 22 | At the same time, RESP has flaws. One of the most obvious is the fact that it has not enough semantic power to allow the client to implicitly understand what kind of conversion is appropriate. For instance the Redis commands `LRANGE`, `SMEMBERS` and `HGETALL` will all reply an array, called in RESP v2 terms a *multi bulk reply*. However the three commands actually return an array, a set and a map. 23 | Currently, from the point of view of the client, the conversion of the reply to the programming language type is command-dependent. Clients need to remember what command was called in order to turn the Redis reply into a reply object of some kind. What is worse is that clients need to know about each command, or alternatively provide a lower level interface letting users select the appropriate conversion. 24 | 25 | Similarly RESP lacks important data types: floating point numbers and boolean values were returned respectively as strings and integers. Null values had a double representation, called *null bulk* and *null multi bulk*, which is useless, since the semantic value of telling apart null arrays from null strings is non existent. 26 | 27 | Finally there was no way to return binary safe errors. When implementing generic APIs producing the protocol, implementations must check and remove potential newlines from the error string. 28 | 29 | The limitations stated so far are the main motivations for a new version of RESP. However the redesign gave us a chance to consider different other improvements that may be worthwhile and make the protocol both more powerful and less dependent on the implicit state of the connection. 30 | 31 | The gist of such additional features are to provide the protocol with the ability to support a more generic *push mode* compared to the Pub/Sub mode used by Redis, which is not really built-in in the protocol, but is an agreement between the server and the client about the fact that the connection will consume replies as they arrive. Moreover it was useful to modify the protocol to return *out of band* data, such as attributes that augment the reply. Also the protocol was sometimes abused by the internals of Redis, like for example in the case of *replicaless replication*, in order to support streaming of large strings whose length is initially not known. This specification makes this special mode part of the RESP protocol itself. 32 | 33 | This specification describes RESP3 from scratch, and not just as a change from RESP v2. However differences between the two will be noted while describing the new protocol. 34 | 35 | ## Why existing serialization protocols are not good enough? 36 | 37 | In theory instead of improving RESP v2, we could use an existing serialization 38 | protocol like MessagePack, BSON or others, which are widely available 39 | and implemented. This is a viable approach, and could be a potential solution, 40 | however there are certain design goals that RESP has that are not aligned 41 | with using such serialization formats. 42 | 43 | The first and most important is the fact that such serialization protocols 44 | are not specifically designed for a request-response server-client chat, so 45 | clients and servers would be required to agree on an additional protocol on 46 | top of the underlying serialization protocol. Basically it is not possible 47 | to escape the problem of designing a Redis specific protocol, so 48 | to bind together the serialization and the semantic looks a more effective 49 | way to reach the goals of RESP3. 50 | 51 | A different problem is the fact that such serialization protocols are more 52 | complex than RESP, so client libraries would have to rely on a separated 53 | library implementing the serialization protocol. The library may not have 54 | support for streaming directly to a socket, and may return a buffer instead, 55 | leading to potential inefficiencies. Relying on a library in order to perform 56 | the serialization has the other disadvantage of having more moving parts 57 | where things may go wrong, or where different versions of Redis and 58 | serialization libraries may not work well together. 59 | 60 | Finally certain features like transferring large strings with initially 61 | unknown length, or streaming of arrays, two features that RESP3 supports 62 | and that this specification describes, are not easy to found among 63 | existing serialization protocols. 64 | 65 | In short this specification was written believing that designing a good 66 | serialization format is different compared to designing a protocol 67 | specifically suited in order to support the chat between a client and 68 | its server. RESP3 aims to create a protocol which is not just suitable 69 | for Redis, but more broadly to solve the general problem of client-server 70 | communication in many scenarios even outside Redis and outside the 71 | database space. 72 | 73 | ## Conventions used in this document 74 | 75 | In order to illustrate the RESP3 protocol this specification will show 76 | fragments of the protocol in many sections. In addition of using the escaped 77 | string format, like "foo\r\n", we'll use a more readable format where 78 | "\r\n" will be presented as `` followed by an actual newline. Other 79 | special characters will be displayed as `<\xff>`, where `ff` is the 80 | hex code of the byte. 81 | 82 | So for instance the string `"*1\r\n$1\r\nA\r\n"` representing a RESP3 array with 83 | a single string `"A"` as unique element, will be presented like this: 84 | 85 | *1 86 | $1 87 | A 88 | 89 | However for the first part of this specification, both this format and 90 | the escaped string format will be used in order to make sure there is 91 | no confusion. In the latter sections however only one or the other 92 | will be used. 93 | 94 | When nested aggregate data structures are shown, indentation is used in 95 | order to make it more clear the actual structure of the protocol. For 96 | instance instead of writing: 97 | 98 | *2 99 | *2 100 | :1 101 | :2 102 | #t 103 | 104 | We'll write: 105 | 106 | *2 107 | *2 108 | :1 109 | :2 110 | #t 111 | 112 | Both the indentation and the newlines are hence only used in order to improve 113 | human readability and are not semantical in respect of the actual protocol. 114 | 115 | ## RESP3 overview 116 | 117 | RESP3 is an updated version of RESP v2, which is the protocol used in Redis 118 | starting with roughly version 2.0 (1.2 already supported it, but Redis 2.0 119 | was the first version to talk only this protocol). The name of this protocol 120 | is just **RESP3** and not RESP v3 or RESP 3.0. 121 | 122 | The protocol is designed to handle request-response chats between clients 123 | and servers, where the client performs some kind of request, and the server 124 | replies with some data. The protocol is especially suitable for databases due 125 | to its ability to return complex data types and associated information to 126 | augment the returned data (for instance the popularity index of a given 127 | information). 128 | 129 | The RESP3 protocol can be used asymmetrically, as it is in Redis: only a subset 130 | can be sent by the client to the server, while the server can return the full set 131 | of types available. This is due to the fact that RESP is designed to send non 132 | structured commands like `SET mykey somevalue` or `SADD myset a b c d`. Such 133 | commands can be represented as arrays, where each argument is an array element, 134 | so this is the only type the client needs to send to a server. However different 135 | applications willing to use RESP3 for other goals may just allow the protocol 136 | to be used in a "full duplex" fashion where both the ends can use the full set 137 | of types available. 138 | 139 | Not all parts of RESP3 are mandatory for clients and servers. In the specific 140 | case of Redis, RESP3 describes certain functionalities that will be useful 141 | in the future and likely will not be initially implemented. Other optional parts 142 | of RESP3 may be implemented by Redis only in specific situations, like the 143 | link between the primary database and its replicas, or client connections in 144 | a specific state. 145 | 146 | ## RESP3 types 147 | 148 | RESP3 abandons the confusing wording of the second version of RESP, and uses 149 | a much simpler to understand name for types, so you'll see no mention of 150 | *bulk reply* or *multi bulk reply* in this document. 151 | 152 | The following are the types implemented by RESP3: 153 | 154 | **Types equivalent to RESP version 2** 155 | 156 | * Array: an ordered collection of N other types 157 | * Blob string: binary safe strings 158 | * Simple string: a space efficient non binary safe string 159 | * Simple error: a space efficient non binary safe error code and message 160 | * Number: an integer in the signed 64 bit range 161 | 162 | **Types introduced by RESP3** 163 | 164 | * Null: a single null value replacing RESP v2 `*-1` and `$-1` null values. 165 | * Double: a floating point number 166 | * Boolean: true or false 167 | * Blob error: binary safe error code and message. 168 | * Verbatim string: a binary safe string that should be displayed to humans without any escaping or filtering. For instance the output of `LATENCY DOCTOR` in Redis. 169 | * Map: an ordered collection of key-value pairs. Keys and values can be any other RESP3 type. 170 | * Set: an unordered collection of N other types. 171 | * Attribute: Like the Map type, but the client should keep reading the reply ignoring the attribute type, and return it to the client as additional information. 172 | * Push: Out of band data. The format is like the Array type, but the client should just check the first string element, stating the type of the out of band data, a call a callback if there is one registered for this specific type of push information. Push types are not related to replies, since they are information that the server may push at any time in the connection, so the client should keep reading if it is reading the reply of a command. 173 | * Hello: Like the Map type, but is sent only when the connection between the client and the server is established, in order to welcome the client with different information like the name of the server, its version, and so forth. 174 | * Big number: a large number non representable by the Number type 175 | 176 | ## Simple types 177 | 178 | This section describes all the RESP3 types which are not aggregate types. 179 | They consist of just a single typed element. 180 | 181 | **Blob string** 182 | 183 | The general form is `$\r\n\r\n`. It is basically exactly like 184 | in the previous version of RESP. 185 | 186 | The string `"hello world"` is represented by the following protocol: 187 | 188 | $11 189 | helloworld 190 | 191 | Or as an escaped string: 192 | 193 | "$11\nhelloworld\r\n" 194 | 195 | The length field is limited to the range of an unsigned 64 bit 196 | integer. Zero is a valid length, so the empty string is represented by: 197 | 198 | "$0\r\n\r\n" 199 | 200 | **Simple string** 201 | 202 | The general form is `+\r\n`, so "hello world" is encoded as 203 | 204 | +hello world 205 | 206 | Or as an escaped string: 207 | 208 | "+hello world\r\n" 209 | 210 | Simple strings cannot contain the `` nor the `` characters inside. 211 | 212 | **Simple error** 213 | 214 | This is exactly like a simple string, but the initial byte is `-` instead 215 | of `+`: 216 | 217 | -ERR this is the error description 218 | 219 | Or as an escaped string: 220 | 221 | "-ERR this is the error description\r\n" 222 | 223 | The first word in the error is in upper case and describes the error 224 | code. The remaining string is the error message itself. 225 | The `ERR` error code is the generic one. The error code is useful for 226 | clients to distinguish among different error conditions without having 227 | to do pattern matching in the error message, that may change. 228 | 229 | **Number** 230 | 231 | The general form is `:\r\n`, so the number 1234 is encoded as 232 | 233 | :1234 234 | 235 | Or as an escaped string: 236 | 237 | ":1234\r\n" 238 | 239 | Valid numbers are in the range of the signed 64 bit integer. 240 | Larger numbers should use the Big Number type instead. 241 | 242 | **Null** 243 | 244 | The null type is encoded just as `_\r\n`, which is just the underscore 245 | character followed by the `CR` and `LF` characters. 246 | 247 | **Double** 248 | 249 | The general form is `,\r\n`. For instance 1.23 is 250 | encoded as: 251 | 252 | ,1.23 253 | 254 | Or as an escaped string: 255 | 256 | ",1.23\r\n" 257 | 258 | To just start with `.` assuming an initial zero is invalid. 259 | Exponential format is invalid. 260 | To completely miss the decimal part, that is, the point followed by other 261 | digits, is valid, so the number 10 may be returned both using the number 262 | or double format: 263 | 264 | ":10\r\n" 265 | ",10\r\n" 266 | 267 | However the client library should return a floating point number in one 268 | case and an integer in the other case, if the programming language in which 269 | the client is implemented has a clear distinction between the two types. 270 | 271 | **Boolean** 272 | 273 | True and false values are just represented using `#t\r\n` and `#f\r\n` 274 | sequences. Client libraries implemented in programming languages without 275 | the boolean type should return to the client the canonical values used 276 | to represent true and false in such languages. For instance a C program 277 | should likely return an integer type with a value of 0 or 1. 278 | 279 | **Blob error** 280 | 281 | The general form is `!\r\n\r\n`. It is exactly like the String 282 | type. However like the Simple error type, the first uppercase word represents 283 | the error code. 284 | 285 | The error `"SYNTAX invalid syntax"` is represented by the following protocol: 286 | 287 | !21 288 | SYNTAX invalid syntax 289 | 290 | Or as an escaped string: 291 | 292 | "!21\r\nSYNTAX invalid syntax\r\n" 293 | 294 | **Verbatim string** 295 | 296 | This is exactly like the Blob string type, but the initial byte is `=` instead 297 | of `$`. Moreover the first three bytes provide information about the format 298 | of the following string, which can be `txt` for plain text, or `mkd` for 299 | markdown. The fourth byte is always `:`. Then the real string follows. 300 | 301 | For instance this is a valid verbatim string: 302 | 303 | =15 304 | txt:Some string 305 | 306 | Normal client libraries may ignore completely the difference between this 307 | type and the String type, and return a string in both cases. However interactive 308 | clients such as command line interfaces (for instance `redis-cli`), knows that 309 | the output must be presented to the human user as it is, without quoting 310 | the string. 311 | 312 | For example the Redis command `LATENCY DOCTOR` outputs a report that includes 313 | newlines. It's basically a plain text document. However currently `redis-cli` 314 | requires special handling to avoid quoting the resulting string as it normally 315 | does when a string is received. 316 | 317 | From the `redis-cli` source code: 318 | 319 | ```c 320 | output_raw = 0; 321 | if (!strcasecmp(command,"info") || 322 | ... [snip] ... 323 | (argc == 3 && !strcasecmp(command,"latency") && 324 | !strcasecmp(argv[1],"graph")) || 325 | (argc == 2 && !strcasecmp(command,"latency") && 326 | !strcasecmp(argv[1],"doctor"))) 327 | { 328 | output_raw = 1; 329 | } 330 | ``` 331 | 332 | With the introduction of verbatim strings clients can be simplified not 333 | having to remember if the output must be escaped or not. 334 | 335 | **Big number** 336 | 337 | This type represents very large numbers that are out of the range of 338 | the signed 64 bit numbers that can be represented by the Number type. 339 | 340 | The general form is `(\r\n`, like in the following example: 341 | 342 | (3492890328409238509324850943850943825024385 343 | 344 | Or as an escaped string: 345 | 346 | "(3492890328409238509324850943850943825024385\r\n" 347 | 348 | Big numbers can be positive or negative, but they must not include a 349 | decimal part. Client libraries written in languages with support for big 350 | numbers should just return a big number. When big numbers are not available 351 | the client should return a string, signaling however that the reply is 352 | a big integer when possible (it depends on the API used by the client 353 | library). 354 | 355 | ## Aggregate data types overview 356 | 357 | The types described so far are simple types that just define a single 358 | item of a given type. However the core of RESP3 is the ability to represent 359 | different kinds of aggregate data types having different semantic meaning, 360 | both from the type perspective, and from the protocol perspective. 361 | 362 | In general an aggregate type has a given format stating what is the type 363 | of the aggregate, and how many elements there are inside the aggregate. 364 | Then the single elements follow. Elements of the aggregate type can be, in turn, 365 | other aggregate types, so it is possible to have an array of arrays, or 366 | a map of sets, and so forth. Normally Redis commands will use just a subset 367 | of the possibilities. However with Lua scripts or using Redis modules any 368 | combination is possible. From the point of view of the client library however 369 | this is not complex to handle: every type fully specifies how the client 370 | should translate it to report it to the user, so all the aggregated data types 371 | are implemented as recursive functions that then read N other types. 372 | 373 | The format for every aggregate type in RESP3 is always the same: 374 | 375 | ... numelements other types ... 376 | 377 | The aggregate type char for the Array is `*`, so to represent an array 378 | of three Numbers 1, 2, 3, the following protocol will be emitted: 379 | 380 | *3 381 | :1 382 | :2 383 | :3 384 | 385 | Or as an escaped string: 386 | 387 | "*3\r\n:1\r\n:2\r\n:3\r\n" 388 | 389 | Of course an array can also contain other nested arrays: 390 | 391 | *2 392 | *3 393 | :1 394 | $5 395 | hello 396 | :2 397 | #f 398 | 399 | The above represents the array `[[1,"hello",2],false]` 400 | 401 | Client libraries should return the arrays with a sensible type representing 402 | ordered sequences of elements, accessible at random indexes in constant 403 | or logarithmic time. For instance a Ruby client should return a 404 | *Ruby array* type, while Python should use a *Python list*, and so forth. 405 | 406 | ## Map type 407 | 408 | Maps are represented exactly as arrays, but instead of using the `*` 409 | byte, the encoded value starts with a `%` byte. Moreover the number of 410 | following elements must be even. Maps represent a sequence of field-value 411 | items, basically what we could call a dictionary data structure, or in 412 | other terms, an hash. 413 | 414 | For instance the dictionary represented in JSON by: 415 | 416 | { 417 | "first":1, 418 | "second":2 419 | } 420 | 421 | Is represented in RESP3 as: 422 | 423 | %2 424 | +first 425 | :1 426 | +second 427 | :2 428 | 429 | Note that after the `%` character, what follows is not, like in the array, 430 | the number of single items, but the number of field-value pairs. 431 | 432 | Maps can have any other type as field and value, however Redis will use 433 | only a subset of the available possibilities. For instance it is very unlikely 434 | that Redis commands would return an Array as a key, however Lua scripts 435 | and modules will likely be able to do so. 436 | 437 | Client libraries should return Maps using the idiomatic dictionary type 438 | available. However low level languages like C will likely still return 439 | an array of items, but with type information so that the user can tell 440 | the reply is actually a dictionary. 441 | 442 | ## Set reply 443 | 444 | Sets are exactly like the Array type, but the first byte is `~` instead 445 | of `*`: 446 | 447 | ~5 448 | +orange 449 | +apple 450 | #t 451 | :100 452 | :999 453 | 454 | However they are semantically different because the represented 455 | items are *unordered* collections of elements, so the client library should 456 | return a type that, while not necessarily ordered, has a *test for existence* 457 | operation running in constant or logarithmic time. 458 | 459 | Since many programming languages lack a native set type, a sensible 460 | choice is to return an Hash where the fields are the elements inside the 461 | Set type, and the values are just *true* values or any other value. 462 | 463 | In lower level programming languages such as C, the type should be still 464 | reported as a linear array, together with type information to signal the 465 | user it is a Set type. 466 | 467 | Normally Set replies should not contain the same element emitted multiple 468 | times, but the protocol does not enforce that: client libraries should try 469 | to handle such case, and in case of repeated elements, do some effort to 470 | avoid returning duplicated data, at least if some form of hash is used in 471 | order to return the reply. Otherwise when returning an array just reading 472 | what the protocol contains, duplicated items if present could be passed 473 | by client libraries to the caller. Many implementations will find it very 474 | natural to avoid duplicates. For instance they'll try to add every read 475 | element in some Map or Hash or Set data type, and adding the same element 476 | again will either replace the old copy or will fail silently, retaining the 477 | old copy. 478 | 479 | ## Attribute type 480 | 481 | The attribute type is exactly like the Map type, but instead of the `%` 482 | first byte, the `|` byte is used. Attributes describe a dictionary exactly 483 | like the Map type, however the client should not consider such a dictionary 484 | part of the reply, but *just auxiliary data* that is used in order to 485 | augment the reply. 486 | 487 | For instance newer versions of Redis may include the ability to report, for 488 | every executed command, the popularity of keys. So the reply to the command 489 | `MGET a b` may be the following: 490 | 491 | |1 492 | +key-popularity 493 | %2 494 | $1 495 | a 496 | ,0.1923 497 | $1 498 | b 499 | ,0.0012 500 | *2 501 | :2039123 502 | :9543892 503 | 504 | The actual reply to `MGET` was just the two items array `[2039123,9543892]`, 505 | however the attributes specify the popularity (frequency of requests) of the 506 | keys mentioned in the original command, as floating point numbers from 0 507 | to 1 (at least in the example, the actual Redis implementation may differ). 508 | 509 | When a client reads a reply and encounters an attribute type, it should read 510 | the attribute, and continue reading the reply. The attribute reply should 511 | be accumulated separately, and the user should have a way to access such 512 | attributes. For instance, if we imagine a session in an higher level language, 513 | something like that could happen: 514 | 515 | > r = Redis.new 516 | # 517 | 518 | > r.mget("a","b") 519 | # 520 | 521 | > r 522 | [2039123,9543892] 523 | 524 | > r.attribs 525 | {:key-popularity => {:a => 0.1923, :b => 0.0012}} 526 | 527 | Attributes can appear anywhere before a valid part of the protocol identifying 528 | a given type, and will inform only the part of the reply that immediately 529 | follows, like in the following example: 530 | 531 | *3 532 | :1 533 | :2 534 | |1 535 | +ttl 536 | :3600 537 | :3 538 | 539 | In the above example the third element of the array has an associated 540 | auxiliary information of `{ttl:3600}`. Note that it's not up to the client 541 | library to interpret the attributes, they'll just be passed to the caller 542 | in a sensible way. 543 | 544 | ## Push type 545 | 546 | A push connection is one where the usual *request-response* mode of the 547 | protocol is no longer true, and the server may send to the client asynchronous 548 | data which was not explicitly requested. 549 | 550 | In Redis there is already the concept of a connection pushing data in at least 551 | three different parts of the Redis protocol: 552 | 553 | 1. Pub/Sub is a push-mode connection, where clients receive published data. 554 | 2. The `MONITOR` command implements an *ad-hoc* push mode with a kinda unspecified protocol which is obvious to parse, but still, unspecified. 555 | 3. The Master-Replica link may, at a first glance, be considered a push mode connection. However actually in this case the client (which is the replica), even if is the entity starting the connection, will configure the connection like if the master is a client sending commands, so in practical terms, it is unfair to call this a push mode connection. 556 | 557 | Let's ignore the master-replica link since it is an internal protocol, and 558 | as already noted, is an edge case, and focus on the Pub/Sub and `MONITOR` 559 | modes. They have a common problem: 560 | 561 | 1. The fact that the connection is in push mode is a private *state* of the connection. Otherwise the data we get from Pub/Sub do not contain anything that at the protocol level to make them distinguishable from other replies. 562 | 2. The connection can only be used for Pub/Sub or `MONITOR` once setup in this way, because there is no way (because of the previous problem) in order to tell apart replies from commands and push data. 563 | 564 | Moreover a connection for Pub/Sub cannot be used also for `MONITOR` or any other kind of push notifications. For this reasons RESP3 introduces an explicit 565 | push data type, attempting to solve the above issues. 566 | 567 | RESP3 push data is represented from the point of view of the protocol exactly 568 | like the Array type. However the first byte is `>` instead of `*`, and the 569 | first element of the array is always a String item, representing the kind 570 | of push data the server is sending to the client. All the other fields in the 571 | push array are type dependent, which means that depending on the type string 572 | as first argument, the remaining items will be interpreted following different 573 | conventions. The existing push data in RESP version 2 will be represented 574 | in RESP3 by the push types `pubsub` and `monitor`. 575 | 576 | This is an example of push data: 577 | 578 | >4 579 | +pubsub 580 | +message 581 | +somechannel 582 | +this is the message 583 | 584 | *Note that the above format uses simple strings for simplicity, the 585 | actual Redis implementation would use blob strings instead* 586 | 587 | In the above example the push data type is `pubsub`. For this type, if 588 | the next element is `message` we know that it's a Pub/Sub message (other 589 | sub types may be subscribe, unsubscribe, and so forth), which is followed 590 | by the channel name and the message itself. 591 | 592 | Push data may be interleaved with any protocol data, but always at the top 593 | level, so the client will never find push data in the middle of a Map reply 594 | for instance. 595 | 596 | Clients should normally react to the publication of a push data by invoking 597 | a callback associated with the push data type. Synchronous clients may 598 | instead enter a loop and return every new message or command reply. 599 | 600 | Note that in this mode it is possible to get both replies and push messages 601 | at the same time, interleaved in any way, however the order of the commands 602 | and their replies is not affected: if a command is called, the next reply 603 | (that is not a push reply) received will be the one relative of this command, 604 | and so forth, even if it is possible that there will be push data items to 605 | consume before. 606 | 607 | For instance after a `GET key` command, it is possible to get the two following 608 | valid replies: 609 | 610 | >4 611 | +pubsub 612 | +message 613 | +somechannel 614 | +this is the message 615 | $9 616 | Get-Reply 617 | 618 | Or in inverse order: 619 | 620 | $9 621 | Get-Reply 622 | >4 623 | +pubsub 624 | +message 625 | +somechannel 626 | +this is the message 627 | 628 | Still the client will know that the first non push type reply processed 629 | will be the actual reply to GET. 630 | 631 | However synchronous clients may of course miss for a long time that there is 632 | something to read in the socket, because they only read after a command is 633 | executed, so the client library should still allow the user to specify if the 634 | connection should be monitored for new messages in some way (usually by 635 | entering some loop) or not. For asynchronous clients the implementation is a 636 | lot more obvious. 637 | 638 | ## Hello replies 639 | 640 | Hello replies are exactly like Map replies, but they start with the 641 | byte `@` instead of `%`. They are sent immediately by the server after 642 | the connection with the client, in order to inform the client about the 643 | exact object the server represents. The dictionary in the Hello reply is 644 | server dependent, but there is one item which is mandatory: a field 645 | named `server` must tell the client the name of the service that implements 646 | the RESP3 protocol. In the case of Redis the value will just be `redis`. 647 | All the other fields are service dependent. Redis will likely emit 648 | the following fields: 649 | 650 | * server: "redis" 651 | * version: the Redis (or other software using RESP3) version 652 | * proto: the protocol version ("3" in the case of RESP3) 653 | * id: the client connection ID 654 | 655 | In addition, in the case of the RESP3 implementation of Redis, the following 656 | fields will also be emitted: 657 | 658 | * mode: standalone, sentinel, cluster 659 | * role: master or replica 660 | * modules: list of loaded modules as an array of strings 661 | 662 | The exact number and value of fields emitted by Redis is however currently 663 | a work in progress, you should not rely on the above list. 664 | 665 | Note that the Hello reply still allows a client that wants to be compatible 666 | with older versions of Redis to detect the version of the protocol. Upon 667 | connection the client should send a `PING` command. If the first byte read 668 | will be `@`, the version of the protocol is RESP3, the Hello reply will 669 | be processed, and later the `PING` reply will be read. Instead if the first 670 | byte is not `@` we just read the `PING` reply and switch to RESP version 2 671 | mode. 672 | 673 | ## Acknowledgements 674 | 675 | This specification was written by Salvatore Sanfilippo, however the design was informed by multiple people that contributed worthwhile ideas and improvements. A special thank to Dvir Volk and Yao Yue for the conversation and ideas around 676 | having metadata in requests. 677 | 678 | ## TODOs in this specification 679 | 680 | * Document streaming of big strings. 681 | * Document streaming of arrays. 682 | * Document the optional "inline" protocol. 683 | * Document pipelining 684 | --------------------------------------------------------------------------------