Example #1
0
    def test_commit(self, mock_create_stub):
        # Mock gRPC layer
        grpc_stub = mock.Mock()
        mock_create_stub.return_value = grpc_stub

        client = spanner_v1.SpannerClient()

        # Mock request
        session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]',
                                      '[SESSION]')
        mutations = []

        # Mock response
        expected_response = {}
        expected_response = spanner_pb2.CommitResponse(**expected_response)
        grpc_stub.Commit.return_value = expected_response

        response = client.commit(session, mutations)
        self.assertEqual(expected_response, response)

        grpc_stub.Commit.assert_called_once()
        args, kwargs = grpc_stub.Commit.call_args
        self.assertEqual(len(args), 2)
        self.assertEqual(len(kwargs), 1)
        self.assertIn('metadata', kwargs)
        actual_request = args[0]

        expected_request = spanner_pb2.CommitRequest(session=session,
                                                     mutations=mutations)
        self.assertEqual(expected_request, actual_request)
Example #2
0
    def test_commit(self):
        # Setup Expected Response
        expected_response = {}
        expected_response = spanner_pb2.CommitResponse(**expected_response)

        # Mock the API response
        channel = ChannelStub(responses=[expected_response])
        patch = mock.patch("google.api_core.grpc_helpers.create_channel")
        with patch as create_channel:
            create_channel.return_value = channel
            client = spanner_v1.SpannerClient()

        # Setup Request
        session = client.session_path("[PROJECT]", "[INSTANCE]", "[DATABASE]",
                                      "[SESSION]")
        mutations = []

        response = client.commit(session, mutations)
        assert expected_response == response

        assert len(channel.requests) == 1
        expected_request = spanner_pb2.CommitRequest(session=session,
                                                     mutations=mutations)
        actual_request = channel.requests[0][1]
        assert expected_request == actual_request
def _transaction(stub):
    """Probe to test BeginTransaction, Commit and Rollback grpc from Spanner stub.

  Args:
    stub: An object of SpannerStub.
  """
    _transaction_tracer = initialize_tracer()
    with _transaction_tracer.span(name='_transaction') as root_span:
        root_span.add_annotation('endpoint info available',
                                 endpoint=_SPANNER_TARGET)
        session = None
        try:
            with _transaction_tracer.span(name='stub.CreateSession'):
                session = stub.CreateSession(
                    spanner_pb2.CreateSessionRequest(database=_DATABASE))

            txn_options = transaction_pb2.TransactionOptions(
                read_write=transaction_pb2.TransactionOptions.ReadWrite())
            txn_request = spanner_pb2.BeginTransactionRequest(
                session=session.name,
                options=txn_options,
            )

            # Probing BeginTransaction call
            with _transaction_tracer.span(name='stub.BeginTransaction'):
                txn = stub.BeginTransaction(txn_request)

            # Probing Commit call
            commit_request = spanner_pb2.CommitRequest(session=session.name,
                                                       transaction_id=txn.id)
            with _transaction_tracer.span(name='stub.Commit'):
                stub.Commit(commit_request)

            # Probing Rollback call
            txn = stub.BeginTransaction(txn_request)
            rollback_request = spanner_pb2.RollbackRequest(
                session=session.name, transaction_id=txn.id)
            with _transaction_tracer.span(name='stub.Rollback'):
                stub.Rollback(rollback_request)

        finally:
            if session is not None:
                with _transaction_tracer.span(name='stub.DeleteSession'):
                    stub.DeleteSession(
                        spanner_pb2.DeleteSessionRequest(name=session.name))
Example #4
0
    def test_commit(self):
        # Setup Expected Response
        expected_response = {}
        expected_response = spanner_pb2.CommitResponse(**expected_response)

        # Mock the API response
        channel = ChannelStub(responses=[expected_response])
        client = spanner_v1.SpannerClient(channel=channel)

        # Setup Request
        session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]',
                                      '[SESSION]')
        mutations = []

        response = client.commit(session, mutations)
        assert expected_response == response

        assert len(channel.requests) == 1
        expected_request = spanner_pb2.CommitRequest(session=session,
                                                     mutations=mutations)
        actual_request = channel.requests[0][1]
        assert expected_request == actual_request
