Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHPLIB-1627: BulkWriteCommand API #1630

Draft
wants to merge 7 commits into
base: v2.x
Choose a base branch
from
Draft

Conversation

jmikola
Copy link
Member

@jmikola jmikola commented Mar 4, 2025

throw new InvalidArgumentException('$collection is associated with a different MongoDB\Driver\Manager');
}

return new self(
Copy link
Member

Choose a reason for hiding this comment

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

Do you allow extending this class? In that case, you should use static here and in all return types. Otherwise the class should be final.

Copy link
Member Author

Choose a reason for hiding this comment

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

Introducing it as final seems preferable.

* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function bulkWrite(BulkWriteCommand|BulkWriteCommandBuilder $bulk, array $options = []): ?BulkWriteCommandResult
Copy link
Member

Choose a reason for hiding this comment

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

When is null returned? I think this should be mentioned in the comment.

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently, executeBulkWriteCommand() returns null when an unacknowledged write concern is used.

The alternative would be to return BulkWriteCommandResult object where isAcknowledged() returns false and no other methods can be called. That's what we do in the legacy executeBulkWrite() API.

I'm leaning towards a null object since it's consistent with the spec's instruction on not populating partialResult on BulkWriteCommandException when zero successful writes have occurred. In the legacy API, the result object could just be empty.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm now wondering if the current design of having executeBulkWriteCommand() return a nullable BulkWriteCommandResult is optimal. Interestingly, the spec doesn't explicitly suggest that when it presents a signature for Client::bulkWrite(), but the section on modeling unacknowledged results ends up suggesting this when it links to the CRUD spec's guidance on modeling unacknowledged results. I was also influenced by libmongoc, which leaves the result null in these cases.

The spec is clear about BulkWriteCommandException having an optional value for the partial write result, so I was planning to use nullable BulkWriteCommandResult for its $partialResult property (and getter); however, I'm curious if a BulkWriteCommandResult object in an unacknowledged state would also be preferable there.

In PHPC-2144, we changed PHPC 2.0 to remove the nullable return types for fields on WriteResult when the write was unacknowledged. Instead, we just throw if getters are accessed and the result object is empty (i.e. isAcknowledged() returns false). That made PHPC consistent with the PHPLIB API. My memory is a bit fuzzy, but I remember the nullable return values being more of an annoyance for static analysis. And in the general case where users don't use w:0, they can probably ignore isAcknowledged() and just assume that exceptions won't be thrown when they access the result.

Copy link
Member

Choose a reason for hiding this comment

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

In general, I think it would be preferable to return something other than null in all cases, as long as users can deduce what happen (e.g. unacknowledged writes). Returning null in some cases creates one "special" condition that users need to check for instead of handling a result in all cases that didn't error.

Copy link
Member

@GromNaN GromNaN Mar 11, 2025

Choose a reason for hiding this comment

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

The method Collection::bulkWrite() always returns an instance of BulkWriteResult, I would do the same for Client::bulkWrite().

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it would be preferable to return something other than null in all cases

How do you feel about the verbose result fields (e.g. BulkWriteCommandResult::getInsertResults()) returning a nullable Document? If we have the regular getters (e.g. getInsertedCount()) throw when isAcknowledged() is false, we can do the same with the others in relation to a hasVerboseResults() field. That is one approach suggested in the bulkWrite spec, although it's this is a level removed from the Client::bulkWrite() API so it's less important.

I also didn't have qualms about using a nullable BulkWriteCommandResult for BulkWriteCommandException::getPartialResult(), which is directly suggested in the spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants