Skip to content

Commit d750a13

Browse files
tseaverlukesneeringer
authored andcommitted
Drop 'Session' as a promoted, top-level entity in docs. (#3792)
1 parent 7e960e6 commit d750a13

File tree

8 files changed

+314
-417
lines changed

8 files changed

+314
-417
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
Advanced Session Pool Topics
2+
============================
3+
4+
Custom Session Pool Implementations
5+
-----------------------------------
6+
7+
You can supply your own pool implementation, which must satisfy the
8+
contract laid out in
9+
:class:`~google.cloud.spanner.pool.AbstractSessionPool`:
10+
11+
.. code-block:: python
12+
13+
from google.cloud.spanner.pool import AbstractSessionPool
14+
15+
class MyCustomPool(AbstractSessionPool):
16+
17+
def __init__(self, custom_param):
18+
super(MyCustomPool, self).__init__()
19+
self.custom_param = custom_param
20+
21+
def bind(self, database):
22+
...
23+
24+
def get(self, read_only=False):
25+
...
26+
27+
def put(self, session, discard_if_full=True):
28+
...
29+
30+
pool = MyCustomPool(custom_param=42)
31+
database = instance.database(DATABASE_NAME, pool=pool)
32+
33+
Lowering latency for read / query operations
34+
--------------------------------------------
35+
36+
Some applications may need to minimize latency for read operations, including
37+
particularly the overhead of making an API request to create or refresh a
38+
session. :class:`~google.cloud.spanner.pool.PingingPool` is designed for such
39+
applications, which need to configure a background thread to do the work of
40+
keeping the sessions fresh.
41+
42+
Create an instance of :class:`~google.cloud.spanner.pool.PingingPool`:
43+
44+
.. code-block:: python
45+
46+
from google.cloud.spanner import Client
47+
from google.cloud.spanner.pool import PingingPool
48+
49+
client = Client()
50+
instance = client.instance(INSTANCE_NAME)
51+
pool = PingingPool(size=10, default_timeout=5, ping_interval=300)
52+
database = instance.database(DATABASE_NAME, pool=pool)
53+
54+
Set up a background thread to ping the pool's session, keeping them
55+
from becoming stale:
56+
57+
.. code-block:: python
58+
59+
import threading
60+
61+
background = threading.Thread(target=pool.ping, name='ping-pool')
62+
background.daemon = True
63+
background.start()
64+
65+
Lowering latency for mixed read-write operations
66+
------------------------------------------------
67+
68+
Some applications may need to minimize latency for read write operations,
69+
including particularly the overhead of making an API request to create or
70+
refresh a session or to begin a session's transaction.
71+
:class:`~google.cloud.spanner.pool.TransactionPingingPool` is designed for
72+
such applications, which need to configure a background thread to do the work
73+
of keeping the sessions fresh and starting their transactions after use.
74+
75+
Create an instance of
76+
:class:`~google.cloud.spanner.pool.TransactionPingingPool`:
77+
78+
.. code-block:: python
79+
80+
from google.cloud.spanner import Client
81+
from google.cloud.spanner.pool import TransactionPingingPool
82+
83+
client = Client()
84+
instance = client.instance(INSTANCE_NAME)
85+
pool = TransactionPingingPool(size=10, default_timeout=5, ping_interval=300)
86+
database = instance.database(DATABASE_NAME, pool=pool)
87+
88+
Set up a background thread to ping the pool's session, keeping them
89+
from becoming stale, and ensuring that each session has a new transaction
90+
started before it is used:
91+
92+
.. code-block:: python
93+
94+
import threading
95+
96+
background = threading.Thread(target=pool.ping, name='ping-pool')
97+
background.daemon = True
98+
background.start()

docs/spanner/database-usage.rst

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,141 @@ method:
117117
:meth:`~google.cloud.spanner.instance.Operation.finished`
118118
will result in an :exc`ValueError` being raised.
119119

120+
Non-Admin Database Usage
121+
========================
120122

121-
Next Step
122-
---------
123+
Use a Snapshot to Read / Query the Database
124+
-------------------------------------------
123125

124-
Next, learn about :doc:`session-crud-usage`.
126+
A snapshot represents a read-only point-in-time view of the database.
127+
128+
Calling :meth:`~google.cloud.spanner.database.Database.snapshot` with
129+
no arguments creates a snapshot with strong concurrency:
130+
131+
.. code:: python
132+
133+
with database.snapshot() as snapshot:
134+
do_something_with(snapshot)
135+
136+
See :class:`~google.cloud.spanner.snapshot.Snapshot` for the other options
137+
which can be passed.
138+
139+
.. note::
140+
141+
:meth:`~google.cloud.spanner.database.Database.snapshot` returns an
142+
object intended to be used as a Python context manager (i.e., as the
143+
target of a ``with`` statement). Use the instance, and any result
144+
sets returned by its ``read`` or ``execute_sql`` methods, only inside
145+
the block created by the ``with`` statement.
146+
147+
See :doc:`snapshot-usage` for more complete examples of snapshot usage.
148+
149+
Use a Batch to Modify Rows in the Database
150+
------------------------------------------
151+
152+
A batch represents a bundled set of insert/upsert/update/delete operations
153+
on the rows of tables in the database.
154+
155+
.. code:: python
156+
157+
with database.batch() as batch:
158+
batch.insert_or_update(table, columns, rows)
159+
batch.delete(table, keyset_to_delete)
160+
161+
.. note::
162+
163+
:meth:`~google.cloud.spanner.database.Database.batch` returns an
164+
object intended to be used as a Python context manager (i.e., as the
165+
target of a ``with`` statement). It applies any changes made inside
166+
the block of its ``with`` statement when exiting the block, unless an
167+
exception is raised within the block. Use the batch only inside
168+
the block created by the ``with`` statement.
169+
170+
See :doc:`batch-usage` for more complete examples of batch usage.
171+
172+
Use a Transaction to Query / Modify Rows in the Database
173+
--------------------------------------------------------
174+
175+
A transaction represents the union of a "strong" snapshot and a batch:
176+
it allows ``read`` and ``execute_sql`` operations, and accumulates
177+
insert/upsert/update/delete operations.
178+
179+
Because other applications may be performing concurrent updates which
180+
would invalidate the reads / queries, the work done by a transaction needs
181+
to be bundled as a retryable "unit of work" function, which takes the
182+
transaction as a required argument:
183+
184+
.. code:: python
185+
186+
def unit_of_work(transaction):
187+
result = transaction.execute_sql(QUERY)
188+
189+
for emp_id, hours, pay in _compute_pay(result):
190+
transaction.insert_or_update(
191+
table='monthly_hours',
192+
columns=['employee_id', 'month', 'hours', 'pay'],
193+
values=[emp_id, month_start, hours, pay])
194+
195+
database.run_in_transaction(unit_of_work)
196+
197+
.. note::
198+
199+
:meth:`~google.cloud.spanner.database.Database.run_in_transaction`
200+
commits the transaction automatically if the "unit of work" function
201+
returns without raising an exception.
202+
203+
.. note::
204+
205+
:meth:`~google.cloud.spanner.database.Database.run_in_transaction`
206+
retries the "unit of work" function if the read / query operatoins
207+
or the commit are aborted due to concurrent updates
208+
209+
See :doc:`transaction-usage` for more complete examples of transaction usage.
210+
211+
Configuring a session pool for a database
212+
-----------------------------------------
213+
214+
Under the covers, the ``snapshot``, ``batch``, and ``run_in_transaction``
215+
methods use a pool of :class:`~google.cloud.spanner.session.Session` objects
216+
to manage their communication with the back-end. You can configure
217+
one of the pools manually to control the number of sessions, timeouts, etc.,
218+
and then passing it to the :class:`~google.cloud.spanner.database.Database`
219+
constructor:
220+
221+
.. code-block:: python
222+
223+
from google.cloud.spanner import Client
224+
from google.cloud.spanner import FixedSizePool
225+
client = Client()
226+
instance = client.instance(INSTANCE_NAME)
227+
pool = FixedSizePool(size=10, default_timeout=5)
228+
database = instanc.database(DATABASE_NAME, pool=pool)
229+
230+
Note that creating a database with a pool may presume that its database
231+
already exists, as it may need to pre-create sessions (rather than creating
232+
them on demand, as the default implementation does).
233+
234+
You can supply your own pool implementation, which must satisfy the
235+
contract laid out in :class:`~google.cloud.spanner.pool.AbstractSessionPool`:
236+
237+
.. code-block:: python
238+
239+
from google.cloud.pool import AbstractSessionPool
240+
241+
class MyCustomPool(AbstractSessionPool):
242+
243+
def __init__(self, database, custom_param):
244+
super(MyCustomPool, self).__init__(database)
245+
self.custom_param = custom_param
246+
247+
def get(self, read_only=False):
248+
...
249+
250+
def put(self, session, discard_if_full=True):
251+
...
252+
253+
database = instance.database(DATABASE_NAME, pool=pool)
254+
pool = MyCustomPool(database, custom_param=42)
255+
256+
See :doc:`advanced-session-pool-topics` for more advanced coverage of
257+
session pools.

docs/spanner/session-crud-usage.rst

Lines changed: 0 additions & 80 deletions
This file was deleted.

docs/spanner/session-implicit-txn-usage.rst

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)