Skip to content

Fix flaky GcsIOIntegrationTest and handle GCS bucket creation race conditions#39130

Open
shunping wants to merge 4 commits into
apache:masterfrom
shunping:fix-flaky-gcsio-integration-test
Open

Fix flaky GcsIOIntegrationTest and handle GCS bucket creation race conditions#39130
shunping wants to merge 4 commits into
apache:masterfrom
shunping:fix-flaky-gcsio-integration-test

Conversation

@shunping

@shunping shunping commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

A flaky test example:
https://github.com/apache/beam/actions/runs/28256309850/job/83720139509

______________ GcsIOIntegrationTest_1.test_create_default_bucket _______________
[gw2] linux -- Python 3.11.15 /runner/_work/beam/beam/build/gradleenv/2050596099/bin/python3

self = <apache_beam.io.gcp.gcsio_integration_test.GcsIOIntegrationTest_1 testMethod=test_create_default_bucket>
mock_default_gcs_bucket_name = <MagicMock name='default_gcs_bucket_name' id='134725042979024'>

...
    
>     bucket = gcsio.get_or_create_default_gcs_bucket(google_cloud_options)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

apache_beam/io/gcp/gcsio_integration_test.py:237: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
apache_beam/io/gcp/gcsio.py:146: in get_or_create_default_gcs_bucket
    return gcs.create_bucket(bucket_name, project, location=region)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
apache_beam/io/gcp/gcsio.py:245: in create_bucket
    bucket = self.client.create_bucket(
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/cloud/storage/client.py:1211: in create_bucket
    api_response = self._post_resource(
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/cloud/storage/client.py:790: in _post_resource
    return self._connection.api_request(
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/cloud/storage/_http.py:123: in api_request
    return call()
           ^^^^^^
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/api_core/retry/retry_unary.py:294: in retry_wrapped_func
    return retry_target(
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/api_core/retry/retry_unary.py:156: in retry_target
    next_sleep = _retry_error_helper(
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/api_core/retry/retry_base.py:216: in _retry_error_helper
    raise final_exc from source_exc
../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/api_core/retry/retry_unary.py:147: in retry_target
            path=path,
            query_params=query_params,
            api_base_url=api_base_url,
            api_version=api_version,
        )
    
        # Making the executive decision that any dictionary
        # data will be sent properly as JSON.
        if data and isinstance(data, dict):
            data = json.dumps(data)
            content_type = "application/json"
    
        response = self._make_request(
            method=method,
            url=url,
            data=data,
            content_type=content_type,
            headers=headers,
            target_object=_target_object,
            timeout=timeout,
            extra_api_info=extra_api_info,
        )
    
        if not 200 <= response.status_code < 300:
>           raise exceptions.from_http_response(response)
E           google.api_core.exceptions.Conflict: 409 POST https://storage.googleapis.com/storage/v1/b?project=apache-beam-testing&prettyPrint=false: Your previous request to create the named bucket succeeded and you already own it.

../../build/gradleenv/2050596099/lib/python3.11/site-packages/google/cloud/_http/__init__.py:494: Conflict

In this PR, we made the following changes:

  • Modify get_or_create_default_gcs_bucket in gcsio.py to catch Conflict (409) exceptions, resolving to the existing bucket on concurrent creation requests.
  • Add unit tests for default bucket creation conflict handling in gcsio_test.py.
  • Modify test_create_default_bucket in gcsio_integration_test.py to generate unique bucket names with a UUID prefix and test parameters to eliminate parallel test thread collisions.

…nditions

* Modify get_or_create_default_gcs_bucket in gcsio.py to catch Conflict (409)
  exceptions, resolving to the existing bucket on concurrent creation requests.
* Add unit tests for default bucket creation conflict handling in gcsio_test.py.
* Modify test_create_default_bucket in gcsio_integration_test.py to generate
  unique bucket names with a UUID prefix and test parameters to eliminate parallel
  test thread collisions.
@shunping shunping marked this pull request as ready for review June 27, 2026 09:57
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses flakiness in GcsIOIntegrationTest caused by race conditions during GCS bucket creation. By implementing robust conflict handling for 409 errors and improving the uniqueness of test bucket naming, the changes ensure that concurrent test executions do not interfere with each other, leading to more reliable CI/CD pipelines.

Highlights

  • Conflict Handling: Updated get_or_create_default_gcs_bucket in gcsio.py to catch 409 Conflict exceptions, allowing the system to gracefully handle existing buckets during concurrent creation attempts.
  • Test Stability: Enhanced GcsIOIntegrationTest by incorporating UUIDs and additional test parameters into bucket names to prevent race conditions and collisions in parallel CI environments.
  • Unit Testing: Added comprehensive unit tests in gcsio_test.py to verify the new conflict resolution logic and ensure correct behavior when bucket creation fails.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates get_or_create_default_gcs_bucket in gcsio.py to handle Conflict exceptions during bucket creation by fetching and validating the existing bucket. It also updates integration tests to use more unique bucket names to prevent collisions, and adds corresponding unit tests. Feedback highlights that the new bucket naming scheme in integration tests could exceed the 63-character GCS limit in regions with long names, suggesting shorter identifiers. Additionally, a redundant inner try-except block in gcsio.py was identified for simplification.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread sdks/python/apache_beam/io/gcp/gcsio_integration_test.py Outdated
Comment thread sdks/python/apache_beam/io/gcp/gcsio.py
@github-actions

Copy link
Copy Markdown
Contributor

Assigning reviewers:

R: @damccorm for label python.

Note: If you would like to opt out of this review, comment assign to next reviewer.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant