-
Notifications
You must be signed in to change notification settings - Fork 328
Request-scoped PolarisMetaStoreManager #2555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
9738d71 to
c014ca0
Compare
c1b2564 to
4511b5e
Compare
ebc2443 to
e9f1079
Compare
e9f1079 to
88db62e
Compare
88db62e to
d1dda2e
Compare
dimas-b
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
partial review
| public PolarisMetaStoreManager createMetaStoreManager( | ||
| RealmContext realmContext, @Nullable RealmConfig realmConfig) { | ||
| if (realmConfig == null) { | ||
| realmConfig = new RealmConfigImpl(configurationStore, realmContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the realmConfig parameter at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as we can build it ourselves its not strictly needed no, but many call sites already have it and can pass it in.
i am fine to remove the parameter if we think thats better overall.
| public class InMemoryEntityCache implements EntityCache { | ||
|
|
||
| private final PolarisDiagnostics diagnostics; | ||
| private final PolarisMetaStoreManager polarisMetaStoreManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose InMemoryEntityCache must use a PolarisMetaStoreManager from the same realm. If PolarisMetaStoreManager is a method parameter it become not so obvious. WDYT about keeping this field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
afaict we cant keep this field as PolarisMetaStoreManager now represents a (per-request) persistence session where-as InMemoryEntityCache is supposed to be a shared cache within a realm.
the question is with what persistence session do we want to populate the cache?
a shared one or the request-scoped one given by the callers as "use this for loading in case cache entry is missing" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the cache answers from memory, the per-request persistence session is irrelevant. So the caller of the lookup method(s) does not know whether the current persistence session was / will be used. Some values returned from the cache might have been loaded via a different session.
The "reload if necessary" checks are based on local entity data and do not appear to take the "session" into account.
With that in mind, I think it would be preferable to resolve this ambiguity and always load from a separate session (one per InMemoryEntityCache instance or created on demand).
@dennishuo : WDYT?
d1dda2e to
37696b7
Compare
|
rebased after trivial a conflict and also to adjust to |
faf5210 to
0eb0f2b
Compare
0eb0f2b to
1a1ddb5
Compare
dimas-b
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general direction of this PR LGTM (but I have not reviewed all changes yet). Dealing with PolarisMetaStoreManager instances as per-request objects makes sense to me (irrespective of the runtime framework in use). The metastore factory controls the creation of PolarisMetaStoreManager objects and associating them with request-specific data.
@dennishuo @collado-mike WDYT?
|
|
||
| JWTBroker(PolarisMetaStoreManager metaStoreManager, int maxTokenGenerationInSeconds) { | ||
| this.metaStoreManager = metaStoreManager; | ||
| JWTBroker(int maxTokenGenerationInSeconds) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TokenBroker is already request-scoped, why not rely on the constructor to have the correct metaStoreManager for the current request?
| public interface TokenBrokerFactory extends Function<RealmContext, TokenBroker> {} | ||
| public interface TokenBrokerFactory { | ||
|
|
||
| TokenBroker newTokenBroker(RealmContext realmContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: move this into a separate PR maybe? I think it's a valuable refactoring and independent of the request scope discussions.
| public class InMemoryEntityCache implements EntityCache { | ||
|
|
||
| private final PolarisDiagnostics diagnostics; | ||
| private final PolarisMetaStoreManager polarisMetaStoreManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the cache answers from memory, the per-request persistence session is irrelevant. So the caller of the lookup method(s) does not know whether the current persistence session was / will be used. Some values returned from the cache might have been loaded via a different session.
The "reload if necessary" checks are based on local entity data and do not appear to take the "session" into account.
With that in mind, I think it would be preferable to resolve this ambiguity and always load from a separate session (one per InMemoryEntityCache instance or created on demand).
@dennishuo : WDYT?
1a1ddb5 to
3d96588
Compare
the `PolarisMetaStoreManager` interface methods all take a `PolarisCallContext` parameter because they need access to `PolarisCallContext.getMetaStore` aka the persistence session. also occasionally the `RealmContext` and `RealmConfig` is needed. this means `PolarisMetaStoreManager` is only usable within a request-scope. `MetaStoreManagerFactory.getOrCreateMetaStoreManager` impls suggests that there needs to be one shared `PolarisMetaStoreManager` instance per realm. however if we look at the `PolarisMetaStoreManager` impls (`AtomicOperationMetaStoreManager` and `TransactionalMetaStoreManagerImpl`) we can see that they dont have any state themselves, the fields only reference application-scoped collaborators. those 2 observations combined mean that in order to reduce the dependency on `PolarisCallContext` the `PolarisMetaStoreManager` has to become request-scoped. note that if custom implementations would need any state sharing for a realm, they are still free to do so in their custom `MetaStoreManagerFactory` implementations, as they can initialize the request-scoped `PolarisMetaStoreManager` with whatever data they need. when `PolarisMetaStoreManager` is request-scoped the `getOrCreateSession` method also becomes a private implementation detail of the `MetaStoreManagerFactory`. the `EntityCache` / `InMemoryEntityCache` however can no longer operate on a single `PolarisMetaStoreManager` and the one from the request needs to be passed as a parameter in all the methods now.
this avoids `TokenBrokerFactory` impls having to call `MetaStoreManagerFactory.createMetaStoreManager`
3d96588 to
345212f
Compare
|
Looks like this PR needs a rebase |
see ML discussion:
https://lists.apache.org/thread/ot19px6t0w808pp994rrc8kk7186dfxm
the
PolarisMetaStoreManagerinterface methods all take aPolarisCallContextparameterbecause they need access to
PolarisCallContext.getMetaStoreaka the persistence session.also occasionally the
RealmContextandRealmConfigis needed.this means
PolarisMetaStoreManageris only usable within a request-scope.MetaStoreManagerFactory.getOrCreateMetaStoreManagerimpls suggests that there needs tobe one shared
PolarisMetaStoreManagerinstance per realm.however if we look at the
PolarisMetaStoreManagerimpls (AtomicOperationMetaStoreManagerand
TransactionalMetaStoreManagerImpl) we can see that they dont have any state themselves, the fields only reference application-scoped instances.Those 2 observations combined mean that we can make the
PolarisMetaStoreManagerrequest-scoped and then thePolarisCallContextparameter can be removed from all the methods without losing any functionality/flexibility.note that if custom implementations would need any state sharing for a realm, they are still free to do so in their custom
MetaStoreManagerFactoryimplementations, as they caninitialize the custom request-scoped
PolarisMetaStoreManagerinstance with whatever (shared) data they need.when
PolarisMetaStoreManageris request-scoped thegetOrCreateSessionmethod also becomes a private implementation detail of theMetaStoreManagerFactory.