Skip to content

Commit 0a9a5d9

Browse files
authored
feat(cdi): Remove CallContext.close() (#1776)
Now that every catalog created by PolarisCallContextCatalogFactory is correctly closed by IcebergCatalogAdapter, we can finally remove the CallContext.close() method and the associated cloaseables group. This simplification will hopefully pave the way to a more robust handling of request-scoped beans in task executor threads.
1 parent 90c2580 commit 0a9a5d9

File tree

12 files changed

+470
-607
lines changed

12 files changed

+470
-607
lines changed

polaris-core/src/main/java/org/apache/polaris/core/context/CallContext.java

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,8 @@
1818
*/
1919
package org.apache.polaris.core.context;
2020

21-
import jakarta.annotation.Nonnull;
22-
import java.io.IOException;
23-
import java.util.HashMap;
24-
import java.util.Map;
25-
import java.util.stream.Collectors;
26-
import org.apache.iceberg.io.CloseableGroup;
2721
import org.apache.polaris.core.PolarisCallContext;
2822
import org.apache.polaris.core.PolarisDiagnostics;
29-
import org.slf4j.Logger;
30-
import org.slf4j.LoggerFactory;
3123

3224
/**
3325
* Stores elements associated with an individual REST request such as RealmContext, caller
@@ -37,15 +29,9 @@
3729
* principal/role entities may be defined within a Realm-specific persistence layer, and the
3830
* underlying nature of the persistence layer may differ between different realms.
3931
*/
40-
public interface CallContext extends AutoCloseable {
32+
public interface CallContext {
4133
InheritableThreadLocal<CallContext> CURRENT_CONTEXT = new InheritableThreadLocal<>();
4234

43-
// For requests that make use of a Catalog instance, this holds the instance that was
44-
// created, scoped to the current call context.
45-
String REQUEST_PATH_CATALOG_INSTANCE_KEY = "REQUEST_PATH_CATALOG_INSTANCE";
46-
47-
String CLOSEABLES = "closeables";
48-
4935
static CallContext setCurrentContext(CallContext context) {
5036
CURRENT_CONTEXT.set(context);
5137
return context;
@@ -65,7 +51,6 @@ static void unsetCurrentContext() {
6551

6652
static CallContext of(
6753
final RealmContext realmContext, final PolarisCallContext polarisCallContext) {
68-
Map<String, Object> map = new HashMap<>();
6954
return new CallContext() {
7055
@Override
7156
public RealmContext getRealmContext() {
@@ -76,28 +61,14 @@ public RealmContext getRealmContext() {
7661
public PolarisCallContext getPolarisCallContext() {
7762
return polarisCallContext;
7863
}
79-
80-
@Override
81-
public Map<String, Object> contextVariables() {
82-
return map;
83-
}
8464
};
8565
}
8666

87-
/**
88-
* Copy the {@link CallContext}. {@link #contextVariables()} will be copied except for {@link
89-
* #closeables()}. The original {@link #contextVariables()} map is untouched and {@link
90-
* #closeables()} in the original {@link CallContext} should be closed along with the {@link
91-
* CallContext}.
92-
*/
67+
/** Copy the {@link CallContext}. */
9368
static CallContext copyOf(CallContext base) {
9469
String realmId = base.getRealmContext().getRealmIdentifier();
9570
RealmContext realmContext = () -> realmId;
9671
PolarisCallContext polarisCallContext = PolarisCallContext.copyOf(base.getPolarisCallContext());
97-
Map<String, Object> contextVariables =
98-
base.contextVariables().entrySet().stream()
99-
.filter(e -> !e.getKey().equals(CLOSEABLES))
100-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
10172
return new CallContext() {
10273
@Override
10374
public RealmContext getRealmContext() {
@@ -108,11 +79,6 @@ public RealmContext getRealmContext() {
10879
public PolarisCallContext getPolarisCallContext() {
10980
return polarisCallContext;
11081
}
111-
112-
@Override
113-
public Map<String, Object> contextVariables() {
114-
return contextVariables;
115-
}
11682
};
11783
}
11884

@@ -122,28 +88,4 @@ public Map<String, Object> contextVariables() {
12288
* @return the inner context used for delegating services
12389
*/
12490
PolarisCallContext getPolarisCallContext();
125-
126-
Map<String, Object> contextVariables();
127-
128-
default @Nonnull CloseableGroup closeables() {
129-
return (CloseableGroup)
130-
contextVariables().computeIfAbsent(CLOSEABLES, key -> new CloseableGroup());
131-
}
132-
133-
@Override
134-
default void close() {
135-
if (CURRENT_CONTEXT.get() == this) {
136-
unsetCurrentContext();
137-
CloseableGroup closeables = closeables();
138-
try {
139-
closeables.close();
140-
} catch (IOException e) {
141-
Logger logger = LoggerFactory.getLogger(CallContext.class);
142-
logger
143-
.atWarn()
144-
.addKeyValue("closeableGroup", closeables)
145-
.log("Unable to close closeable group", e);
146-
}
147-
}
148-
}
14991
}

polaris-core/src/test/java/org/apache/polaris/core/storage/InMemoryStorageIntegrationTest.java

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -106,43 +106,41 @@ public void testValidateAccessToLocationsWithWildcard() {
106106
}
107107
},
108108
Clock.systemUTC());
109-
try (CallContext ignored =
110-
CallContext.setCurrentContext(CallContext.of(() -> "realm", polarisCallContext))) {
111-
Map<String, Map<PolarisStorageActions, PolarisStorageIntegration.ValidationResult>> result =
112-
storage.validateAccessToLocations(
113-
new FileStorageConfigurationInfo(List.of("file://", "*")),
114-
Set.of(PolarisStorageActions.READ),
115-
Set.of(
116-
"s3://bucket/path/to/warehouse/namespace/table",
117-
"file:///etc/passwd",
118-
"a/relative/subdirectory"));
119-
Assertions.assertThat(result)
120-
.hasSize(3)
121-
.hasEntrySatisfying(
122-
"s3://bucket/path/to/warehouse/namespace/table",
123-
val ->
124-
Assertions.assertThat(val)
125-
.hasSize(1)
126-
.containsKey(PolarisStorageActions.READ)
127-
.extractingByKey(PolarisStorageActions.READ)
128-
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess))
129-
.hasEntrySatisfying(
130-
"file:///etc/passwd",
131-
val ->
132-
Assertions.assertThat(val)
133-
.hasSize(1)
134-
.containsKey(PolarisStorageActions.READ)
135-
.extractingByKey(PolarisStorageActions.READ)
136-
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess))
137-
.hasEntrySatisfying(
138-
"a/relative/subdirectory",
139-
val ->
140-
Assertions.assertThat(val)
141-
.hasSize(1)
142-
.containsKey(PolarisStorageActions.READ)
143-
.extractingByKey(PolarisStorageActions.READ)
144-
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess));
145-
}
109+
CallContext.setCurrentContext(CallContext.of(() -> "realm", polarisCallContext));
110+
Map<String, Map<PolarisStorageActions, PolarisStorageIntegration.ValidationResult>> result =
111+
storage.validateAccessToLocations(
112+
new FileStorageConfigurationInfo(List.of("file://", "*")),
113+
Set.of(PolarisStorageActions.READ),
114+
Set.of(
115+
"s3://bucket/path/to/warehouse/namespace/table",
116+
"file:///etc/passwd",
117+
"a/relative/subdirectory"));
118+
Assertions.assertThat(result)
119+
.hasSize(3)
120+
.hasEntrySatisfying(
121+
"s3://bucket/path/to/warehouse/namespace/table",
122+
val ->
123+
Assertions.assertThat(val)
124+
.hasSize(1)
125+
.containsKey(PolarisStorageActions.READ)
126+
.extractingByKey(PolarisStorageActions.READ)
127+
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess))
128+
.hasEntrySatisfying(
129+
"file:///etc/passwd",
130+
val ->
131+
Assertions.assertThat(val)
132+
.hasSize(1)
133+
.containsKey(PolarisStorageActions.READ)
134+
.extractingByKey(PolarisStorageActions.READ)
135+
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess))
136+
.hasEntrySatisfying(
137+
"a/relative/subdirectory",
138+
val ->
139+
Assertions.assertThat(val)
140+
.hasSize(1)
141+
.containsKey(PolarisStorageActions.READ)
142+
.extractingByKey(PolarisStorageActions.READ)
143+
.returns(true, PolarisStorageIntegration.ValidationResult::isSuccess));
146144
}
147145

148146
@Test

0 commit comments

Comments
 (0)