o Sb=@sdZddlZddlZddlZddlmZddlmZm Z m Z m Z mZm Z m Z mZddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZmZmZmZm Z m!Z!dd l"m#Z#dd l$m%Z%ddl&m'Z'm(Z(ddl)m*Z*ddl+m,Z,Gddde-Z.Gddde-Z/ddZ0Gddde-Z1Gddde-Z2Gddde-Z3de de fdd Z4d!d"Z5e#e6d#d$gBZ7d%Z8d&d'Z9ed(Z:erdd)l;mGd.d/d/e-Z?Gd0d1d1ej@ZAdS)2aLogical sessions for ordering sequential operations. .. versionadded:: 3.6 Causally Consistent Reads ========================= .. code-block:: python with client.start_session(causal_consistency=True) as session: collection = client.db.collection collection.update_one({'_id': 1}, {'$set': {'x': 10}}, session=session) secondary_c = collection.with_options( read_preference=ReadPreference.SECONDARY) # A secondary read waits for replication of the write. secondary_c.find_one({'_id': 1}, session=session) If `causal_consistency` is True (the default), read operations that use the session are causally after previous read and write operations. Using a causally consistent session, an application can read its own writes and is guaranteed monotonic reads, even when reading from replica set secondaries. .. seealso:: The MongoDB documentation on `causal-consistency `_. .. _transactions-ref: Transactions ============ .. versionadded:: 3.7 MongoDB 4.0 adds support for transactions on replica set primaries. A transaction is associated with a :class:`ClientSession`. To start a transaction on a session, use :meth:`ClientSession.start_transaction` in a with-statement. Then, execute an operation within the transaction by passing the session to the operation: .. code-block:: python orders = client.db.orders inventory = client.db.inventory with client.start_session() as session: with session.start_transaction(): orders.insert_one({"sku": "abc123", "qty": 100}, session=session) inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}}, {"$inc": {"qty": -100}}, session=session) Upon normal completion of ``with session.start_transaction()`` block, the transaction automatically calls :meth:`ClientSession.commit_transaction`. If the block exits with an exception, the transaction automatically calls :meth:`ClientSession.abort_transaction`. In general, multi-document transactions only support read/write (CRUD) operations on existing collections. However, MongoDB 4.4 adds support for creating collections and indexes with some limitations, including an insert operation that would result in the creation of a new collection. For a complete description of all the supported and unsupported operations see the `MongoDB server's documentation for transactions `_. A session may only have a single active transaction at a time, multiple transactions on the same session can be executed in sequence. Sharded Transactions ^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.9 PyMongo 3.9 adds support for transactions on sharded clusters running MongoDB >=4.2. Sharded transactions have the same API as replica set transactions. When running a transaction against a sharded cluster, the session is pinned to the mongos server selected for the first operation in the transaction. All subsequent operations that are part of the same transaction are routed to the same mongos server. When the transaction is completed, by running either commitTransaction or abortTransaction, the session is unpinned. .. seealso:: The MongoDB documentation on `transactions `_. .. _snapshot-reads-ref: Snapshot Reads ============== .. versionadded:: 3.12 MongoDB 5.0 adds support for snapshot reads. Snapshot reads are requested by passing the ``snapshot`` option to :meth:`~pymongo.mongo_client.MongoClient.start_session`. If ``snapshot`` is True, all read operations that use this session read data from the same snapshot timestamp. The server chooses the latest majority-committed snapshot timestamp when executing the first read operation using the session. Subsequent reads on this session read from the same snapshot timestamp. Snapshot reads are also supported when reading from replica set secondaries. .. code-block:: python # Each read using this session reads data from the same point in time. with client.start_session(snapshot=True) as session: order = orders.find_one({"sku": "abc123"}, session=session) inventory = inventory.find_one({"sku": "abc123"}, session=session) Snapshot Reads Limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^ Snapshot reads sessions are incompatible with ``causal_consistency=True``. Only the following read operations are supported in a snapshot reads session: - :meth:`~pymongo.collection.Collection.find` - :meth:`~pymongo.collection.Collection.find_one` - :meth:`~pymongo.collection.Collection.aggregate` - :meth:`~pymongo.collection.Collection.count_documents` - :meth:`~pymongo.collection.Collection.distinct` (on unsharded collections) Classes ======= N)Mapping) TYPE_CHECKINGAnyCallableContextManagerrNoReturnOptionalTypeVar)Binary)Int64)SON) Timestamp)_csot)_SocketManager)ConfigurationErrorConnectionFailureInvalidOperationOperationFailure PyMongoError WTimeoutError)_RETRYABLE_ERROR_CODES) ReadConcern)ReadPreference _ServerMode) SERVER_TYPE) WriteConcernc @s|eZdZdZ   ddeededdeeddfd d Zedefd d Zededfd dZ edeefddZ dS)SessionOptionsaOptions for a new :class:`ClientSession`. :Parameters: - `causal_consistency` (optional): If True, read operations are causally ordered within the session. Defaults to True when the ``snapshot`` option is ``False``. - `default_transaction_options` (optional): The default TransactionOptions to use for transactions started on this session. - `snapshot` (optional): If True, then all reads performed using this session will read from the same snapshot. This option is incompatible with ``causal_consistency=True``. Defaults to ``False``. .. versionchanged:: 3.12 Added the ``snapshot`` parameter. NFcausal_consistencydefault_transaction_optionsTransactionOptionssnapshotreturncCsX|r |rtdd}n|durd}||_|dur$t|ts$td|f||_||_dS)Nz5snapshot reads do not support causal_consistency=TrueFTzedefault_transaction_options must be an instance of pymongo.client_session.TransactionOptions, not: %r)r_causal_consistency isinstancer TypeError_default_transaction_options _snapshot)selfrrr r(=/tmp/pip-target-onvjaxws/lib/python/pymongo/client_session.py__init__s   zSessionOptions.__init__cC|jS)z)Whether causal consistency is configured.)r"r'r(r(r)rz!SessionOptions.causal_consistencycCr+)zThe default TransactionOptions to use for transactions started on this session. .. versionadded:: 3.7 )r%r,r(r(r)rsz*SessionOptions.default_transaction_optionscCr+)zOWhether snapshot reads are configured. .. versionadded:: 3.12 )r&r,r(r(r)r zSessionOptions.snapshot)NNF) __name__ __module__ __qualname____doc__rboolr*propertyrrr r(r(r(r)rs( rc @seZdZdZ    ddeedeedeedeeddf dd Z e deefd d Z e deefd d Z e deefddZ e deefddZdS)raOptions for :meth:`ClientSession.start_transaction`. :Parameters: - `read_concern` (optional): The :class:`~pymongo.read_concern.ReadConcern` to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of the :class:`MongoClient` is used. - `write_concern` (optional): The :class:`~pymongo.write_concern.WriteConcern` to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of the :class:`MongoClient` is used. - `read_preference` (optional): The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`MongoClient` is used. See :mod:`~pymongo.read_preferences` for options. Transactions which read must use :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. - `max_commit_time_ms` (optional): The maximum amount of time to allow a single commitTransaction command to run. This option is an alias for maxTimeMS option on the commitTransaction command. If ``None`` (the default) maxTimeMS is not used. .. versionchanged:: 3.9 Added the ``max_commit_time_ms`` option. .. versionadded:: 3.7 N read_concern write_concernread_preferencemax_commit_time_msr!cCs||_||_||_||_|durt|tstd|f|dur6t|ts,td|f|js6t d|f|durFt|t sFtd|f|durSt|t sUtddSdS)NzMread_concern must be an instance of pymongo.read_concern.ReadConcern, not: %rzPwrite_concern must be an instance of pymongo.write_concern.WriteConcern, not: %rzThis transaction's :class:`~pymongo.read_concern.ReadConcern`.)r9r,r(r(r)r5,r-zTransactionOptions.read_concerncCr+)z@This transaction's :class:`~pymongo.write_concern.WriteConcern`.)r:r,r(r(r)r61r-z TransactionOptions.write_concerncCr+)zEThis transaction's :class:`~pymongo.read_preferences.ReadPreference`.)r;r,r(r(r)r76r-z"TransactionOptions.read_preferencecCr+)zfThe maxTimeMS to use when running a commitTransaction command. .. versionadded:: 3.9 )r<r,r(r(r)r8;r.z%TransactionOptions.max_commit_time_msNNNN)r/r0r1r2rrrrr>r*r4r5r6r7r8r(r(r(r)rs2 'rcCs.|r|dur|js|jrdStd|f|S)zValidate that an explicit session is not used with an unack'ed write. Returns the session to use for the next operation. NzHExplicit sessions are incompatible with unacknowledged write concern: %r)r= _implicitr)sessionr6r(r(r)_validate_session_write_concernDsrBc@(eZdZdZddZddZddZdS) _TransactionContextz;Internal transaction context manager for start_transaction.cCs ||_dSN)_TransactionContext__session)r'rAr(r(r)r*] z_TransactionContext.__init__cC|SrEr(r,r(r(r) __enter__`z_TransactionContext.__enter__cCs0|jjr|dur|jdS|jdSdSrE)rFin_transactioncommit_transactionabort_transactionr'exc_typeexc_valexc_tbr(r(r)__exit__cs z_TransactionContext.__exit__N)r/r0r1r2r*rIrRr(r(r(r)rDZs  rDc@s$eZdZdZdZdZdZdZdZdS) _TxnStateN) r/r0r1NONESTARTING IN_PROGRESS COMMITTEDCOMMITTED_EMPTYABORTEDr(r(r(r)rSksrSc@sTeZdZdZddZddZddZedd Zd d Z d d Z ddZ ddZ dS) _TransactionzBInternal class to hold transaction information in a ClientSession.cCs6||_tj|_d|_d|_d|_d|_d|_||_ dSNFr) optsrSrZstateshardedpinned_addresssock_mgrrecovery_tokenattemptclient)r'rbrir(r(r)r*ws z_Transaction.__init__cCs|jtjtjfvSrE)rcrSr[r\r,r(r(r)activez_Transaction.activecCs |jtjkSrE)rcrSr[r,r(r(r)starting z_Transaction.startingcCs|r |jr |jjSdSrE)rjrfsockr,r(r(r) pinned_connsz_Transaction.pinned_conncCs:d|_|jj|_|jjtjkr|t|d|_ dSdS)NTF) rd descriptionaddressreZ server_typerZ LoadBalancerZpin_txnrrfr'server sock_infor(r(r)pins  z_Transaction.pincCs d|_|jr |jd|_dSrE)rerfcloser,r(r(r)unpins  z_Transaction.unpincCs&|tj|_d|_d|_d|_dSra)rwrSrZrcrdrgrhr,r(r(r)resets  z_Transaction.resetcCs&|jr|jdd|jd|_dSdSNr)rfriZ_close_cursor_soonr,r(r(r)__del__s z_Transaction.__del__N) r/r0r1r2r*rjrlr4rorurwrxrzr(r(r(r)r`ts   r`excr!cCs |d)zDRe-raise an exception with the UnknownTransactionCommitResult label.UnknownTransactionCommitResult)Z_add_error_labelr{r(r(r)_reraise_with_unknown_commits r~cCst|to |jdkS)z/Return true if exc is a MaxTimeMSExpired error.2)r#rcoder}r(r(r)_max_time_expired_errorsr@rxcCst|tkS)z/Are we within the with_transaction retry limit?)time monotonic"_WITH_TRANSACTION_RETRY_TIME_LIMIT) start_timer(r(r)_within_time_limitsr_T) MongoClientc @sVeZdZdZdddedededdf d d Zd[d d Zd dZ ddZ d\ddZ dedededdfddZ e d]ddZe defddZe deeeffddZe deeeeffddZe deefd d!Zd"d#Z    d^d$edgefd%eed&eed'eed(eedef d)d*Z    d^d%eed&eed'eed(eedef d+d,Z d[d-d.Z!d[d/d0Z"d1d2Z#d3d4Z$d5d6Z%d7eeefddfd8d9Z&d:d;Z'dZ(d?d@Z)e defdAdBZ*e defdCdDZ+e dEdFZ,e dGdHZ-e dIdJZ.dKdLZ/dMdNZ0dOdPZ1dQdRZ2dSdTZ3dUdVZ4dWdXZ5de6fdYdZZ7dS)_ ClientSessionaA session for ordering sequential operations. :class:`ClientSession` instances are **not thread-safe or fork-safe**. They can only be used by one thread or process at a time. A single :class:`ClientSession` cannot be used to run multiple operations concurrently. Should not be initialized directly by application developers - to create a :class:`ClientSession`, call :meth:`~pymongo.mongo_client.MongoClient.start_session`. rirserver_sessionoptionsimplicitr!NcCs:||_||_||_d|_d|_d|_||_td||_dSrE) _client_server_session_options _cluster_time_operation_time_snapshot_timer@r` _transaction)r'rirrrr(r(r)r*szClientSession.__init__cCs|jdddS)zFinish this session. If a transaction has started, abort it. It is an error to use the session after the session has ended. TlockN _end_sessionr,r(r(r) end_sessionszClientSession.end_sessionc CsZ|jdur+z|jr ||W|j|j|d|_dS|j|j|d|_wdSrE)rrKrM_unpinrZ_return_server_session)r'rr(r(r)rs   zClientSession._end_sessioncCs|jdur tddS)NzCannot use ended session)rrr,r(r(r) _check_endeds zClientSession._check_endedcCrHrEr(r,r(r(r)rIrJzClientSession.__enter__rOrPrQcCs|jdddS)NTrrrNr(r(r)rRszClientSession.__exit__cCr+)z^The :class:`~pymongo.mongo_client.MongoClient` this session was created from. )rr,r(r(r)ri zClientSession.clientcCr+)z:The :class:`SessionOptions` this session was created with.)rr,r(r(r)rr-zClientSession.optionscCs||jjS)z6A BSON document, the opaque server session identifier.)rr session_idr,r(r(r)rszClientSession.session_idcCr+)zZThe cluster time returned by the last operation executed in this session. rr,r(r(r) cluster_timerzClientSession.cluster_timecCr+)z\The operation time returned by the last operation executed in this session. rr,r(r(r)operation_time$rzClientSession.operation_timecCs2|r|S|jj}|ot||}|r|St|j|S)z-Return the inherited TransactionOption value.)rrgetattrri)r'namevalZtxn_optsr(r(r)_inherit_option+s zClientSession._inherit_optioncallbackr5r6r7r8c Cst} |||||z||}Wn(ty;}z|jr"|t|tr6|dr6t |r6WYd}~qd}~ww|jsA|S z| W|Styx}z#|drdt |rdt |sdWYd}~qA|drst |rsWYd}~nd}~wwq)a0Execute a callback in a transaction. This method starts a transaction on this session, executes ``callback`` once, and then commits the transaction. For example:: def callback(session): orders = session.client.db.orders inventory = session.client.db.inventory orders.insert_one({"sku": "abc123", "qty": 100}, session=session) inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}}, {"$inc": {"qty": -100}}, session=session) with client.start_session() as session: session.with_transaction(callback) To pass arbitrary arguments to the ``callback``, wrap your callable with a ``lambda`` like this:: def callback(session, custom_arg, custom_kwarg=None): # Transaction operations... with client.start_session() as session: session.with_transaction( lambda s: callback(s, "custom_arg", custom_kwarg=1)) In the event of an exception, ``with_transaction`` may retry the commit or the entire transaction, therefore ``callback`` may be invoked multiple times by a single call to ``with_transaction``. Developers should be mindful of this possiblity when writing a ``callback`` that modifies application state or has any other side-effects. Note that even when the ``callback`` is invoked multiple times, ``with_transaction`` ensures that the transaction will be committed at-most-once on the server. The ``callback`` should not attempt to start new transactions, but should simply run operations meant to be contained within a transaction. The ``callback`` should also not commit the transaction; this is handled automatically by ``with_transaction``. If the ``callback`` does commit or abort the transaction without error, however, ``with_transaction`` will return without taking further action. :class:`ClientSession` instances are **not thread-safe or fork-safe**. Consequently, the ``callback`` must not attempt to execute multiple operations concurrently. When ``callback`` raises an exception, ``with_transaction`` automatically aborts the current transaction. When ``callback`` or :meth:`~ClientSession.commit_transaction` raises an exception that includes the ``"TransientTransactionError"`` error label, ``with_transaction`` starts a new transaction and re-executes the ``callback``. When :meth:`~ClientSession.commit_transaction` raises an exception with the ``"UnknownTransactionCommitResult"`` error label, ``with_transaction`` retries the commit until the result of the transaction is known. This method will cease retrying after 120 seconds has elapsed. This timeout is not configurable and any exception raised by the ``callback`` or by :meth:`ClientSession.commit_transaction` after the timeout is reached will be re-raised. Applications that desire a different timeout duration should not use this method. :Parameters: - `callback`: The callable ``callback`` to run inside a transaction. The callable must accept a single argument, this session. Note, under certain error conditions the callback may be run multiple times. - `read_concern` (optional): The :class:`~pymongo.read_concern.ReadConcern` to use for this transaction. - `write_concern` (optional): The :class:`~pymongo.write_concern.WriteConcern` to use for this transaction. - `read_preference` (optional): The read preference to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of this :class:`Database` is used. See :mod:`~pymongo.read_preferences` for options. :Returns: The return value of the ``callback``. .. versionadded:: 3.9 TTransientTransactionErrorNr|) rrstart_transaction ExceptionrKrMr#rZhas_error_labelrrLr) r'rr5r6r7r8rretr{r(r(r)with_transaction5sP]       zClientSession.with_transactioncCs||jjr td|jrtd|d|}|d|}|d|}|dur2|jj}|r2|j}t|||||j _ |j t j |j _|t|S)zStart a multi-statement transaction. Takes the same arguments as :class:`TransactionOptions`. .. versionchanged:: 3.9 Added the ``max_commit_time_ms`` option. .. versionadded:: 3.7 z3Transactions are not supported in snapshot sessionszTransaction already in progressr5r6r7N)rrr rrKrrr8rrrbrxrSr[rc_start_retryable_writerD)r'r5r6r7r8rbr(r(r)rs&     zClientSession.start_transactionc CsZ||jj}|tjurtd|tjtjfvr tj|j_dS|tjur)td|tj ur3tj |j_zsz| dWnKt yV}z| dt|WYd}~n=d}~wtyk}z t|WYd}~n0d}~wty}z|jtvrxt|WYd}~nd}~wwWtj |j_dSWtj |j_dSWtj |j_dSWtj |j_dStj |j_w)zMCommit a multi-statement transaction. .. versionadded:: 3.7 No transaction startedNz.funcTN)rZ_retry_internal)r'rrr(rr)r,sz,ClientSession._finish_transaction_with_retrycCs|jjd7_|jj}|j}t|dfg}|dkrB|jr(tdur(|j|d<|jjdkrB|j}d|d<| ddt d i|}|jj rL|jj |d<|j j j||||d d S) NrTrZ maxTimeMSZmajoritywZwtimeouti' recoveryTokenT)rAr6Zparse_write_concern_errorr()rrhrbr6r r8rZ get_timeoutdocument setdefaultrrgrZadminZ_command)r'rtrrbwccmdZwc_docr(r(r)r8s"     z!ClientSession._finish_transactioncCs@|jdur ||_dS|dur|d|jdkr||_dSdSdS)zInternal cluster time helper.N clusterTimerr'rr(r(r)_advance_cluster_timeQs   z#ClientSession._advance_cluster_timercCs8t|ts tdt|dtstd||dS)zUpdate the cluster time for this session. :Parameters: - `cluster_time`: The :data:`~pymongo.client_session.ClientSession.cluster_time` from another `ClientSession` instance. z6cluster_time must be a subclass of collections.MappingrzInvalid cluster_timeN)r#_Mappingr$getr ValueErrorrrr(r(r)advance_cluster_timeYs z"ClientSession.advance_cluster_timecCs8|jdur ||_dS|dur||jkr||_dSdSdS)zInternal operation time helper.Nrr'rr(r(r)_advance_operation_timegs    z%ClientSession._advance_operation_timercCs t|ts td||dS)zUpdate the operation time for this session. :Parameters: - `operation_time`: The :data:`~pymongo.client_session.ClientSession.operation_time` from another `ClientSession` instance. z>operation_time must be an instance of bson.timestamp.TimestampN)r#r r$rrr(r(r)advance_operation_timeos z$ClientSession.advance_operation_timecCs||d||d|jjr-|jdur-d|vr%|dd}n|d}||_|jrA|jjrC|d}|rE||j_ dSdSdSdS)z?Process a response to a command that was run with this session.z $clusterTimeZ operationTimeNcursor atClusterTimer) rrrrr rrKrrdrg)r'Zreplyctrgr(r(r)_process_response{s   zClientSession._process_responsecCs |jduS)z!True if this session is finished.N)rr,r(r(r) has_ended zClientSession.has_endedcC |jS)zhTrue if this session has an active multi-statement transaction. .. versionadded:: 3.10 )rrjr,r(r(r)rK zClientSession.in_transactioncCr)z?True if this session is starting a multi-statement transaction.)rrlr,r(r(r)_starting_transactionrz#ClientSession._starting_transactioncCs|jr |jjSdS)z3The mongos address this transaction was created on.N)rrjrer,r(r(r)_pinned_addresss zClientSession._pinned_addresscCs|jjS)z/The connection this transaction was started on.)rror,r(r(r)_pinned_connectionsz ClientSession._pinned_connectioncCs|j||dS)z@Pin this session to the given Server or to the given connection.N)rrurrr(r(r)_pinszClientSession._pincCs|jdS)z*Unpin this session from any pinned Server.N)rrwr,r(r(r)rszClientSession._unpincCs|jr|jjjSdS)z3Return read preference of this transaction or None.N)rKrrbr7r,r(r(r)_txn_read_preferences z"ClientSession._txn_read_preferencecCs<t|jtr|j}|jj|_|jr|jdSdSdSrE)r#r_EmptyServerSessionrZ _topologyget_server_sessionstarted_retryable_writeinc_transaction_id)r'oldr(r(r) _materializes zClientSession._materializecCs|||jjr|||t|j_|jj |d<|r(|jj |d<dS|j rj|t j kr7td|f|jjtjkr^tj|j_d|d<|jjjrX|jjjj}|rX||d<||||jj |d<d|d<dSdS) NZlsidZ txnNumberz9read preference in a transaction must be primary, not: %rTZstartTransaction readConcernFZ autocommit)rrrr _update_read_concernrrrlast_usertransaction_idrKrZPRIMARYrrrcrSr[r\rbr5r)r'commandZ is_retryabler7rtrcr(r(r) _apply_tos6           zClientSession._apply_tocCs||jdSrE)rrrr,r(r(r)rsz$ClientSession._start_retryable_writecCsr|jjr|jdur|j|did<|jjr5|jdkrtd|di}d|d<|jdur7|j|d<dSdSdS)NrZafterClusterTime z+Snapshot reads require MongoDB 5.0 or laterr levelr)rrrrr Zmax_wire_versionrr)r'rrtrr(r(r)rs   z"ClientSession._update_read_concerncCstd)Nz>A ClientSession cannot be copied, create a new session instead)r$r,r(r(r)__copy__szClientSession.__copy__)r!N)r!r)r!rr?)8r/r0r1r2rrr3r*rrrrIrRr4rirrstrrrrr rrrrrrrr>rrrrLrMrrrrrrrrrKrrrrrrrrrrrrr(r(r(r)rs         ( +     " rc@rC) rdirtyrcCsd|_d|_dS)NFrr,r(r(r)r*s z_EmptyServerSession.__init__cC d|_dSNTrr,r(r(r) mark_dirtyrGz_EmptyServerSession.mark_dirtycCrr)rr,r(r(r)rrGz&_EmptyServerSession.inc_transaction_idN)r/r0r1 __slots__r*rrr(r(r(r)rs  rc@s8eZdZddZddZddZeddZd d Zd S) _ServerSessioncCs6dttjdi|_t|_d|_d|_ ||_ dS)NidrWrF) r uuiduuid4bytesrrrr_transaction_idr generation)r'rr(r(r)r*s   z_ServerSession.__init__cCs d|_dS)zMark this session as dirty. A server session is marked dirty when a command fails with a network error. Dirty sessions are later discarded from the server session pool. TNrr,r(r(r)r rz_ServerSession.mark_dirtycCst|j}||ddkS)NrT<)rrr)r'session_timeout_minutesZ idle_secondsr(r(r) timed_outsz_ServerSession.timed_outcCs t|jS)zPositive 64-bit integer.)r rr,r(r(r)rrz_ServerSession.transaction_idcCs|jd7_dSNrT)rr,r(r(r)rrkz!_ServerSession.inc_transaction_idN) r/r0r1r*rrr4rrr(r(r(r)rs  rcsPeZdZdZfddZddZddZdd Zd d Zd d Z ddZ Z S)_ServerSessionPoolzsPool of _ServerSession objects. This class is not thread-safe, access it while holding the Topology lock. cs tt|j|i|d|_dSry)superrr*r)r'argskwargs __class__r(r)r*&s z_ServerSessionPool.__init__cCs|jd7_|dSr)rclearr,r(r(r)rx*s z_ServerSessionPool.resetcCs g}|r||j|s|SrE)appendpopr)r'idsr(r(r)pop_all.s z_ServerSessionPool.pop_allcCs2|||r|}||s|S|st|jSrE) _clear_stalepopleftrrr)r'rsr(r(r)r4s   z%_ServerSessionPool.get_server_sessioncCs.|dur||||rdS||dSrE)rrreturn_server_session_no_lock)r'rrr(r(r)return_server_sessionDs   z(_ServerSessionPool.return_server_sessioncCs(|j|jkr|js||dSdSdSrE)rr appendleft)r'rr(r(r)rKsz0_ServerSessionPool.return_server_session_no_lockcCs,|r|d|r|ndS|sdSdS)N)rr)r'rr(r(r)rQs   z_ServerSessionPool._clear_stale) r/r0r1r2r*rxrrrrr __classcell__r(r(rr)r s r)Br2 collectionsrrcollections.abcrrtypingrrrrrrr Z bson.binaryr Z bson.int64r Zbson.sonr Zbson.timestampr ZpymongorZpymongo.cursorrZpymongo.errorsrrrrrrZpymongo.helpersrZpymongo.read_concernrZpymongo.read_preferencesrrZpymongo.server_typerZpymongo.write_concernrobjectrrrBrDrSr`r~r frozensetrrrrZpymongo.mongo_clientrrrrdequerr(r(r(r)sXw (          ?[ 5  '