Skip to content

Instantly share code, notes, and snippets.

Last active June 11, 2024 23:01
Show Gist options
  • Save saurabh500/60e094e14c2820538fdf55ce4b53537e to your computer and use it in GitHub Desktop.
Save saurabh500/60e094e14c2820538fdf55ce4b53537e to your computer and use it in GitHub Desktop.
Explanation of Chain of responsibilities

Chain of responsibilities in Sql Connection open.

The following handlers are used during connection establishment.

graph LR
    A[DataSourceHandler] --> B[TransportHandler]
    B --> C[PreLoginHandler]
    C --> D[LoginHandler]

The handlers will be assembled by the ConnectionExecutor

As we develop the chain of responsibilities, the implementors may need some more information from the previous handler, and may need to enhance the ConnectionRequest object with more information. The implementations can take the call and enhance the ConnectionRequest as the need arises.

The request object being passed around in these handlers is ConnectionRequest

After each handler executes, it enriches the ConnectionRequest with more information.

The ConnectionRequest will be initialized with the connection string.

DataSourceHandler::Handle() -> Parses the Data source and enriches the request object with DataSource

TransportHandler::Handle() -> Uses the DataSource information to establish the transport connection with the server. If TCP is the protocol, then it will levarage the ConnectionString to fetch the other parameters which govern TCP connectivity. It will enrich the ConnectionRequest with the Stream instance, and add more information like the Socket in case of TCP Connectivity. A low level information like the socket, may be used later on to check for the socket being alive, or to dispose the socket.

PreloginHandler::Handle() -> Uses the stream and the information in the connection string to negotiate FedAuth, MARS, SSL etc. It will also decide whether to perform TLS handshake before or after Prelogin negotiation, based on the Encrypt parameter. Prelogin handler, will enhance the request object to set parameters like Mars Enabled, SSLStream, and TDS stream. It will also setup the layering of the TDS stream appropriately based on encryption.

LoginHandler::Handle() -> Uses the TDS stream to send the login packet and then receive the Login acknowledgement from the server. It will leverage a bunch of other parameters in the connection string to negotiate information with the server. The Login Handler will also make sure that we negotiate the features in the feature extension.

The LoginHandler can dynamically enhance the chain of responsibilities to add another TransportHandler, PreloginHandler and LoginHandler if the Routing information is received from the server and the last login handler can keep doing this, till the server stops routing.

Since the routing based handling is based on the response from the server, we cannot determine the chain before executing the TDS request.

    participant ConnectionExecutor
    participant DataSourceHandler
    participant TransportHandler
    participant PreloginHandler
    participant LoginHandler
    ConnectionExecutor->>ConnectionRequest: Initialize with connection string
    ConnectionExecutor->>DataSourceHandler: Handle()
    DataSourceHandler->>ConnectionRequest: Enrich with DataSource
    DataSourceHandler->>TransportHandler: Handle()
    TransportHandler->>ConnectionRequest: Enrich with Stream and Socket
    TransportHandler->>PreloginHandler: Handle()
    PreloginHandler->>ConnectionRequest: Enrich with Mars Enabled, SSLStream, and TDS stream
    PreloginHandler->>LoginHandler: Handle()
    LoginHandler->>ConnectionRequest: Enrich with Login acknowledgement and feature negotiation
    LoginHandler->>LoginHandler: Handle() (if Routing information is received)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment