Skip to content

Commit 1408577

Browse files
annibondannisimpsonkrylosov-aa
authored
Concurrent & remaining docs suggestions (#16)
* docs edits index getting started problem it solves Base docs suggestions as per the commit message. Will open a separate PR for the other stuff I'd suggest in general. * made minor/moderate wording changes from the Usage Examples and API References sections, including the text represnted in code which has been COMMENTED OUT, NOT THE CODE ITSELF * Docs changes to API Reference section * cleaned up testing section using lists, v small grammar changes for master_replica and concurrent_queries --------- Co-authored-by: annibond <anni.simpson@gmail.com> Co-authored-by: krylosov-aa <krylosov.andrew@gmail.com>
1 parent 07c3e20 commit 1408577

File tree

7 files changed

+53
-69
lines changed

7 files changed

+53
-69
lines changed

docs/api/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ <h3 id="connect">connect</h3>
213213
</code></pre>
214214
<p>Establishes a connection to the specified host.
215215
It doesn’t need to be called explicitly.
216-
If you don't use the call, the first session request will automatically
216+
The first session request automatically
217217
establishes the connection.</p>
218218
<hr />
219219
<h3 id="change_host">change_host</h3>
@@ -391,7 +391,7 @@ <h3 id="set_test_context">set_test_context</h3>
391391
It is intended to test the application when it shares a single transaction.</p>
392392
<p>Use <code>auto_close=False</code> if you’re using a test session and transaction
393393
that you close elsewhere in your code.</p>
394-
<p>Use <code>auto_close=True</code> if you want to call a function
394+
<p>Use <code>auto_close=True</code> to call a function
395395
in a test that uses a context while the middleware is not
396396
active. All sessions close automatically.</p>
397397
<hr />
@@ -404,6 +404,7 @@ <h3 id="put_savepoint_session_in_ctx">put_savepoint_session_in_ctx</h3>
404404
<p>Sets the context to a session that uses a save point instead of creating
405405
a transaction. You need to pass the session you're using inside
406406
your tests to attach a new session to the same connection.</p>
407+
407408
<pre><code>It is important to use this function inside set_test_context.
408409
</code></pre>
409410
<p>Learn more about <a href="../testing/">testing</a></p>

docs/concurrent_queries/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@
104104
<h1 id="concurrent-sql-queries">Concurrent sql queries</h1>
105105
<p>Concurrent query execution deserves special attention.
106106
In SQLAlchemy, you can’t run multiple queries concurrently within the same
107-
session - you need to create a new one.</p>
107+
session. You need to create a new one.</p>
108108
<p>The library provides two simple ways to execute queries concurrently:</p>
109109
<ul>
110-
<li>Run a function in a new context - <code>run_in_new_ctx</code></li>
111-
<li>Create a new session that is completely independent of the current context -
110+
<li>Run a function in a new context: <code>run_in_new_ctx</code></li>
111+
<li>Create a new session that is independent of the current context:
112112
<code>new_non_ctx_atomic_session</code> or <code>new_non_ctx_session</code></li>
113113
</ul>
114114
<pre><code class="language-python">import asyncio

docs/examples/index.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,7 @@ <h3 id="manually-close-the-transaction-and-session">Manually close the transacti
223223

224224
# We closed the transaction
225225
await commit_db_session(connection)
226-
227-
# We closed the session and returned the connection to the pool.
226+
# We closed the session, which returned the connection to the pool automatically.
228227
# Use if you have more work you need to complete without keeping the connection open.
229228
await close_db_session(connection)
230229

@@ -324,7 +323,7 @@ <h3 id="rollback">Rollback</h3>
324323
await session.execute(stmt)
325324

326325
raise Exception(&quot;Some exception&quot;)
327-
# transaction rolls back automatically
326+
# transaction automatically rolls back
328327
</code></pre>
329328
<pre><code class="language-python">from fastapi import HTTPException
330329

docs/master_replica/index.html

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,24 @@
103103
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
104104
<div class="section" itemprop="articleBody">
105105

106-
<h1 id="masterreplica-or-several-databases-at-the-same-time">Master/Replica or several databases at the same time</h1>
107-
<p>This is why <code>db_session</code> and other functions accept a <code>DBConnect</code> instance as
108-
input.
109-
This approach allows you to work with multiple hosts simultaneously -
110-
for example, with both a master and a replica.</p>
111-
<p><code>DBConnect</code> can also accept factory functions instead of ready-made objects,
112-
making it easy to switch hosts when needed.</p>
113-
<p>For example, <code>libpq</code> can detect the master and replica when creating an engine,
106+
<h1 id="masterreplica-or-several-databases-at-the-same-time">Using multiple databases at the same time (master/replica)</h1>
107+
<p><code>db_session</code> and other functions accept a <code>DBConnect</code> instance as input. This approach allows you to work with multiple hosts simultaneously. This system allows you to manage scalability and version control.</p>
108+
<ul>
109+
<li><b>Master:</b> The primary database which runs the "live" version of your information, the location of your primary data set. The master database
110+
handles INSERT, DELETE, and UPDATE API calls.
111+
</li>
112+
<li><b>Replicas:</b> Secondary database(s) which run READ-ONLY versions of your information and receive updates from the master database.</li>
113+
</ul>
114+
<p><code>DBConnect</code> accepts factory functions instead of ready-made objects, making it easy to switch hosts when needed.</p>
115+
116+
<p><code>libpq</code> can detect the master and replica when creating an engine,
114117
but it only does this once - at creation time.
115-
The before_create_session_handler hook allows you to change the host at
118+
The <code>before_create_session_handler</code> hook allows you to change the host at
116119
runtime if the master or replica changes.
117-
You’ll need third-party functionality to determine which host is the master
118-
or the replica.</p>
119-
<h4 id="i-have-an-extremely-lightweight-microservice-pg-status-that-fits-perfectly-here">I have an extremely lightweight microservice <a href="https://github.com/krylosov-aa/pg-status">pg-status</a> that fits perfectly here.</h4>
120-
<p>The engine is not created immediately when <code>DBConnect</code> is initialized -
121-
it is created only on the first request.
120+
121+
<p><b>You need third-party functionality to determine which host is the master or the replica.</b></p>
122+
<h4 id="change_host">I have an extremely lightweight microservice <a href="https://github.com/krylosov-aa/pg-status">pg-status</a> that fits perfectly here</h4>
123+
<p>The engine is not created when <code>DBConnect</code> initializes, also known as lazy initialization. It is created only on the first request.
122124
The library uses lazy initialization in many places.</p>
123125
<pre><code class="language-python">from context_async_sqlalchemy import DBConnect
124126

docs/search/search_index.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/testing/index.html

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -106,47 +106,30 @@
106106
<div class="section" itemprop="articleBody">
107107

108108
<h1 id="testing">Testing</h1>
109-
<p>When testing with a real database, one important problem needs to be
110-
solved - ensuring data isolation between tests.</p>
111-
<p>There are basically two approaches:</p>
112-
<ol>
113-
<li>Separate sessions</li>
114-
</ol>
115-
<p>The test has its own session that it uses to prepare data and verify
116-
results after execution.
117-
The application also has its own session.
118-
Data isolation is achieved by clearing all tables at the end of each test
119-
(and once before running all tests).</p>
120-
<ol>
121-
<li>Shared session and transaction
122-
The test and the application share the same session and transaction.
123-
Data isolation is achieved by rolling back the transaction at
124-
the end of the test.</li>
125-
</ol>
126-
<p>Personally, I prefer the first option, because it is a more "honest" way
127-
to test the application.
128-
We can verify how it handles sessions and transactions on its own.
129-
It’s also convenient to inspect the database state when a test is paused.</p>
130-
<p>Sometimes, there are complex session management scenarios (for example,
131-
concurrent query execution) where other types of testing are either
132-
impossible or very difficult.</p>
133-
<p>The main disadvantage of this approach is the slower execution speed.
134-
Since we clear all tables after each test, this process takes additional time.</p>
135-
<p>This is where the second approach comes in - its main advantage is speed,
136-
as rolling back a transaction is very fast.</p>
109+
<p>When testing with a real database, one important problem needs to be solved: ensuring data isolation between tests. There are two approaches:
110+
<ol>
111+
<li><b>Separate sessions</b>: The test uses its own session that prepares data and verifies results after execution. The application also has its own session.
112+
<ul>
113+
<li>It is a more "honest" way to test the application.</li>
114+
<li>Verifies how it handles sessions and transactions automatically.</li>
115+
<li>The ability to inspect the database state when the test is paused.</li>
116+
<li>Complex session management scenarios make other test methods difficult or impossible (e.g., concurrent query execution).</li>
117+
</ul>
118+
<li><b>Shared session and transaction:</b> The test and the application share the same session and transaction.
119+
<ul>
120+
<li>Rolling back transactions is faster and takes less time than starting a new session.</li>
121+
</ul>
122+
</ol>
123+
</p>
124+
137125
<p>In my projects, I use both approaches at the same time:</p>
138126
<ul>
139-
<li>For most tests with simple or common logic, I use a shared transaction
140-
for the test and the application</li>
141-
<li>For more complex cases, or ones that cannot be tested this way,
142-
I use separate transactions.</li>
127+
<li>For most tests with simple or common logic, I use a shared transaction for the test and the application</li>
128+
<li>For more complex cases, or ones that cannot be tested with separate sessions, I use separate transactions.</li>
143129
</ul>
144-
<p>This combination allows for both good performance and convenient testing.</p>
145-
<p>The library provides several utilities that can be used in tests - for
146-
example, in fixtures.
147-
They help create tests that share a common transaction between the test
148-
and the application, so data isolation between tests is achieved through
149-
fast transaction rollback.</p>
130+
<p>The library provides several utilities that can be used in tests (e.g., fixtures). They create tests that share a common transaction between the test
131+
and the application. You achieve data isolation by rolling back transactions.
132+
150133
<p>You can see these capabilities in the examples:</p>
151134
<p><a href="https://github.com/krylosov-aa/context-async-sqlalchemy/blob/main/examples/fastapi_example/tests/transactional">Here are tests with a common transaction between the
152135
application and the tests.</a></p>

docs_sources/docs/api.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ from the target host.
8888
```python
8989
async def create_session(self: DBConnect) -> AsyncSession:
9090
```
91-
Creates a new session the library uses internally.
92-
You never need to call it directly. (Only maybe in some special cases.)
91+
Creates a new session. Used internally by the library. You may never need to call it directly.
9392
---
9493

9594
### session_maker
@@ -196,7 +195,8 @@ async def atomic_db_session(
196195
A context manager you can use to wrap another function which
197196
uses a context session, making that call isolated within its own transaction.
198197

199-
Several options define how a function handles an open transaction.
198+
There are several options that define how the function will handle
199+
an open transaction.
200200

201201
current_transaction:
202202

@@ -219,19 +219,18 @@ Commits the active session.
219219
```python
220220
async def rollback_db_session(connect: DBConnect) -> None:
221221
```
222-
Rolls back an active session.
222+
Rollbacks the active session.
223223

224224
---
225225

226226
### close_db_session
227227
```python
228228
async def close_db_session(connect: DBConnect) -> None:
229229
```
230-
Closes the current context session and returns the connection to the pool.
231-
If you close an uncommitted transaction, the connection rolls back
230+
Closes the current context session. The connection is returned to the pool.
231+
If you close an uncommitted transaction, the connection rolls back.
232232

233-
This is useful when you need to run a database query at the start of the
234-
handler, then continue working over time without keeping the connection open.
233+
Use if you have more work you need to complete without keeping the connection open.
235234

236235
---
237236

0 commit comments

Comments
 (0)