Repository navigation
feat(connection): stop the SQL session on request - #91
Conversation
Closing a connection leaves its SQL session running until its inactivity
timeout passes, which a batch job pays for after it has finished.
Connection.stop_session() closes the connection, then asks the API to
stop the session (DELETE /sql/session/{id}), which stops within seconds.
Connection.session_key reports the key the API created the session under,
read from the session's stored request while connect() waits for READY,
so a caller can check that a session is its own before stopping it.
A connection from connect_direct() has no API to ask: stop_session()
raises NotSupportedError and leaves it open.
| ... # run the job's queries | ||
| finally: | ||
| if conn.session_key == "nightly-build-1234": | ||
| conn.stop_session() |
There was a problem hiding this comment.
medium: Session-key check does not establish exclusive ownership
If two jobs connect with the same session key, the API can reuse one SQL session for both (README.md:351-353). Both connections then pass the example's key check, so the first job to finish calls stop_session() and stops the session while the other job is still using it. The guidance should require a key unique to the job or another way to establish that no other client shares the session.
There was a problem hiding this comment.
Fixed in 3a791d8. The README now says that every connection asking with the same session_key can share a session, so each run of a job needs a key of its own, for example one that includes a run ID. The example builds the key from a run ID before checking conn.session_key and calling stop_session(). dbt-wherobots follows the same rule: its key is dbt-<invocation_id>, which differs for every run.
Two jobs that send the same session_key can share one session, so a matching key proves the session is the run's own only when the key is unique to the run. The example now builds the key from a run ID.
Closing a connection leaves its SQL session running until
shutdown_after_inactive_secondspass, and the server's idle check adds up to about 3 more minutes. A batch job pays for that time after it has finished. dbt-wherobots users running scheduled builds asked for a way to end the session when the job ends (Linear WBC-1621). The API already hasDELETE /sql/session/{session_id}, but the driver had no way to call it.Changes
Connection.stop_session()closes the connection, then sendsDELETE /sql/session/{id}with the headersconnect()used.InterfaceErrorif the API refuses or can't be reached. The connection is closed anyway.connect_direct()has no API URL. On those,stop_session()raisesNotSupportedErrorand leaves the connection open.Connection.session_keyis the key the API created the session under.connect()reads it fromapiPayload.sessionKeyin the session record it already polls until READY, so it costs no extra request. It differs from the requestedsession_keyafter a quota fallback, or when the organization has session keys disabled. A caller checks it before stopping a session that other clients might share.connect()builds the stop function from the session URL and a snapshot of its headers, the same way reconnecting snapshots them.connect_direct()passes the key and the stop function through toConnection.Verification
InterfaceErrorthat names the session;stop_session()closing first and then calling the API;connect_direct()connection raisingNotSupportedErrorand staying open.pre-commit run --all-filespasses.microinaws-us-west-2, against production:connect(session_key=...)returnedsession_keyequal to the requested key, with no fallback.stop_session()returned in 0.39 s. The session wasDESTROY_REQUESTEDat +0.5 s andDESTROYEDat +3.7 s.stop_session()a second time succeeded.dbt-wherobots will use this behind an opt-in setting once it's released.