diff --git a/google/cloud/bigtable/admin_v2/overlay/__init__.py b/google/cloud/bigtable/admin_v2/overlay/__init__.py new file mode 100644 index 000000000..3b85e4989 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/__init__.py @@ -0,0 +1,45 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This directory and all its subdirectories are the only handwritten +# components of the otherwise autogenerated google/cloud/bigtable/admin_v2. +# The purpose of the overlay directory is to add additional functionality to +# the autogenerated library while preserving its developer experience. These +# handwritten additions currently consist of the following: +# +# 1. TODO: Document final GcRule design choice here +# 2. An LRO class for restore_table that exposes an Operation for +# OptimizeRestoreTable, if that LRO exists. +# 3. New methods (wait_for_consistency and wait_for_replication) that return +# a polling future class for automatically polling check_consistency. +# +# This directory is structured to mirror that of a typical autogenerated library (e.g. +# services/types subdirectories), and the aforementioned handwritten additions are +# currently implemented as either types under overlay/types or in methods in an overwritten +# client class under overlay/services. + +from .types import ( + RestoreTableOperation, + CheckConsistencyPollingFuture, +) + +from .services.bigtable_table_admin import ( + BigtableTableAdminClient, +) + +__all__ = ( + "RestoreTableOperation", + "CheckConsistencyPollingFuture", + "BigtableTableAdminClient", +) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/__init__.py b/google/cloud/bigtable/admin_v2/overlay/services/__init__.py new file mode 100644 index 000000000..ab7686e26 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py new file mode 100644 index 000000000..ec9de1382 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO: Add the async client after owlbot changes. + +from .client import BigtableTableAdminClient + +__all__ = ("BigtableTableAdminClient",) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py new file mode 100644 index 000000000..e7ee4db3a --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py @@ -0,0 +1,339 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import functools + +from typing import Optional, Sequence, Tuple, Union +from google.api_core import gapic_v1 +from google.api_core import retry as retries + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.api_core import operation # type: ignore +from google.cloud.bigtable.admin_v2.types import bigtable_table_admin + +from google.cloud.bigtable.admin_v2.services.bigtable_table_admin import ( + BaseBigtableTableAdminClient, +) +from google.cloud.bigtable.admin_v2.overlay.types import consistency, restore_table + + +class BigtableTableAdminClient(BaseBigtableTableAdminClient): + def restore_table( + self, + request: Optional[Union[bigtable_table_admin.RestoreTableRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> restore_table.RestoreTableOperation: + r"""Create a new table by restoring from a completed backup. The + returned table :ref:`long-running operation + <:class:google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation>` + can be used to track the progress of the operation, and to cancel it. The + :ref:`metadata <:attr:google.api_core.operation.Operation.metadata>` field type is + :ref:`RestoreTableMetadata <:class:google.bigtable.admin_v2.types.RestoreTableMetadata>`. + The :ref:`response <:meth:google.api_core.operation.Operation.result>` type is + :class:`google.cloud.bigtable.admin_v2.types.Table`, if successful. + + Additionally, the returned :ref:`long-running-operation <:class:google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation>` + provides a method, :meth:`google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation.optimize_restore_table_operation` that + provides access to a :class:`google.api_core.operation.Operation` object representing the OptimizeRestoreTable long-running-operation + after the current one has completed. + + .. code-block:: python + + # This snippet should be regarded as a code template only. + # + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_restore_table(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.RestoreTableRequest( + backup="backup_value", + parent="parent_value", + table_id="table_id_value", + ) + + # Make the request + operation = client.restore_table(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + # Handle LRO2 + optimize_operation = operation.optimize_restore_table_operation() + + if optimize_operation: + print("Waiting for table optimization to complete...") + + response = optimize_operation.result() + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.RestoreTableRequest, dict]): + The request object. The request for + [RestoreTable][google.bigtable.admin.v2.BigtableTableAdmin.RestoreTable]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.bigtable.admin_v2.types.Table` A collection of user data indexed by row, column, and timestamp. + Each table is served using the resources of its + parent cluster. + """ + operation = self._restore_table( + request=request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + restore_table_operation = restore_table.RestoreTableOperation( + self._transport.operations_client, operation + ) + return restore_table_operation + + def wait_for_consistency( + self, + request: Optional[ + Union[bigtable_table_admin.CheckConsistencyRequest, dict] + ] = None, + *, + name: Optional[str] = None, + consistency_token: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> consistency.CheckConsistencyPollingFuture: + r"""Creates a polling future that periodically checks replication + consistency based on a consistency token, that is, if replication + has caught up based on the conditions specified in the token and + the check request. The future will stop checking once the underlying + :meth:`check_consistency` request involving that token returns True. + + .. code-block:: python + + # This snippet should be regarded as a code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_wait_for_consistency(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.CheckConsistencyRequest( + name="name_value", + consistency_token="consistency_token_value", + ) + + # Make the request + future = client.wait_for_consistency(request=request) + + # Wait for the table to become consistent + print("Waiting for operation to complete...") + + response = future.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.CheckConsistencyRequest, dict]): + The request object. Request message for + [google.bigtable.admin.v2.BigtableTableAdmin.CheckConsistency][google.bigtable.admin.v2.BigtableTableAdmin.CheckConsistency] + name (str): + Required. The unique name of the Table for which to + check replication consistency. Values are of the form + ``projects/{project}/instances/{instance}/tables/{table}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + consistency_token (str): + Required. The token created using + GenerateConsistencyToken for the Table. + + This corresponds to the ``consistency_token`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.CheckConsistencyPollingFuture: + An object representing a polling future. + + The result type for the operation will be `bool`, and will return True when the + consistency check involving the given consistency token returns True. + """ + api_call = functools.partial( + self.check_consistency, + request, + name=name, + consistency_token=consistency_token, + timeout=timeout, + metadata=metadata, + ) + return consistency.CheckConsistencyPollingFuture(api_call, default_retry=retry) + + def wait_for_replication( + self, + request: Optional[ + Union[bigtable_table_admin.GenerateConsistencyTokenRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> consistency.CheckConsistencyPollingFuture: + r"""Generates a consistency token for a Table, which will then + be used to create a polling future for checking the replication + consistency based on that token. The future will stop checking + once the underlying :meth:`check_consistency` request involving + that token returns True. + + .. code-block:: python + + # This snippet should be regarded as a code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_wait_for_replication(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.GenerateConsistencyTokenRequest( + name="name_value", + ) + + # Make the request + future = client.wait_for_replication(request=request) + + # Wait for the table to become consistent + print("Waiting for operation to complete...") + + response = future.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.GenerateConsistencyTokenRequest, dict]): + The request object. Request message for + [google.bigtable.admin.v2.BigtableTableAdmin.GenerateConsistencyToken][google.bigtable.admin.v2.BigtableTableAdmin.GenerateConsistencyToken] + name (str): + Required. The unique name of the Table for which to + create a consistency token. Values are of the form + ``projects/{project}/instances/{instance}/tables/{table}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.CheckConsistencyPollingFuture: + An object representing a polling future. + + The result type for the operation will be `bool`, and will return True when the + consistency check involving the given consistency token returns True. + """ + generate_consistency_response = self.generate_consistency_token( + request, + name=name, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Create the CheckConsistencyRequest object. + check_consistency_request = bigtable_table_admin.CheckConsistencyRequest() + + # If the generate_consistency_token request is valid, there's a name in the request object + # or the name parameter. + if isinstance(request, dict): + check_consistency_request.name = request["name"] + elif isinstance(request, bigtable_table_admin.GenerateConsistencyTokenRequest): + check_consistency_request.name = request.name + else: + check_consistency_request.name = name + + check_consistency_request.consistency_token = ( + generate_consistency_response.consistency_token + ) + + return self.await_consistency( + check_consistency_request, retry=retry, timeout=timeout, metadata=metadata + ) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py new file mode 100644 index 000000000..01b1f7115 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py @@ -0,0 +1,26 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .consistency import ( + CheckConsistencyPollingFuture, +) + +from .restore_table import ( + RestoreTableOperation, +) + +__all__ = ( + "CheckConsistencyPollingFuture", + "RestoreTableOperation", +) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py new file mode 100644 index 000000000..f5775b697 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py @@ -0,0 +1,97 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Union, Callable + +from google.api_core.future import polling +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.bigtable.admin_v2.types import bigtable_table_admin + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +class CheckConsistencyPollingFuture(polling.PollingFuture): + """A Future that polls an underlying `check_consistency` operation until it returns True. + + **This class should not be instantiated by users** and should only be instantiated by the admin + client's `google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.wait_for_consistency` or + :meth:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.wait_for_replication` methods. + + Args: + check_consistency_call(Callable[ + [Optional[google.api_core.retry.Retry], + google.cloud.bigtable.admin_v2.types.CheckConsistencyResponse]): + A :meth:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.check_consistency` call + from :class:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient`. The call should fix + every user parameter except for retry, which will be done via :meth:`functools.partial`. + default_retry(Optional[google.api_core.retry.Retry]): The `retry` parameter passed in to either `wait_for_consistency` + or `wait_for_replication`. + polling (google.api_core.retry.Retry): The configuration used for polling. + This parameter controls how often :meth:`done` is polled. If the + ``timeout`` argument is specified in :meth:`result` method it will + override the ``polling.timeout`` property. + """ + def __init__( + self, + check_consistency_call: Callable[[OptionalRetry], bigtable_table_admin.CheckConsistencyResponse], + default_retry: OptionalRetry = gapic_v1.method.DEFAULT, + polling: retries.Retry = polling.DEFAULT_POLLING, + **kwargs + ): + super(CheckConsistencyPollingFuture, self).__init__(polling=polling, **kwargs) + + # Done is called with two different scenarios, retry is specified or not specified. + # API_call will be a functools partial with everything except retry specified because of + # that. + self._check_consistency_call = check_consistency_call + self._default_retry = default_retry + + def done(self, retry: OptionalRetry = None): + """Checks to see if the operation is complete. + + This will be return True when the underlying check_consistency call returns + True while polling. + + Args: + retry (google.api_core.retry.Retry): (Optional) How to retry the + polling RPC (to not be confused with polling configuration. See + the documentation for :meth:`result` for details). + + Returns: + bool: True if the operation is complete, False otherwise. + """ + + if self._result_set: + return True + + retry = retry or self._default_retry + + try: + check_consistency_response = self._check_consistency_call(retry=retry) + if check_consistency_response.consistent: + self.set_result(True) + + return check_consistency_response.consistent + except Exception as e: + self.set_exception(e) + + def cancel(self): + raise NotImplementedError("Cannot cancel consistency token operation") + + def cancelled(self): + raise NotImplementedError("Cannot cancel consistency token operation") diff --git a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py new file mode 100644 index 000000000..495fbdf3a --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py @@ -0,0 +1,101 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Optional + +from google.api_core import operation +from google.protobuf import empty_pb2 + +from google.cloud.bigtable.admin_v2.types import OptimizeRestoredTableMetadata + + +class RestoreTableOperation(operation.Operation): + """A Future for interacting with Bigtable Admin's RestoreTable Long-Running Operation. + + This is needed to expose a potential long-running operation that might run after this operation + finishes, OptimizeRestoreTable. This is exposed via the the :meth:`optimize_restore_table` method. + + **This class should not be instantiated by users** and should only be instantiated by the admin + client's `google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.restore_table` + method. + + Args: + operations_client (google.api_core.operations_v1.AbstractOperationsClient): The operations + client from the :class:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient`'s + transport. + restore_table_operation (google.api_core.operation.Operation): A :class:`google.api_core.operation.Operation` + instance resembling a RestoreTable long-running operation + """ + + def __init__(self, operations_client, restore_table_operation: operation.Operation): + self._operations_client = operations_client + self._optimize_restore_table_operation = None + super().__init__( + restore_table_operation._operation, + restore_table_operation._refresh, + restore_table_operation._cancel, + restore_table_operation._result_type, + restore_table_operation._metadata_type, + polling=restore_table_operation._polling, + ) + + def optimize_restore_table_operation( + self, timeout=operation.Operation._DEFAULT_VALUE, retry=None, polling=None + ) -> Optional[operation.Operation]: + """Gets the OptimizeRestoreTable long-running operation that runs after this operation finishes. + + This is a blocking call that will return the operation after this current long-running operation + finishes, just like :meth:`result`. The follow-up operation has + :ref:`metadata <:attr:google.api_core.operation.Operation.metadata>` type + :ref:`OptimizeRestoreTableMetadata <:class:google.bigtable.admin_v2.types.OptimizeRestoreTableMetadata>` + and no return value, but can be waited for with `result`. + + The current operation might not trigger a follow-up OptimizeRestoreTable operation, in which case, this + method will return `None`. + + For more documentation on the parameters for this method, see the documentation on :meth:`result`. + + Returns: + Optional[google.api_core.operation.Operation]: + An object representing a long-running operation, or None if there is no OptimizeRestoreTable operation + after this one. + """ + self._blocking_poll(timeout=timeout, retry=retry, polling=polling) + + if self._exception is not None: + # pylint: disable=raising-bad-type + # Pylint doesn't recognize that this is valid in this case. + raise self._exception + + return self._optimize_restore_table_operation + + def set_result(self, response): + optimize_restore_table_operation_name = ( + self.metadata.optimize_table_operation_name + ) + + # When the RestoreTable operation finishes, it might not necessarily trigger + # an optimize operation. + if optimize_restore_table_operation_name: + optimize_restore_table_operation = self._operations_client.get_operation( + name=optimize_restore_table_operation_name + ) + self._optimize_restore_table_operation = operation.from_gapic( + optimize_restore_table_operation, + self._operations_client, + empty_pb2.Empty, + metadata_type=OptimizeRestoredTableMetadata, + ) + + super().set_result(response)