Skip to content

Commit c12b122

Browse files
committed
refactor per-realm persistence retrieval
1 parent 7df701d commit c12b122

File tree

7 files changed

+126
-107
lines changed

7 files changed

+126
-107
lines changed

Diff for: components/persistence/api/src/main/java/org/apache/polaris/persistence/api/RealmPersistence.java

-67
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.polaris.persistence.api;
20+
21+
import jakarta.annotation.Nonnull;
22+
import jakarta.enterprise.context.ApplicationScoped;
23+
import org.apache.polaris.realms.id.RealmId;
24+
25+
/**
26+
* Builder factory to generate "realm-scoped" {@link Persistence} instances.
27+
*
28+
* <p>{@link RealmPersistenceFactory} instance is available as an {@link ApplicationScoped} bean.
29+
*/
30+
public interface RealmPersistenceFactory {
31+
/**
32+
* Return a new builder for per-realm persistence.
33+
*
34+
* <p>Builders must only be used once.
35+
*/
36+
RealmPersistenceBuilder newBuilder();
37+
38+
interface RealmPersistenceBuilder {
39+
RealmPersistenceBuilder realmId(@Nonnull RealmId realmId);
40+
41+
RealmPersistenceBuilder realmId(@Nonnull String realmId);
42+
43+
Persistence build();
44+
}
45+
}

Diff for: components/persistence/api/src/main/java/org/apache/polaris/persistence/api/StartupPersistence.java

+12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
import static java.lang.annotation.ElementType.TYPE;
2525
import static java.lang.annotation.RetentionPolicy.RUNTIME;
2626

27+
import jakarta.enterprise.context.ApplicationScoped;
2728
import jakarta.enterprise.util.AnnotationLiteral;
29+
import jakarta.inject.Inject;
2830
import jakarta.inject.Qualifier;
2931
import java.lang.annotation.Documented;
3032
import java.lang.annotation.Retention;
@@ -42,6 +44,16 @@
4244
*
4345
* <p>The qualified {@link Persistence} instance has <em>no</em> functional {@link IdGenerator}.
4446
*
47+
* <p>A system-realm {@link Persistence} instance can be {@link Inject @Inject}ed as an {@link
48+
* ApplicationScoped @ApplicationScoped} bean using
49+
*
50+
* {@snippet :
51+
* @ApplicationScoped
52+
* class MyBean {
53+
* @Inject @StartupPersistence Persistence startupPersistence; // @highlight
54+
* }
55+
* }
56+
*
4557
* @see SystemPersistence
4658
*/
4759
@Target({TYPE, METHOD, PARAMETER, FIELD})

Diff for: components/persistence/api/src/main/java/org/apache/polaris/persistence/api/SystemPersistence.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@
3535
import org.apache.polaris.nodes.api.NodeManagement;
3636
import org.apache.polaris.realms.id.RealmId;
3737

38-
// Spotless/Java doesn't really "like" Javadoc @snippet
39-
// spotless:off
4038
/**
4139
* Qualifier for system-level {@link Persistence} instance against the {@linkplain RealmId#SYSTEM
4240
* system realm} needed for realms management.
4341
*
4442
* <p>The qualified {@link Persistence} instance has a functional {@link IdGenerator}, enabled via a
4543
* valid {@linkplain NodeManagement#lease() node lease}.
4644
*
47-
* <p>A system-realm {@link Persistence} instance can be {@link Inject @Inject}ed as an {@link ApplicationScoped @ApplicationScoped} bean using
45+
* <p>A system-realm {@link Persistence} instance can be {@link Inject @Inject}ed as an {@link
46+
* ApplicationScoped @ApplicationScoped} bean using
4847
*
4948
* {@snippet :
5049
* @ApplicationScoped
@@ -55,7 +54,6 @@
5554
*
5655
* @see StartupPersistence
5756
*/
58-
// spotless:on
5957
@Target({TYPE, METHOD, PARAMETER, FIELD})
6058
@Retention(RUNTIME)
6159
@Documented