Example #5
0
    def commit(self,
               session,
               mutations,
               transaction_id=None,
               single_use_transaction=None,
               options=None):
        """
        Commits a transaction. The request includes the mutations to be
        applied to rows in the database.

        ``Commit`` might return an ``ABORTED`` error. This can occur at any time;
        commonly, the cause is conflicts with concurrent
        transactions. However, it can also happen for a variety of other
        reasons. If ``Commit`` returns ``ABORTED``, the caller should re-attempt
        the transaction from the beginning, re-using the same session.

        Example:
            >>> from google.cloud import spanner_v1
            >>>
            >>> client = spanner_v1.SpannerClient()
            >>>
            >>> session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]', '[SESSION]')
            >>> mutations = []
            >>>
            >>> response = client.commit(session, mutations)

        Args:
            session (str): Required. The session in which the transaction to be committed is running.
            mutations (list[Union[dict, ~google.cloud.spanner_v1.types.Mutation]]): The mutations to be executed when this transaction commits. All
                mutations are applied atomically, in the order they appear in
                this list.
                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.Mutation`
            transaction_id (bytes): Commit a previously-started transaction.
            single_use_transaction (Union[dict, ~google.cloud.spanner_v1.types.TransactionOptions]): Execute mutations in a temporary transaction. Note that unlike
                commit of a previously-started transaction, commit with a
                temporary transaction is non-idempotent. That is, if the
                ``CommitRequest`` is sent to Cloud Spanner more than once (for
                instance, due to retries in the application, or in the
                transport library), it is possible that the mutations are
                executed more than once. If this is undesirable, use
                ``BeginTransaction`` and
                ``Commit`` instead.
                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.TransactionOptions`
            options (~google.gax.CallOptions): Overrides the default
                settings for this call, e.g, timeout, retries etc.

        Returns:
            A :class:`~google.cloud.spanner_v1.types.CommitResponse` instance.

        Raises:
            :exc:`google.gax.errors.GaxError` if the RPC is aborted.
            :exc:`ValueError` if the parameters are invalid.
        """
        # Sanity check: We have some fields which are mutually exclusive;
        # raise ValueError if more than one is sent.
        oneof.check_oneof(
            transaction_id=transaction_id,
            single_use_transaction=single_use_transaction, )

        request = spanner_pb2.CommitRequest(
            session=session,
            mutations=mutations,
            transaction_id=transaction_id,
            single_use_transaction=single_use_transaction)
        return self._commit(request, options)
    def commit(self,
               session,
               mutations,
               transaction_id=None,
               single_use_transaction=None,
               retry=google.api_core.gapic_v1.method.DEFAULT,
               timeout=google.api_core.gapic_v1.method.DEFAULT,
               metadata=None):
        """
        Commits a transaction. The request includes the mutations to be
        applied to rows in the database.

        ``Commit`` might return an ``ABORTED`` error. This can occur at any time;
        commonly, the cause is conflicts with concurrent
        transactions. However, it can also happen for a variety of other
        reasons. If ``Commit`` returns ``ABORTED``, the caller should re-attempt
        the transaction from the beginning, re-using the same session.

        Example:
            >>> from google.cloud import spanner_v1
            >>>
            >>> client = spanner_v1.SpannerClient()
            >>>
            >>> session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]', '[SESSION]')
            >>> mutations = []
            >>>
            >>> response = client.commit(session, mutations)

        Args:
            session (str): Required. The session in which the transaction to be committed is running.
            mutations (list[Union[dict, ~google.cloud.spanner_v1.types.Mutation]]): The mutations to be executed when this transaction commits. All
                mutations are applied atomically, in the order they appear in
                this list.
                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.Mutation`
            transaction_id (bytes): Commit a previously-started transaction.
            single_use_transaction (Union[dict, ~google.cloud.spanner_v1.types.TransactionOptions]): Execute mutations in a temporary transaction. Note that unlike
                commit of a previously-started transaction, commit with a
                temporary transaction is non-idempotent. That is, if the
                ``CommitRequest`` is sent to Cloud Spanner more than once (for
                instance, due to retries in the application, or in the
                transport library), it is possible that the mutations are
                executed more than once. If this is undesirable, use
                ``BeginTransaction`` and
                ``Commit`` instead.
                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.TransactionOptions`
            retry (Optional[google.api_core.retry.Retry]):  A retry object used
                to retry requests. If ``None`` is specified, requests will not
                be retried.
            timeout (Optional[float]): The amount of time, in seconds, to wait
                for the request to complete. Note that if ``retry`` is
                specified, the timeout applies to each individual attempt.

        Returns:
            A :class:`~google.cloud.spanner_v1.types.CommitResponse` instance.

        Raises:
            google.api_core.exceptions.GoogleAPICallError: If the request
                    failed for any reason.
            google.api_core.exceptions.RetryError: If the request failed due
                    to a retryable error and retry attempts failed.
            ValueError: If the parameters are invalid.
        """
        # Sanity check: We have some fields which are mutually exclusive;
        # raise ValueError if more than one is sent.
        google.api_core.protobuf_helpers.check_oneof(
            transaction_id=transaction_id,
            single_use_transaction=single_use_transaction,
        )

        request = spanner_pb2.CommitRequest(
            session=session,
            mutations=mutations,
            transaction_id=transaction_id,
            single_use_transaction=single_use_transaction,
        )
        return self._commit(
            request, retry=retry, timeout=timeout, metadata=metadata)