GH-maggio commented on issue #11108: URL: https://github.com/apache/gravitino/issues/11108#issuecomment-5804317004
Additionally, this closes a silent data-loss window for Lance writers on S3-compatible gateways, ie versitygw. ### The dependency today With `namespace-backend: gravitino`, Lance clients resolve tables through the namespace but commit through the object store. For an `s3://` location, `commit_handler_from_url` selects `ConditionalPutCommitHandler` unconditionally — no capability probe, no fallback — and that handler's `put_opts(..., PutMode::Create)` (`If-None-Match: *`) is the **sole** arbiter of who wins a version. `AlreadyExists`/`Precondition` becomes `CommitConflict`; anything else is treated as a successful commit. So correctness rests entirely on the object store enforcing put-if-absent. ### Where that breaks Not all S3 gateways enforce it across gateway processes. See [versity/versitygw#2359](https://github.com/versity/versitygw/pull/2359), "make conditional publish lock modes explicit" (merged 2026-09-11, not yet in a release; v1.8.0 is current). Its premise: > A successful flock call does not prove that property: some clustered > filesystem configurations accept flock but scope it to one node, silently > leaving cross-gateway check-and-publish races open. Measured this on an clustered fileset backing a multi-replica versitygw deployment, using pods pinned to different nodes: | Primitive | Same node | Cross node | Result | | --- | --- | --- | --- | | `flock` | denied | **acquired** (both directions) | not cluster-coherent | | `fcntl` byte-range | denied | denied (`EAGAIN`, both directions) | cluster-coherent | Controls: both pods verified to address the same inode, and an attempt from the holder's own node was denied on every round, so the lock was genuinely held and the harness was sound. Consequence for Lance: with a gateway that uses node-scoped locking, two concurrent writers to the same dataset can both pass the existence check and both publish the same manifest version. The later silently wins. Both clients report a successful commit and no conflict is raised — there is nothing to alert on. Lance already special-cases Tencent COS (`TencentCosCommitHandler`) for the same class of problem, but there is no way to detect it for a self-hosted gateway from the URI or storage options. ### Why this feature fixes it `CreateTableVersion` documents `put_if_not_exists` semantics with 409 Conflict, which moves commit arbitration from the object store into the catalog. Once that path is used, gateway lock coherence stops mattering — the same reason Iceberg-on-JDBC is unaffected in the same deployment. The client side already appears complete: `namespace_manifest.rs` maps `put`/`get`/`get_latest_version` onto `create_table_version`/`describe_table_version`/`list_table_versions`, and `DatasetBuilder::from_namespace` installs `ExternalManifestCommitHandler` when `managed_versioning == Some(true)`. On the Gravitino side (1.3.0), the Lance REST server exposes `/v1/namespace` and `/v1/table/{id}` only, and `managed_versioning` appears solely in the generated client DTOs — so the remaining gap looks like the five version operations plus setting that flag in `describe_table`/`declare_table`. AI generated. -- 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]
