[book] add doc about request, session and connection management you need to know when writing tests
--- a/doc/book/en/devrepo/testing.rst Tue Jan 17 14:04:56 2012 +0100
+++ b/doc/book/en/devrepo/testing.rst Tue Jan 17 14:05:04 2012 +0100
@@ -460,3 +460,127 @@
``````````````
.. autoclass:: cubicweb.devtools.testlib.CubicWebTC
:members:
+
+
+What you need to know about request and session
+-----------------------------------------------
+
+
+.. image:: ../images/request_session.png
+
+First, remember to think that some code run on a client side, some
+other on the repository side. More precisely:
+
+* client side: web interface, raw db-api connection (cubicweb-ctl shell for
+ instance);
+
+* repository side: RQL query execution, that may trigger hooks and operation.
+
+The client interact with the repository through a db-api connection.
+
+
+A db-api connection is tied to a session in the repository. The connection and
+request objects are unaccessible from repository code / the session object is
+unaccessible from client code (theorically at least).
+
+The :mod:`cubicweb.dbapi` module provides a base request class. The web interface
+provides an extended request class.
+
+
+The `request` object provides access to all cubicweb resources, eg:
+
+* the registry (which itself provides access to the schema and the
+ configuration);
+
+* an underlying db-api connection (when using req.execute, you actually call the
+ db-api);
+
+* other specific resources depending on the client type (url generation according
+ to base url, form parameters, etc.).
+
+
+A `session` provides an api similar to a request regarding RQL execution and
+access to global resources (registry and all), but also have the following
+responsibilities:
+
+* handle transaction data, that will live during the time of a single
+ transaction. This includes the database connections that will be used to
+ execute RQL queries.
+
+* handle persistent data that may be used across different (web) requests
+
+* security and hooks control (not possible through a request)
+
+
+The `_cw` attribute
+```````````````````
+The `_cw` attribute available on every application object provides access to all
+cubicweb resources, eg:
+
+For code running on the client side (eg web interface view), `_cw` is a request
+instance.
+
+For code running on the repository side (hooks and operation), `_cw` is a session
+instance.
+
+
+Beware some views may be called with a session (eg notifications) or with a
+DB-API request. In the later case, see :meth:`use_web_compatible_requests` on
+:class:`Connection` instances.
+
+
+Request, session and transaction
+````````````````````````````````
+
+In the web interface, an HTTP request is handle by a single request, which will
+be thrown way once the response send.
+
+The web publisher handle the transaction:
+
+* commit / rollback is done automatically
+* you should not commit / rollback explicitly
+
+When using a raw db-api, you're on your own regarding transaction.
+
+On the other hand, db-api connection and session live from a user login to its logout.
+
+Because session lives for a long time, and database connections is a limited
+resource, we can't bound a session to its own database connection for all its
+lifetime. The repository handles a pool of connections (4 by default), and it's
+responsible to attribute them as needed.
+
+Let's detail the process:
+
+1. an incoming RQL query comes from a client to the repository
+
+2. the repository attributes a database connection to the session
+
+3. the repository's querier execute the query
+
+4. this query may trigger hooks. Hooks and operation may execute some rql queries
+ through `_cw.execute`. Those queries go directly to the querier, hence don't
+ touch the database connection, they use the one attributed in 2.
+
+5. the repository's get the result of the query in 1. If it was a RQL read query,
+ the database connection is released. If it was a write query, the connection
+ is then tied to the session until the transaction is commited or rollbacked.
+
+6. results are sent back to the client
+
+This implies several things:
+
+* when using a request, or code executed in hooks, this database connection
+ handling is totally transparent
+
+* however, take care when writing test: you are usually faking / testing both the
+ server and the client side, so you have to decide when to use self.request() /
+ self.session. Ask yourself "where the code I want to test will be running,
+ client or repository side ?". The response is usually : use a request :)
+ However, if you really need using a session:
+
+ - commit / rollback will free the database connection (unless explicitly told
+ not to do so).
+
+ - if you issue a query after that without asking for a database connection
+ (`session.get_cnxset()`), you will end up with a 'None type has no attribute
+ source()' error
Binary file doc/book/en/images/request_session.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/images/request_session.svg Tue Jan 17 14:05:04 2012 +0100
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="85.960938"
+ height="12.382812"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.1 r9760"
+ sodipodi:docname="request_session.svg">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3822"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="25.928992"
+ inkscape:cy="-185.87004"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="766"
+ inkscape:window-height="1151"
+ inkscape:window-x="1152"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0"
+ inkscape:snap-global="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-263.52249,-495.73373)">
+ <rect
+ style="fill:#ffffff;stroke:#000000;stroke-width:0.92460138;stroke-opacity:1"
+ id="rect3773"
+ width="214.15233"
+ height="184.80336"
+ x="57.578697"
+ y="366.01306" />
+ <rect
+ id="rect2985"
+ width="216.86372"
+ height="183.54575"
+ x="348.50262"
+ y="367.78079"
+ style="fill:#ffffff;stroke:#000000;stroke-width:0.55298227;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="376.7869"
+ y="399.80365"
+ id="text3755"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3757"
+ x="376.7869"
+ y="399.80365">Repository</tspan></text>
+ <rect
+ style="fill:#ffffff;stroke:#000000;stroke-opacity:1"
+ id="rect3759"
+ width="144.45181"
+ height="104.04572"
+ x="237.38585"
+ y="423.03714" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="262.63968"
+ y="470.51431"
+ id="text3761"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3763"
+ x="262.63968"
+ y="470.51431">DB API</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="262.63968"
+ y="507.88998"
+ id="text3765"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3767"
+ x="262.63968"
+ y="507.88998">connection</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="419.21332"
+ y="509.91025"
+ id="text3769"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3771"
+ x="419.21332"
+ y="509.91025">session</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="102.02541"
+ y="397.78333"
+ id="text3775"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3777"
+ x="102.02541"
+ y="397.78333">Client</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="116.16754"
+ y="507.88995"
+ id="text3779"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3781"
+ x="116.16754"
+ y="507.88995">request</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="361.50729"
+ y="585.89832"
+ id="text3802"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3804"
+ x="361.50729"
+ y="585.89832">database </tspan><tspan
+ sodipodi:role="line"
+ x="361.50729"
+ y="605.89832"
+ id="tspan3806">connection</tspan></text>
+ <rect
+ style="fill:#ffffff;stroke:#000000;stroke-width:1.48014534;stroke-opacity:1"
+ id="rect3808"
+ width="192.09367"
+ height="58.095726"
+ x="365.79443"
+ y="621.50018" />
+ <text
+ xml:space="preserve"
+ style="font-size:36px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="369.5885"
+ y="662.66992"
+ id="text3810"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3812"
+ x="369.5885"
+ y="662.66992">Database</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
+ d="M 197.57252,125.76645 195.76971,55.592808"
+ id="path4260"
+ inkscape:connector-type="polyline"
+ inkscape:connector-curvature="3"
+ inkscape:connection-start="#rect3808"
+ inkscape:connection-start-point="d4"
+ inkscape:connection-end="#rect2985"
+ inkscape:connection-end-point="d4"
+ transform="translate(263.52249,495.73373)" />
+ </g>
+</svg>