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

Attempting to update a document with revision comparison in 7.2.0 causes conflict #707

Closed
robross0606 opened this issue Dec 15, 2020 · 12 comments
Labels
Feature Request Request for new functionality to be added to the driver.

Comments

@robross0606
Copy link

robross0606 commented Dec 15, 2020

This unit test fails:

  it.only('Document updates with revision checking causes conflict', async () => {
    const testCount = 10

    const db = arangoService.getInstance()
    const collection = await db.createCollection('test')
    const collectionData = await collection.get()
    expect(collectionData.type).toBe(CollectionType.DOCUMENT_COLLECTION)

    // Create documents
    const created = []
    for (let i = 0; i < testCount; i++) {
      created.push(await collection.save({ test: 'update-failure', count: 1 }, { returnNew: true }))
    }
    expect(created).toBeArrayOfObjects()
    expect(created).toBeArrayOfSize(testCount)

    // Now try to update them
    const updated = []
    for (const doc of created) {
      updated.push(
        await collection.update(
          doc._id,
          { _rev: doc._rev, updated: true },
          { returnOld: true, returnNew: true, ignoreRevs: false }
        )
      )
    }
    expect(updated).toBeArrayOfObjects()
    expect(updated).toBeArrayOfSize(testCount)
  })

The error is:

    ArangoError: conflict

      at new ArangoError (node_modules/src/error.ts:143:17)
      at Object.resolve (node_modules/src/connection.ts:900:20)
      at callback (node_modules/src/connection.ts:628:16)

If ignoreRevs is set to true or the _rev property is not provided on the document content, the test passes.

@robross0606 robross0606 changed the title Attempting to update a document while using _rev property causes conflict Attempting to update a document with revision comparison causes conflict Dec 15, 2020
@robross0606 robross0606 changed the title Attempting to update a document with revision comparison causes conflict Attempting to update a document with revision comparison in 7.2.0 causes conflict Dec 15, 2020
@robross0606
Copy link
Author

robross0606 commented Dec 15, 2020

I have also tried with a single document update which also fails with the same error:

  it.only('Document update with revision checking causes conflict', async () => {
    const db = arangoService.getInstance()
    const collection = await db.createCollection('test')
    const collectionData = await collection.get()
    expect(collectionData.type).toBe(CollectionType.DOCUMENT_COLLECTION)

    // Create document
    const created = await collection.save({ test: 'update-failure' }, { returnNew: true })
    expect(created).toBeNonEmptyObject()
    expect(created._id).toBeNonEmptyString()
    expect(created._rev).toBeNonEmptyString()
    expect(created.new.test).toBe('update-failure')
    expect(created.new.updated).toBeFalsy()

    // Now try to update
    const updated = await collection.update(
      created._id,
      { _rev: created._rev, updated: true },
      { returnOld: true, returnNew: true, ignoreRevs: false }
    )
    expect(updated).toBeNonEmptyObject()
    expect(updated._id).toBe(created._id)
    expect(updated._rev).not.toBe(created._rev)
    expect(updated.new.test).toBe(created.new.test)
    expect(updated.new.updated).toBeTruthy()
  })

Failure:

    ArangoError: conflict

      at new ArangoError (node_modules/src/error.ts:143:17)
      at Object.resolve (node_modules/src/connection.ts:900:20)
      at callback (node_modules/src/connection.ts:628:16)
      at IncomingMessage.<anonymous> (node_modules/src/lib/request.node.ts:165:15)

@robross0606
Copy link
Author

robross0606 commented Dec 15, 2020

With the old driver where rev was passed in as an option, this resulted in an HTTP API header value:

if-match: _bkexiY----

However, with the new API, there is no if-match header value. The value is passed in as a _rev in the body and this fails for some reason even though the HTTP API docs read for all the world like this should succeed:

If the If-Match header is specified and the revision of the document in the database is unequal to the given revision, the precondition is violated.

If If-Match is not given and ignoreRevs is false and there is a _rev attribute in the body and its value does not match the revision of the document in the database, the precondition is violated.

I have attached two Wireshark PCAP captures showing the difference between the two drivers using effectively the same unit test.

PCAP.zip

@robross0606
Copy link
Author

I think the documentation on HTTP API is incorrect, or at least misleading. I tried this directly from the REST "Try It" feature on the Support page of the web UI and it fails in a similar manner. If using the If-Match header it works fine. If using a _rev stored in the body of the input, it fails:
image

@pluma
Copy link
Contributor

pluma commented Jan 13, 2021

Looks like the HTTP API docs are incorrect or misleading. It's probably easiest to restore the if-match behavior of v6, though I think the new option should be called ifMatch rather than rev.

@robross0606
Copy link
Author

robross0606 commented Jan 13, 2021

My only issue with calling it ifMatch is you're intentionally breaking backward compatibility with previous versions of your library. Putting back rev would make it backward compatible. This isn't a new option. It is an old option that was removed. Either way, I'll take it if it works. :)

@robross0606
Copy link
Author

FYI, underlying Arango bug (arangodb/arangodb#13232) is confirmed.

@Simran-B
Copy link
Contributor

The server-side issue is fixed in 3.6.12 and 3.7.7, but it may still be desirable to have a driver-side workaround for earlier versions.

@robross0606
Copy link
Author

robross0606 commented Apr 19, 2021

@Simran-B, trying to plan for our own projects. Any idea if/when a "driver-side workaround for earlier versions" might be implemented?

@robross0606
Copy link
Author

robross0606 commented Apr 26, 2021

@Simran-B, I'm trying to figure out if this change now makes the ArangoJS 7.x driver incompatible with older servers. This would appear to be the case as attempting to put _rev in the input with ignoreRevs: false works okay with 3.7.9 but breaks against a 3.6.5 server with a " precondition failed" error. Is there some way to use the 7.x driver update() call with revision checks that is compatible with both 3.6.x and 3.7.x servers?

@robross0606
Copy link
Author

@Simran-B, looks like this only fails on servers earlier than 3.6.12 so that may well be what you mean by:

The server-side issue is fixed in 3.6.12 and 3.7.7, but it may still be desirable to have a driver-side workaround for earlier versions.

I wasn't expecting it to fail outright on earlier versions now.

@robross0606
Copy link
Author

robross0606 commented Apr 27, 2021

@Simran-B here are some wireshark captures of the update HTTP PATCH calls to compare responses from a 3.7.9, 3.6.12 and 3.6.5 server.
3.7.9 success.pcapng.log
3.6.12 success.pcapng.log
3.6.5 failure.pcapng.log
The driver is clearly doing the same thing every time. But the earlier versions of the server do not like the changes.

@robross0606
Copy link
Author

@Simran-B, just noticed workaround hinted at in arangodb/arangodb#13232 (comment). Adding the _key to the input does indeed appear to make calls cross-compatible with old and new versions.

@pluma pluma added Feature Request Request for new functionality to be added to the driver. and removed Bug A code defect that needs to be fixed. labels Jan 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Request for new functionality to be added to the driver.
Projects
None yet
Development

No branches or pull requests

3 participants