WL#12375: xprotocol: reset connection state
Motivation
xprotocol supports
- Session::Reset
- Session::Close
- Connection::Close
messages to
- reset the current session state without reauth
- close the current session and force a reauth, without closing the connection
- close the connection
Due to
- SESS_RESET calls "close current session, force reauth"
- SESS_CLOSE calls "close current connection"
the implementation in MySQL 8.0.13 and earlier doesn't match the indent behaviour.
Background
Behaviour
The xprotocol defines the behaviour of messages:
- session-reset
- reset current session (drop temp-tables, session-variables, transactions, ...). Connections stays open and session authenticated.
- session-close
- close current session. Connection stays open and session needs to authenticated again.
- connection-close
- close current connection.
Message-IDs
Through ClientMessages::Type they have message-ids and symbolic names assigned:
msg-id | client-message name | message |
---|---|---|
6 | SESS_RESET | Session::Reset |
7 | SESS_CLOSE | Session::Close |
Old Client/Old Server (8.0.13) [broken behaviour]
expected client behaviour | msg-id | server-behaviour |
---|---|---|
session-reset | 6 | session-close |
session-close | 7 | connection-close |
The 8.0.13 protocol description lists
- msg-id 6 as SESS_RESET, but the implemented behaviour matches Session::Close.
- msg-id 7 as SESS_CLOSE, but the implemented behaviour matches Connection::Close.
While the message-name implies one behaviour, the implementation provides another.
It has no way to reset the connections state without having to go through the authentication sequence.
Goal
- fix invalid behaviour of msg-id 6 in backward compatible way
- fix invalid hehaviour of msg-id 7 in backward compatible way
- allow the reset the session state
Design Requirement
- DR1
- New implementation SHALL NOT be more expensive on the protocol side then working around old, broken behaviour.
Requirements
- FR1
- New clients MUST be able to reset a session without reauthenticating nor reopening the connection
- FR2
- New clients MUST be able to close a session without requiring reopening a connection
- FR3
- Old clients sending a SESS_RESET (msg-id 6) message without payload MUST receive the same behaviour from new servers as they received from old servers: Session::Close
- FR4
- Old clients sending a SESS_CLOSE (msg-id 7) message without payload MUST receive the same behaviour from new servers as they received from old servers: Connection::Close
- FR5
- session-reset MUST NOT change the client_id
Implementation
Assumption
- session-reset behaviour is a subset of session-close behaviour
- session-close behaviour is a subset of connection-close behaviour
A client asking for session-reset and receiving an Ok, but getting the behaviour session-close, still got the session properly reset.
A client asking for session-close and receiving an Ok, but getting the behaviour connection-close, still got the session closed and left in a state that needs reauthentication. The client can't distinguish if the connection if closed due to wrong server behaviour or very small wait-timeout.
New Client/New Server
expected client-behaviour | client msg-id | msg-payload | server-behaviour |
---|---|---|---|
session-close | 6 (SESS_RESET) | {} | session-close |
session-reset | 6 (SESS_RESET) | { keep_open: 1 } | session-reset |
session-close | 7 (SESS_CLOSE) | {} | session-close |
The new implementation does:
add a new field to msg-id 6: bool keep_open, default false
- if keep_open is true
- the session will be reset (temp-tables droped, user-vars removed, locks removed, transactions rolledback, ...), but stays authenticated.
- otherwise, the session will be closed and needs to be authenticated again.
- Important: New clients MUST check if the server supports the new field "keep_open" with an Expect.Open(has_field=6.1).
fix the behaviour of msg-id 7 to NOT close the connection immediately anymore.
- the connection will be closed after mysqlx_wait_timeout
Compatibility
Old Client/New Server
Old clients that send a msg-id 6, assuming session-reset behaviour, will get and Ok and the session is closed. The following statements will fail with "not authenticated" (same as older servers did). The client will report an error to the user. At this time, no client implements behaviour.
Old clients that send msg-id 7, assuming session-close behaviour, will get an Ok and the session gets closed.
expected client-behaviour | client msg-id | msg-payload | server-behaviour |
---|---|---|---|
session-close | 6 (SESS_RESET) | {} | session-close |
session-close | 7 (SESS_CLOSE) | {} | session-close |
New Client/Old Server
New clients that send msg-id 6, assuming session-close behaviour, will get the expected behaviour.
New clients that send msg-id 6 { keep_open: true }, assuming session-reset behaviour, AND check with Expectations that the server support the keep_open field, will get a failed expectation and should fall back to
- msg-id 6 (session-close)
- msg-id 4 (session-authenticate-start)
to get the same behaviour.
New clients that send msg-id 7, assuming session-close behaviour, will get connection-close behaviour and need to reopen the connection.
expected client-behaviour | client msg-id | msg-payload | server-behaviour |
---|---|---|---|
session-close | 6 (SESS_RESET) | {} | session-close |
session-reset | 6 (SESS_RESET) | { keep_open: 1 } | Invalid (1) |
session-close | 7 (SESS_CLOSE) | {} | connection-close |
(1) client must ask with Expect.Open(has_field=6.1) before use
Notes
"Expectation blocks" are tied to connection, not to the session. This means that Mysqlx.Session.Reset(keep_open:true) must preserve opened expectation blocks.