Skip to content

Commit d2fbd5b

Browse files
authored
fix(catalog): return 404 instead of 503 when drop races with concurrent delete (#4499)
* fix(catalog): return 404 instead of 503 when drop races with concurrent delete When a table/view/namespace is concurrently deleted by another request, dropEntityIfExists returns CATALOG_PATH_CANNOT_BE_RESOLVED. Previously this fell through to the default case and threw ServiceFailureException (HTTP 503). The entity is simply gone — this should be treated the same as ENTITY_NOT_FOUND (return false / 404), not a service failure. * Add DEBUG log when CATALOG_PATH_CANNOT_BE_RESOLVED on drop table * Add DEBUG log for CATALOG_PATH_CANNOT_BE_RESOLVED in dropNamespace and dropView
1 parent 4e2e71a commit d2fbd5b

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,13 @@ public boolean dropTable(TableIdentifier tableIdentifier, boolean purge) {
434434
case BaseResult.ReturnStatus.ENTITY_NOT_FOUND:
435435
return false;
436436

437+
case BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED:
438+
LOGGER.debug(
439+
"Catalog path cannot be resolved for {}, treating as dropped; extraInfo={}",
440+
tableIdentifier,
441+
dropEntityResult.getExtraInformation());
442+
return false;
443+
437444
case BaseResult.ReturnStatus.ENTITY_UNDROPPABLE:
438445
throw new ForbiddenException(
439446
"Table %s cannot be dropped: %s",
@@ -683,6 +690,13 @@ public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyExcept
683690
case BaseResult.ReturnStatus.ENTITY_NOT_FOUND:
684691
return false;
685692

693+
case BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED:
694+
LOGGER.debug(
695+
"Catalog path cannot be resolved for {}, treating as dropped; extraInfo={}",
696+
namespace,
697+
dropEntityResult.getExtraInformation());
698+
return false;
699+
686700
default:
687701
throw new ServiceFailureException(
688702
"Failed to drop namespace %s, status=%s, extraInfo=%s",
@@ -934,6 +948,13 @@ public boolean dropView(TableIdentifier identifier) {
934948
case BaseResult.ReturnStatus.ENTITY_NOT_FOUND:
935949
return false;
936950

951+
case BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED:
952+
LOGGER.debug(
953+
"Catalog path cannot be resolved for {}, treating as dropped; extraInfo={}",
954+
identifier,
955+
dropEntityResult.getExtraInformation());
956+
return false;
957+
937958
case BaseResult.ReturnStatus.ENTITY_UNDROPPABLE:
938959
throw new ForbiddenException(
939960
"View %s cannot be dropped: %s", identifier, dropEntityResult.getExtraInformation());

runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,70 @@ public void testDropViewWithUndroppableEntity() {
20832083
.hasMessageContaining("cannot be dropped");
20842084
}
20852085

2086+
@Test
2087+
public void testDropTableWithCatalogPathCannotBeResolved() {
2088+
catalog.createNamespace(NS);
2089+
catalog.buildTable(TABLE, SCHEMA).create();
2090+
2091+
PolarisMetaStoreManager spiedManager = spy(metaStoreManager);
2092+
doReturn(new DropEntityResult(BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED, null))
2093+
.when(spiedManager)
2094+
.dropEntityIfExists(any(), anyList(), any(), anyMap(), anyBoolean());
2095+
2096+
IcebergCatalog spiedCatalog = newIcebergCatalog(CATALOG_NAME, spiedManager, fileIOFactory);
2097+
spiedCatalog.initialize(
2098+
CATALOG_NAME,
2099+
ImmutableMap.of(
2100+
CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.inmemory.InMemoryFileIO"));
2101+
2102+
boolean result = spiedCatalog.dropTable(TABLE, false);
2103+
Assertions.assertThat(result).isFalse();
2104+
}
2105+
2106+
@Test
2107+
public void testDropViewWithCatalogPathCannotBeResolved() {
2108+
catalog.createNamespace(NS);
2109+
catalog
2110+
.buildView(TABLE)
2111+
.withSchema(SCHEMA)
2112+
.withDefaultNamespace(NS)
2113+
.withQuery("spark", "SELECT * FROM ns.tbl")
2114+
.create();
2115+
2116+
PolarisMetaStoreManager spiedManager = spy(metaStoreManager);
2117+
doReturn(new DropEntityResult(BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED, null))
2118+
.when(spiedManager)
2119+
.dropEntityIfExists(any(), anyList(), any(), anyMap(), anyBoolean());
2120+
2121+
IcebergCatalog spiedCatalog = newIcebergCatalog(CATALOG_NAME, spiedManager, fileIOFactory);
2122+
spiedCatalog.initialize(
2123+
CATALOG_NAME,
2124+
ImmutableMap.of(
2125+
CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.inmemory.InMemoryFileIO"));
2126+
2127+
boolean result = spiedCatalog.dropView(TABLE);
2128+
Assertions.assertThat(result).isFalse();
2129+
}
2130+
2131+
@Test
2132+
public void testDropNamespaceWithCatalogPathCannotBeResolved() {
2133+
catalog.createNamespace(NS);
2134+
2135+
PolarisMetaStoreManager spiedManager = spy(metaStoreManager);
2136+
doReturn(new DropEntityResult(BaseResult.ReturnStatus.CATALOG_PATH_CANNOT_BE_RESOLVED, null))
2137+
.when(spiedManager)
2138+
.dropEntityIfExists(any(), anyList(), any(), anyMap(), anyBoolean());
2139+
2140+
IcebergCatalog spiedCatalog = newIcebergCatalog(CATALOG_NAME, spiedManager, fileIOFactory);
2141+
spiedCatalog.initialize(
2142+
CATALOG_NAME,
2143+
ImmutableMap.of(
2144+
CatalogProperties.FILE_IO_IMPL, "org.apache.iceberg.inmemory.InMemoryFileIO"));
2145+
2146+
boolean result = spiedCatalog.dropNamespace(NS);
2147+
Assertions.assertThat(result).isFalse();
2148+
}
2149+
20862150
private TableMetadata createSampleTableMetadata(String tableLocation) {
20872151
Schema schema =
20882152
new Schema(

0 commit comments

Comments
 (0)