Coverage for /builds/BuildGrid/buildgrid/buildgrid/server/operations/instance.py: 98.00%
50 statements
« prev ^ index » next coverage.py v7.4.1, created at 2025-02-11 15:07 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2025-02-11 15:07 +0000
1# Copyright (C) 2018 Bloomberg LP
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# <http://www.apache.org/licenses/LICENSE-2.0>
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
16"""
17OperationsInstance
18==================
19An instance of the LongRunningOperations Service.
20"""
22from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import RequestMetadata
23from buildgrid._protos.buildgrid.v2.identity_pb2 import ClientIdentity
24from buildgrid._protos.google.longrunning.operations_pb2 import DESCRIPTOR as OPS_DESCRIPTOR
25from buildgrid._protos.google.longrunning.operations_pb2 import ListOperationsResponse, Operation
26from buildgrid.server.exceptions import InvalidArgumentError, NotFoundError
27from buildgrid.server.logging import buildgrid_logger
28from buildgrid.server.operations.filtering import DEFAULT_OPERATION_FILTERS, FilterParser
29from buildgrid.server.scheduler import Scheduler
30from buildgrid.server.servicer import Instance
31from buildgrid.server.settings import DEFAULT_MAX_LIST_OPERATION_PAGE_SIZE
33LOGGER = buildgrid_logger(__name__)
36class OperationsInstance(Instance):
37 SERVICE_NAME = OPS_DESCRIPTOR.services_by_name["Operations"].full_name
39 def __init__(
40 self, scheduler: Scheduler, max_list_operations_page_size: int = DEFAULT_MAX_LIST_OPERATION_PAGE_SIZE
41 ) -> None:
42 self.scheduler = scheduler
43 self._max_list_operations_page_size = max_list_operations_page_size
45 # --- Public API ---
47 def start(self) -> None:
48 self.scheduler.start()
50 def stop(self) -> None:
51 self.scheduler.stop()
52 LOGGER.info("Stopped Operations.")
54 def get_operation(self, operation_name: str) -> tuple[Operation, RequestMetadata | None, ClientIdentity | None]:
55 try:
56 operation = self.scheduler.load_operation(operation_name)
58 except NotFoundError:
59 raise InvalidArgumentError(f"Operation name does not exist: [{operation_name}]")
61 metadata = self.scheduler.get_operation_request_metadata_by_name(operation_name)
62 client_identity = self.scheduler.get_client_identity_by_operation(operation_name)
63 return operation, metadata, client_identity
65 def list_operations(
66 self, filter_string: str, page_size: int | None, page_token: str | None
67 ) -> ListOperationsResponse:
68 if page_size and page_size > self._max_list_operations_page_size:
69 raise InvalidArgumentError(f"The maximum page size is {self._max_list_operations_page_size}.")
70 if not page_size:
71 page_size = self._max_list_operations_page_size
73 operation_filters = FilterParser.parse_listoperations_filters(filter_string)
74 if not operation_filters:
75 operation_filters = DEFAULT_OPERATION_FILTERS
77 response = ListOperationsResponse()
79 results, next_token = self.scheduler.list_operations(operation_filters, page_size, page_token)
80 response.operations.extend(results)
81 response.next_page_token = next_token
83 return response
85 def delete_operation(self, job_name: str) -> None:
86 """DeleteOperation is not supported in BuildGrid."""
87 pass
89 def cancel_operation(self, operation_name: str) -> None:
90 try:
91 self.scheduler.cancel_operation(operation_name)
93 except NotFoundError:
94 raise InvalidArgumentError(f"Operation name does not exist: [{operation_name}]")