diff --git a/packages/google-cloud-optimization/samples/snippets/async_api.py b/packages/google-cloud-optimization/samples/snippets/async_api.py new file mode 100644 index 000000000000..f181f287f87e --- /dev/null +++ b/packages/google-cloud-optimization/samples/snippets/async_api.py @@ -0,0 +1,55 @@ +# Copyright 2022 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. + +# [START cloudoptimization_async_api] + +from google.api_core.exceptions import GoogleAPICallError +from google.cloud import optimization_v1 + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# request_file_name = 'YOUR_REQUEST_FILE_NAME' +# request_model_gcs_path = 'gs://YOUR_PROJECT/YOUR_BUCKET/YOUR_REQUEST_MODEL_PATH' +# model_solution_gcs_path = 'gs://YOUR_PROJECT/YOUR_BUCKET/YOUR_SOLUCTION_PATH' + + +def call_async_api(project_id: str, request_model_gcs_path: str, model_solution_gcs_path_prefix: str) -> None: + """Call the async api for fleet routing.""" + # Use the default credentials for the environment to authenticate the client. + fleet_routing_client = optimization_v1.FleetRoutingClient() + request_file_name = "resources/async_request.json" + + with open(request_file_name, 'r') as f: + fleet_routing_request = optimization_v1.BatchOptimizeToursRequest.from_json(f.read()) + fleet_routing_request.parent = f"projects/{project_id}" + for idx, mc in enumerate(fleet_routing_request.model_configs): + mc.input_config.gcs_source.uri = request_model_gcs_path + model_solution_gcs_path = f'{model_solution_gcs_path_prefix}_{idx}' + mc.output_config.gcs_destination.uri = model_solution_gcs_path + + # The timeout argument for the gRPC call is independent from the `timeout` + # field in the request's OptimizeToursRequest message(s). + operation = fleet_routing_client.batch_optimize_tours(fleet_routing_request) + print(operation.operation.name) + + try: + # Block to wait for the job to finish. + result = operation.result() + print(result) + # Do you stuff. + except GoogleAPICallError: + print(operation.operation.error) + + +# [END cloudoptimization_async_api] diff --git a/packages/google-cloud-optimization/samples/snippets/async_api_test.py b/packages/google-cloud-optimization/samples/snippets/async_api_test.py new file mode 100644 index 000000000000..81a04a8d08e5 --- /dev/null +++ b/packages/google-cloud-optimization/samples/snippets/async_api_test.py @@ -0,0 +1,48 @@ +# Copyright 2022 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 uuid + +import google.auth +from google.cloud import storage +import pytest +from samples.snippets import async_api + + +# TODO(developer): Replace the variables in the file before use. +# A sample request model can be found at resources/async_request_model.json. +TEST_UUID = uuid.uuid4() +BUCKET = f'optimization-ai-{TEST_UUID}' +OUTPUT_PREFIX = f'code_snippets_test_output_{TEST_UUID}' +INPUT_URI = "gs://cloud-samples-data/optimization-ai/async_request_model.json" +BATCH_OUTPUT_URI_PREFIX = "gs://{}/{}/".format(BUCKET, OUTPUT_PREFIX) + + +@pytest.fixture(autouse=True) +def setup_teardown() -> None: + """Create a temporary bucket to store optimization output.""" + storage_client = storage.Client() + bucket = storage_client.create_bucket(BUCKET) + + yield + + bucket.delete(force=True) + + +def test_call_async_api(capsys: pytest.LogCaptureFixture) -> None: + _, project_id = google.auth.default() + async_api.call_async_api(project_id, INPUT_URI, BATCH_OUTPUT_URI_PREFIX) + out, _ = capsys.readouterr() + + assert "operations" in out diff --git a/packages/google-cloud-optimization/samples/snippets/requirements.txt b/packages/google-cloud-optimization/samples/snippets/requirements.txt index ba9c484035ad..f9727ac0fea2 100644 --- a/packages/google-cloud-optimization/samples/snippets/requirements.txt +++ b/packages/google-cloud-optimization/samples/snippets/requirements.txt @@ -1 +1,2 @@ google-cloud-optimization==0.1.0 +google-cloud-storage==2.2.1 diff --git a/packages/google-cloud-optimization/samples/snippets/resources/async_request.json b/packages/google-cloud-optimization/samples/snippets/resources/async_request.json new file mode 100644 index 000000000000..10ae1b0cc254 --- /dev/null +++ b/packages/google-cloud-optimization/samples/snippets/resources/async_request.json @@ -0,0 +1,33 @@ +{ + "parent": "projects/${YOUR_GCP_PROJECT_ID}", + "model_configs":[ + { + "input_config":{ + "gcs_source":{ + "uri":"${REQUEST_MODEL_GCS_PATH}" + }, + "data_format":"JSON" + }, + "output_config":{ + "gcs_destination":{ + "uri":"${MODEL_SOLUTION_GCS_PATH}" + }, + "data_format":"JSON" + } + }, + { + "input_config":{ + "gcs_source":{ + "uri":"${REQUEST_MODEL_GCS_PATH}" + }, + "data_format":"JSON" + }, + "output_config":{ + "gcs_destination":{ + "uri":"${MODEL_SOLUTION_GCS_PATH}" + }, + "data_format":"JSON" + } + } + ] + } \ No newline at end of file diff --git a/packages/google-cloud-optimization/samples/snippets/resources/async_request_model.json b/packages/google-cloud-optimization/samples/snippets/resources/async_request_model.json new file mode 100644 index 000000000000..75c4b111be4e --- /dev/null +++ b/packages/google-cloud-optimization/samples/snippets/resources/async_request_model.json @@ -0,0 +1,114 @@ +{ + "parent":"${YOUR_GCP_PROJECT_ID}", + "allowLargeDeadlineDespiteInterruptionRisk":true, + "model":{ + "shipments":[ + { + "deliveries":[ + { + "arrivalLocation":{ + "latitude":48.880941999999997, + "longitude":2.3238660000000002 + }, + "duration":"250s", + "timeWindows":[ + { + "endTime":"1970-01-01T01:06:40Z", + "startTime":"1970-01-01T00:50:00Z" + } + ] + } + ], + "loadDemands": { + "weight": { + "amount": "10" + } + }, + "pickups":[ + { + "arrivalLocation":{ + "latitude":48.874507000000001, + "longitude":2.3036099999999999 + }, + "duration":"150s", + "timeWindows":[ + { + "endTime":"1970-01-01T00:33:20Z", + "startTime":"1970-01-01T00:16:40Z" + } + ] + } + ] + }, + { + "deliveries":[ + { + "arrivalLocation":{ + "latitude":48.880940000000002, + "longitude":2.3238439999999998 + }, + "duration":"251s", + "timeWindows":[ + { + "endTime":"1970-01-01T01:06:41Z", + "startTime":"1970-01-01T00:50:01Z" + } + ] + } + ], + "loadDemands": { + "weight": { + "amount": "20" + } + }, + "pickups":[ + { + "arrivalLocation":{ + "latitude":48.880943000000002, + "longitude":2.3238669999999999 + }, + "duration":"151s", + "timeWindows":[ + { + "endTime":"1970-01-01T00:33:21Z", + "startTime":"1970-01-01T00:16:41Z" + } + ] + } + ] + } + ], + "vehicles":[ + { + "loadLimits": { + "weight": { + "maxLoad": 50 + } + }, + "endLocation":{ + "latitude":48.863109999999999, + "longitude":2.341205 + }, + "startLocation":{ + "latitude":48.863101999999998, + "longitude":2.3412039999999998 + } + }, + { + "loadLimits": { + "weight": { + "maxLoad": 60 + } + }, + "endLocation":{ + "latitude":48.863120000000002, + "longitude":2.341215 + }, + "startLocation":{ + "latitude":48.863112000000001, + "longitude":2.3412139999999999 + } + } + ] + } + } \ No newline at end of file