Skip to content

fix(database): serialize push ID generation - #16768

Merged
ncooke3 merged 4 commits into
firebase:mainfrom
dajiaohuang:fix/database-next-push-id-lock
Oct 14, 2026
Merged

ncooke3 merged 4 commits into
firebase:mainfrom
dajiaohuang:fix/database-next-push-id-lock

Conversation

@dajiaohuang

@dajiaohuang dajiaohuang commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Protect the shared Realtime Database push ID timestamp and random suffix while generating IDs.
  • Cover concurrent same-timestamp uniqueness and monitor release after an exception; document the user-visible duplicate-ID race under Unreleased with fix(database): serialize push ID generation #16768.

childByAutoId invokes the generator synchronously on the caller's thread. Concurrent calls could interleave reads and updates of process-wide state, so the whole state transition and ID construction now run under one lock. The exception test accepts Foundation's NSException hierarchy rather than assuming one specific exception name.

Validation

  • Affected files pass clang-format 23.1.2 and git diff --check.
  • At source 30deadd, the actual upstream Catalyst Database unit suite executes 431 tests with zero failures, including concurrent push ID uniqueness and exception handling: native XCTest log.
  • The broader workflow still fails its separate quickstart dependency resolution because FirebaseUI 16 and the required gtm-session-fetcher range conflict. The unit pass above does not claim the full workflow is green.

@gemini-code-assist

Copy link
Copy Markdown
Contributor
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.

@paulb777

paulb777 commented Oct 1, 2026

Copy link
Copy Markdown
Member

Thanks for the contribution! A few housekeeping items:

  • CHANGELOG: The entry in FirebaseDatabase/CHANGELOG.md was added above # 12.19.0 without a heading, so it reads as part of a release that has already shipped. Please move it under a # Unreleased heading at the top of the file (add the heading if it isn't there yet).
  • PR number: end the entry with this PR's number, e.g. - [fixed] Description. (#16768).
  • Formatting: after updating, please run scripts/style.sh so the infra.check job passes. It needs clang-format 23 and swiftformat (see scripts/setup_check.sh). If you can't run it locally, the infra.check log lists the files that need formatting.

@paulb777 paulb777 added this to the 13.1.0 - M188 milestone Oct 1, 2026
@paulb777

paulb777 commented Oct 1, 2026

Copy link
Copy Markdown
Member

/gemini review

@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 introduces thread safety to the generation of Realtime Database push IDs in FNextPushId.m by utilizing an NSLock, and adds a concurrent unit test to verify that push IDs generated concurrently for the same timestamp remain unique. The review feedback suggests a minor improvement to use [id copy] instead of [NSString stringWithString:id] for better idiomatic efficiency in Objective-C.

Comment thread FirebaseDatabase/Sources/Utilities/FNextPushId.m Outdated
@paulb777 paulb777 self-assigned this Oct 1, 2026

@paulb777 paulb777 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, this is a real race: childByAutoId calls +[FNextPushId get:] synchronously on the caller's thread, and the static state isn't synchronized, so concurrent calls can produce duplicate IDs (silently overwriting data) or even an out-of-range characterAtIndex:. Android already makes this method synchronized.

Optional: the CHANGELOG entry could describe the user-visible effect, e.g. - [fixed] Fixed a race where calling childByAutoId() concurrently from multiple threads could generate duplicate push IDs. (#16768)

Comment thread FirebaseDatabase/Sources/Utilities/FNextPushId.m Outdated
Comment thread FirebaseDatabase/Tests/Unit/FNextPushIdTest.m Outdated
@dajiaohuang

Copy link
Copy Markdown
Contributor Author

Replaced the manual NSLock/dispatch_once setup with @synchronized([FNextPushId class]) around the whole shared-state update and ID construction, so an Objective-C exception releases the monitor. The fixed class monitor also covers subclasses sharing this static state. Removed the redundant dispatch header and added a bounded regression that verifies a generation exception does not block a later valid call; the 1000-call same-timestamp uniqueness test remains.

The CHANGELOG now uses Unreleased and the suggested user-visible description with #16768. Both changed Objective-C files pass clang-format 23.1.2 validation and git diff --check. Apple tests have not run locally; current-head native CI must validate the regression.

@paulb777

paulb777 commented Oct 2, 2026

Copy link
Copy Markdown
Member

/gemini review

@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 fixes a race condition in childByAutoId() by wrapping the push ID generation logic in FNextPushId.m within a @synchronized block, and adds corresponding unit tests to verify thread safety. Feedback on the changes suggests optimizing the ID generation by avoiding the reserved keyword id as a variable name and replacing the inefficient NSMutableString loop with a stack-allocated unichar array.

Comment thread FirebaseDatabase/Sources/Utilities/FNextPushId.m
@dajiaohuang

Copy link
Copy Markdown
Contributor Author

Current-head macOS CI exposed an overly specific assumption in the new exception-release test: constant NSString raises NSInvalidArgumentException for the negative index, while the test named NSRangeException. The regression now asserts NSException and retains the background generation completion timeout and 20-character output check. This tests monitor release without depending on Foundation's exception-name choice. Concurrent uniqueness passed in the captured macOS run; the whole DatabaseUnit run was 431 tests with this one failure. Formatter/diff checks pass for the one-line correction; new-head native CI still needs to finish.

@paulb777

paulb777 commented Oct 2, 2026

Copy link
Copy Markdown
Member

/gemini review

@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 addresses a race condition in childByAutoId() by wrapping the push ID generation logic in FNextPushId.m within a @synchronized block, and adds corresponding unit tests to verify thread safety and exception handling. Feedback on the changes highlights a critical buffer underflow risk when incrementing the random character array, the discouraged use of the reserved keyword 'id' as a variable name in Objective-C, and redundant floor function calls on integer values.

Comment thread FirebaseDatabase/Sources/Utilities/FNextPushId.m
@paulb777 paulb777 assigned ncooke3 and unassigned paulb777 Oct 2, 2026
@ncooke3

ncooke3 commented Oct 14, 2026

Copy link
Copy Markdown
Member

Thanks @dajiaohuang!

@ncooke3
ncooke3 merged commit 076787e into firebase:main Oct 14, 2026
42 of 43 checks passed
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.

3 participants