aiskakov28 opened a new pull request, #18760:
URL: https://github.com/apache/iceberg/pull/18760

   When several clients create the same namespace at once, 
`JdbcCatalog.createNamespace` can let more than one of them pass its 
`namespaceExists` check. The first properties insert wins, and the others fail 
on the primary key of `iceberg_namespace_properties`. That `SQLException` comes 
out as `UncheckedSQLException`, which REST servers return as a 500, so the 
client can't tell that its create was simply rejected because the namespace 
already exists.
   
   This catches the failed insert and checks again whether the namespace 
exists. If it does, `createNamespace` throws `AlreadyExistsException`, the same 
as when the first check finds it, and the REST layer returns 409. If the 
recheck succeeds and the namespace still doesn't exist, the original exception 
is rethrown, so other insert failures are reported as before. It doesn't depend 
on database-specific error codes. iceberg-go fixed the same race in its SQL 
catalog the same way (apache/iceberg-go#1635).
   
   The new test, `testCreateNamespaceLosingConcurrentCreate`, is deterministic: 
it creates the namespace, then uses a spy so that the second create's first 
`namespaceExists` check returns `false`, as it would for a create that ran its 
check just before the winner's insert. Without the change it fails with 
`UncheckedSQLException: Failed to execute: INSERT INTO 
iceberg_namespace_properties ...`; with it, the create throws 
`AlreadyExistsException` and the winner's properties are unchanged.
   
   Closes #18759.
   
   **Testing**
   
   - `./gradlew :iceberg-core:test --tests 
org.apache.iceberg.jdbc.TestJdbcCatalog` on JDK 21: 157 tests, 0 failures, 12 
skipped. The new test fails without the change.
   - `./gradlew :iceberg-core:spotlessCheck` passes.
   - End to end, with `apache/iceberg-rest-fixture` images built from this 
commit with and without the change (`./gradlew :iceberg-open-api:shadowJar` and 
the fixture Dockerfile): 6 clients creating the same namespace, 20 rounds, 4 
runs each. Without the change, every round had one 200 and 18–57 of the 120 
creates per run got a 500. With it, every round had one 200 and every other 
create got a 409, with no 500s.
   
   Found by @aiskakov28 and @aldusialn.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to