Replies: 1 comment
-
CHANGELOG2022-07-07
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
#3933 has been updated quite a few times, this is a summarized version of the results.
1. The Concept of State
State is defined as a payload of data that provides a context for EdgeQL commands to run with. Currently, state is consist of module aliases, "session" config and global values, for example:
State is sent from the client with
ParseandExecutemessages, and returned from the server inCommandCompletemessages. The server compiles and executes the given command(s) in the context of the given state, and command(s) inExecutemay modify the state, thenCommandCompletewould include an updated state.State is serialized in the same way as input/output arguments are serialized. A new type descriptor "input shape descriptor" is used to describe state data as sparse objects. This is similar to the object shape descriptor, only that sparse objects will skip serializing missing properties. For example, the state itself is a sparse object, values of its keys
configandglobalsare also sparse objects.2. On establishing connections
Once the server has confirmed successful authentication with AuthenticationOK, it then sends the following messages:
StateDataDescriptionmessageThe new
StateDataDescriptionmessage contains an input shape descriptor of the state in the following format:The client could build codecs from the type descriptor and cache them for future state (de-)serialization on demand.
3. Send command request with state
The
ParseandExecutemessages are updated to allow the client send states:struct Parse { // Message type ('P'). uint8 mtype = 0x50; // Length of message contents in bytes, // including self. uint32 message_length; // A set of message headers. uint16 num_headers; Header headers[num_headers]; // A bit mask of allowed capabilities. uint64<Capability> allowed_capabilities; // A bit mask of query options. uint64<CompilationFlag> compilation_flags; // Implicit LIMIT clause on returned sets. uint64 implicit_limit; // Data output format. uint8<OutputFormat> output_format; // Expected result cardinality. uint8<Cardinality> expected_cardinality; // Command text. string command_text; + + // State data descriptor ID. + uuid state_typedesc_id; + + // Encoded state data. + bytes state_data; }; struct Execute { // Message type ('O'). uint8 mtype = 0x4f; // Length of message contents in bytes, // including self. uint32 message_length; // A set of message headers. uint16 num_headers; Header headers[num_headers]; // A bit mask of allowed capabilities. uint64<Capability> allowed_capabilities; // A bit mask of query options. uint64<CompilationFlag> compilation_flags; // Implicit LIMIT clause on returned sets. uint64 implicit_limit; // Data output format. uint8<OutputFormat> output_format; // Expected result cardinality. uint8<Cardinality> expected_cardinality; // Command text. string command_text; + + // State data descriptor ID. + uuid state_typedesc_id; + + // Encoded state data. + bytes state_data; // Argument data descriptor ID. uuid input_typedesc_id; // Output data descriptor ID. uuid output_typedesc_id; // Encoded argument data. bytes arguments; };If the client decides not to send state, the
state_typedesc_idcan be set to a special null type ID00000000-0000-0000-0000-000000000000, the server will then use the default state to compile and/or execute the given commands accordingly.Otherwise, the given
state_typedesc_idis expected to match the current state type on the server-side. On mismatch, the server will return aStateDataDescriptionmessage with the current state type descriptor, immediately followed by a new errorStateMismatchErrorin anErrorResponsemessage.4. Server returns state
On successful execution of EdgeQL commands, the server will return:
CommandDataDescriptionif the output type identifier mismatches;Datamessages.StateDataDescriptionif the given command(s) modified the state type (e.g. creating a new global);CommandCompletemessage with the state as follows:struct CommandComplete { // Message type ('C'). uint8 mtype = 0x43; // Length of message contents in bytes, // including self. uint32 message_length; // A set of message headers. uint16 num_headers; Header headers[num_headers]; // A bit mask of allowed capabilities. uint64<Capability> capabilities; // Command status. string status; + + // State data descriptor ID. + uuid state_typedesc_id; + + // Encoded state data. + bytes state_data; };If the executed command didn't change the state values, the
state_typedesc_idwill be set to the same special null type ID00000000-0000-0000-0000-000000000000, indicating the state was not changed. In this case,state_datais a zero-lengthedbytes. If the state values are changed by the command, thestate_typedesc_idis guaranteed to be the same as it was in theExecuterequest message, even if the state schema is concurrently changed in other sessions, unless thisExecuteis also changing the state schema.Please note, state DDL and mutation of the state values are transactional. That means,
rollbackcommand could return aStateDataDescriptionmessage and aCommandCompletemessage with concrete state data, if the state schema or state values were updated in the transaction to be rolled back.5. Client bindings guideline
The client bindings is recommended to provide special APIs for users to set state. Particularly,
client.with_config(),client.with_aliases()andclient.with_globals(). Becauseclientis assumed to be safely used in multithreading or different asynchronous tasks/coroutines, EdgeQL commands that modify the state likeset global,set alias,set module,configure sessionand theirresetvariants would be racy. These commands are covered in the capabilitysession config, so the client could either disable this capability inquery()andexecute(), or prevent the server-returned state from affecting other threads/tasks/coroutines.6. State type changes while state is not default
If a global type is changed while its value is set, the DDL must use
set global ... set type ... using ...to instruct the server to convert the value.If the state type is concurrently modified by other clients,
StateMismatchErrorwill be raised from the server handling the next command with an outdated state type identifier. The client should be ready to handle this error, by e.g. re-encoding the state with the codecs built from the updated state type descriptors. If the state cannot be encoded, the client could drop the connection with a proper error.Beta Was this translation helpful? Give feedback.
All reactions