Diff for: components/persistence/bridge/src/main/java/org/apache/polaris/persistence/bridge/PersistenceMetaStoreManagerFactory.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import jakarta.annotation.PostConstruct;
2727
import jakarta.annotation.PreDestroy;
2828
import jakarta.enterprise.context.ApplicationScoped;
29-
import jakarta.enterprise.inject.Any;
30-
import jakarta.enterprise.inject.Instance;
3129
import jakarta.inject.Inject;
3230
import java.time.Clock;
3331
import java.time.Duration;
@@ -61,7 +59,7 @@
6159
import org.apache.polaris.core.storage.PolarisStorageIntegrationProvider;
6260
import org.apache.polaris.core.storage.cache.StorageCredentialCache;
6361
import org.apache.polaris.persistence.api.Persistence;
64-
import org.apache.polaris.persistence.api.RealmPersistence;
62+
import org.apache.polaris.persistence.api.RealmPersistenceFactory;
6563
import org.apache.polaris.realms.api.RealmDefinition;
6664
import org.apache.polaris.realms.api.RealmManagement;
6765
import org.apache.polaris.realms.id.RealmId;
@@ -78,7 +76,7 @@ class PersistenceMetaStoreManagerFactory implements MetaStoreManagerFactory {
7876
private final Map<String, RealmState> realmStateMap = new ConcurrentHashMap<>();
7977
private final RealmManagement realmManagement;
8078
private final Cancelable<Void> scheduled;
81-
private final Instance<Persistence> perRealmPersistence;
79+
private final RealmPersistenceFactory realmPersistenceFactory;
8280
private final PolarisDiagnostics diagServices;
8381
private final Privileges privileges;
8482
private final PolarisStorageIntegrationProvider storageIntegrationProvider;
@@ -90,7 +88,7 @@ class PersistenceMetaStoreManagerFactory implements MetaStoreManagerFactory {
9088
PersistenceMetaStoreManagerFactory(
9189
RealmManagement realmManagement,
9290
AsyncExec asyncExec,
93-
@Any Instance<Persistence> perRealmPersistence,
91+
RealmPersistenceFactory realmPersistenceFactory,
9492
PolarisDiagnostics diagServices,
9593
Privileges privileges,
9694
PolarisStorageIntegrationProvider storageIntegrationProvider,
@@ -100,7 +98,7 @@ class PersistenceMetaStoreManagerFactory implements MetaStoreManagerFactory {
10098
this.realmManagement = realmManagement;
10199
this.scheduled =
102100
asyncExec.schedulePeriodic(this::purgeNoLongerNeededRealmStructures, Duration.ofMinutes(5));
103-
this.perRealmPersistence = perRealmPersistence;
101+
this.realmPersistenceFactory = realmPersistenceFactory;
104102
this.diagServices = diagServices;
105103
this.privileges = privileges;
106104
this.storageIntegrationProvider = storageIntegrationProvider;
@@ -300,7 +298,7 @@ RealmState realmState(String realm) {
300298
}
301299

302300
private Persistence getRealmPersistence(RealmId realmId) {
303-
return perRealmPersistence.select(RealmPersistence.Literal.of(realmId.id())).get();
301+
return realmPersistenceFactory.newBuilder().realmId(realmId).build();
304302
}
305303

306304
BaseResult purgeRealm(String realm) {

Diff for: components/persistence/cdi/common/src/main/java/org/apache/polaris/persistence/cdi/persistence/ObservingRealmPersistence.java

+52-22
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,76 @@
1818
*/
1919
package org.apache.polaris.persistence.cdi.persistence;
2020

21+
import static com.google.common.base.Preconditions.checkState;
2122
import static org.apache.polaris.realms.id.RealmId.newRealmId;
2223

23-
import jakarta.enterprise.context.Dependent;
24-
import jakarta.enterprise.inject.spi.InjectionPoint;
24+
import jakarta.annotation.Nonnull;
25+
import jakarta.enterprise.context.ApplicationScoped;
2526
import jakarta.inject.Inject;
2627
import org.apache.polaris.ids.api.IdGenerator;
2728
import org.apache.polaris.ids.api.MonotonicClock;
2829
import org.apache.polaris.persistence.api.Persistence;
2930
import org.apache.polaris.persistence.api.PersistenceParams;
30-
import org.apache.polaris.persistence.api.RealmPersistence;
31+
import org.apache.polaris.persistence.api.RealmPersistenceFactory;
3132
import org.apache.polaris.persistence.api.backend.Backend;
33+
import org.apache.polaris.realms.id.RealmId;
3234

33-
@RealmPersistence
34-
@Dependent
35-
public class ObservingRealmPersistence extends ObservingPersistence {
36-
private final Persistence delegate;
35+
@ApplicationScoped
36+
class ObservingRealmPersistence implements RealmPersistenceFactory {
37+
private final PersistenceParams persistenceConfig;
38+
private final Backend backend;
39+
private final IdGenerator idGenerator;
40+
private final MonotonicClock monotonicClock;
41+
private final PersistenceDecorators persistenceDecorators;
3742

3843
@Inject
3944
ObservingRealmPersistence(
4045
PersistenceParams persistenceConfig,
4146
Backend backend,
4247
IdGenerator idGenerator,
4348
MonotonicClock monotonicClock,
44-
PersistenceDecorators persistenceDecorators,
45-
InjectionPoint injectionPoint) {
46-
for (var qualifier : injectionPoint.getQualifiers()) {
47-
if (qualifier instanceof RealmPersistence realmPersistence) {
48-
var id = realmPersistence.realmId();
49-
var realmId = newRealmId(id);
50-
var persistence =
51-
backend.newPersistence(persistenceConfig, realmId, monotonicClock, idGenerator);
52-
this.delegate = persistenceDecorators.decorate(persistence);
53-
return;
54-
}
55-
}
56-
throw new IllegalStateException("Not a @RealmPersistence injection point: " + injectionPoint);
49+
PersistenceDecorators persistenceDecorators) {
50+
this.persistenceConfig = persistenceConfig;
51+
this.backend = backend;
52+
this.idGenerator = idGenerator;
53+
this.monotonicClock = monotonicClock;
54+
this.persistenceDecorators = persistenceDecorators;
5755
}
5856

5957
@Override
60-
Persistence delegate() {
61-
return delegate;
58+
public RealmPersistenceBuilder newBuilder() {
59+
return new RealmPersistenceBuilder() {
60+
private RealmId realmId;
61+
private boolean consumed;
62+
63+
@Override
64+
public RealmPersistenceBuilder realmId(@Nonnull RealmId realmId) {
65+
checkState(this.realmId == null, "RealmPersistenceBuilder can only be used once");
66+
this.realmId = realmId;
67+
return this;
68+
}
69+
70+
@Override
71+
public RealmPersistenceBuilder realmId(@Nonnull String realmId) {
72+
return realmId(newRealmId(realmId));
73+
}
74+
75+
@Override
76+
public Persistence build() {
77+
checkState(!consumed, "RealmPersistenceBuilder can only be used once");
78+
checkState(realmId != null, "Must call RealmPersistenceBuilder.setRealmId() before .build");
79+
consumed = true;
80+
81+
var persistence =
82+
backend.newPersistence(persistenceConfig, realmId, monotonicClock, idGenerator);
83+
var notObserved = persistenceDecorators.decorate(persistence);
84+
return new ObservingPersistence() {
85+
@Override
86+
Persistence delegate() {
87+
return notObserved;
88+
}
89+
};
90+
}
91+
};
6292
}
6393
}

Diff for: components/persistence/cdi/weld/src/test/java/org/apache/polaris/persistence/weld/TestProviders.java

+10-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import static org.apache.polaris.realms.id.RealmId.newRealmId;
2222

2323
import org.apache.polaris.persistence.api.Persistence;
24-
import org.apache.polaris.persistence.api.RealmPersistence;
24+
import org.apache.polaris.persistence.api.RealmPersistenceFactory;
2525
import org.apache.polaris.persistence.api.SystemPersistence;
2626
import org.apache.polaris.persistence.api.backend.Backend;
2727
import org.apache.polaris.realms.api.RealmManagement;
@@ -56,16 +56,19 @@ public void checkProviders() {
5656
var requestScopedRunner = weld.select(RequestScopedRunner.class).get();
5757
requestScopedRunner.runWithRequestContext(
5858
() -> {
59-
var persistence =
60-
weld.select(Persistence.class, RealmPersistence.Literal.of("my-realm")).get();
61-
soft.assertThat(persistence.realmId()).isEqualTo(newRealmId("my-realm"));
59+
var builder1 = weld.select(RealmPersistenceFactory.class).get();
60+
var persistence1 = builder1.newBuilder().realmId(newRealmId("my-realm")).build();
61+
soft.assertThat(persistence1.realmId()).isEqualTo(newRealmId("my-realm"));
6262

63-
var persistence2 =
64-
weld.select(Persistence.class, RealmPersistence.Literal.of("other-realm")).get();
63+
var builder2 = weld.select(RealmPersistenceFactory.class).get();
64+
var persistence2 = builder2.newBuilder().realmId(newRealmId("other-realm")).build();
6565
soft.assertThat(persistence2.realmId()).isEqualTo(newRealmId("other-realm"));
6666

6767
// Trigger IdGenerator "activation"
68-
persistence.generateId();
68+
persistence1.generateId();
69+
70+
// Trigger IdGenerator "activation"
71+
persistence2.generateId();
6972
});
7073
}
7174
}

0 commit comments

Comments
 (0)