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

Command does not support writeConcern with wire version 4 #967

Closed
timwhitlock opened this issue Mar 18, 2019 · 4 comments
Closed

Command does not support writeConcern with wire version 4 #967

timwhitlock opened this issue Mar 18, 2019 · 4 comments

Comments

@timwhitlock
Copy link

Description

After upgrading the driver to any 1.5.x version, write commands give me an error like this:

"insert" command does not support writeConcern with wire version 4, wire version 5 is required

Version 1.4.4 works fine using v1.9.4 of the C library. Same code, same server.

Environment

MongoDB server version is 3.2.22 using mmapv1 storage engine.

Happens with drivers 1.5.0 through 1.5.3 using bundled versions of libmongoc 1.11.0 through 1.13.0 respectively.

Same results on Mac (built from source) and CentOS (Remi repo).
PHP version is 7.2.16.

Test Script

$manager = new MongoDB\Driver\Manager( 'mongodb://localhost:27017', [
    'username' => 'foo',
    'password' => 'bar',
    'authSource' => 'admin',
] );

$cursor = $manager->executeWriteCommand( 'test', new MongoDB\Driver\Command( [
    'insert' => 'test',
    'documents' => [ [ 'time' => new MongoDB\BSON\UTCDateTime ] ],
] ), [
    'writeConcern' => new MongoDB\Driver\WriteConcern( 1, 5000, true ),
] );

Expected and Actual Behavior

Throws MongoDB\Driver\Exception\RuntimeException: "insert" command does not support writeConcern with wire version 4, wire version 5 is required.

@timwhitlock
Copy link
Author

timwhitlock commented Mar 18, 2019

Getting server info with db.isMaster() I can see that maxWireVersion = 4 and upgrading to MongoDB 3.4 increases this to 5 and fixes the issue.

To clarify: Does this mean that the driver cannot set write concerns on MongoDB 3.2? Were my write concerns under 1.4.4 simply being disregarded?

I can see this isn't a bug with the driver, but I find it very confusing that upgrading the driver removes functions that appeared to be working.

@jmikola
Copy link
Member

jmikola commented Mar 19, 2019

The read/write-specific command methods introduced in PHP driver 1.4.0 rely on equivalent functions in libmongoc, which are not intended to be used for the basic insert, update, and delete commands. I've opened PHPC-1350 to ensure that this is noted in the documentation for Manager::executeWriteCommand() and the corresponding Server method.

Were my write concerns under 1.4.4 simply being disregarded?

With respect to the code you shared above, yes. PHP driver 1.4.x will ignore a writeConcern option in the third argument to executeWriteCommand() on MongoDB 3.2 unless the command is findAndModify. The writeConcern option is respected for all other commands on MongoDB 3.4+.

Does this mean that the driver cannot set write concerns on MongoDB 3.2?

Write concerns have always been supported through executeBulkWrite(), which is the intended code path for all insert, update, and delete operations. If you look at the implementation of those Collection methods in the PHP library, you'll see executeBulkWrite() used (f.e. InsertOne operation).

If you prefer to use the extension directly, please use executeBulkWrite(). Otherwise, I suggest you use the library and its Collection methods for insert, update, and delete operations. For more information on the library, see the CRUD tutorial in its documentation.

Alternatively, specifying a writeConcern directly in the command document could work around the issue; however, I do not recommend that approach, as a newer version of the PHP extension and/or libmongoc could decide to inherit a client-level write concern and that could lead to undefined behavior (e.g. possibly two writeConcern fields in the outgoing BSON command document).


If you'd like additional background information about this issue, read on. The read/write-specific command methods were added to libmongoc specifically to support wrapping drivers, such as PHP. As you know, the PHP extension only provides a basic API for executing bulk writes, queries, and generic commands. The PHP library builds upon that API and provides various helpers for high-level operations (e.g. aggregation, variations of findAndModify).

When we introduced executeWriteCommand() and related methods in PHP driver 1.4.0, which wrap corresponding methods in libmongoc (e.g. mongoc_client_write_command_with_opts()), we realized an issue with libmongoc not respecting the writeConcern option for findAndModify commands on MongoDB 3.2 (wire version 4). The initial version of libmongoc's functions commands only respected the option when the wire version was >= 5, as MongoDB 3.4 was when all write commands gained support for a writeConcern option (see: wire version feature list). This was an understandable oversight since libmongoc provides its own findAndModify helpers, which do support a writeConcern option correctly on wire version >= 4. Therefore, this wasn't caught until we attempted to route the PHP library's findAndModify commands through the generic write command method.

That bug was addressed in CDRIVER-2410 for libmongoc 1.9. While mongodb/mongo-c-driver@bd7133d added logic to respect the writeConcern option (and inherit client-level write concerns) for findAndModify commands on wire version >= 4 and all other commands for wire version >= 5, it silently ignored the option if the server version was unsupported.

It was not until libmongoc 1.10 and CDRIVER-2214 that error reporting was introduced when a writeConcern or readConcern option was specified and not supported by the server (see: mongodb/mongo-c-driver@5c88fde).

From the perspective of the PHP driver, this means PHP driver 1.4.x may silently ignore the option. PHP driver 1.5.x uses newer versions of libmongoc (currently 1.11 through 1.13), which is why you see the exception there.

@timwhitlock
Copy link
Author

Thank you for such a comprehensive answer. It's much appreciated.

As an aside, I'm only using the driver directly because I migrated a six year old project from the legacy driver. I'll use it for any future projects.

@jmikola
Copy link
Member

jmikola commented Mar 19, 2019

As an aside, I'm only using the driver directly because I migrated a six year old project from the legacy driver. I'll use it for any future projects.

It sounds like you've already ported the legacy application, but on the off chance the job is still in progress you might find this upgrade guide helpful. For most things, there is a 1:1 mapping between the legacy mongo extension and the newer library.

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

No branches or pull requests

2 participants