-
Notifications
You must be signed in to change notification settings - Fork 305
Add Events for Iceberg REST APIs #2480
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
Add Events for Iceberg REST APIs #2480
Conversation
...java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
Show resolved
Hide resolved
runtime/service/src/main/java/org/apache/polaris/service/events/PolarisEventListener.java
Outdated
Show resolved
Hide resolved
runtime/service/src/main/java/org/apache/polaris/service/events/IcebergRestCatalogEvents.java
Show resolved
Hide resolved
@@ -777,8 +777,8 @@ public Response sendNotification( | |||
securityContext, | |||
prefix, | |||
catalog -> { | |||
catalog.sendNotification(tableIdentifier, notificationRequest); | |||
return Response.status(Response.Status.NO_CONTENT).build(); | |||
boolean notificationSent = catalog.sendNotification(tableIdentifier, notificationRequest); |
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.
Unrelated change?
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.
No, at the moment we do not get whether the notification was sent successfully or not. So I've introduced this change so that we can surface that information. (There are code paths possible where the notificationSent can be false but the call still returns without error).
But to be fair, I'm not sure what notificationSent really helps with. So please let me know what you think.
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.
In this case this requires a modification of the OpenAPI spec. See my related comment:
https://github.com/apache/polaris/pull/2482/files#r2318079257
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.
Also: status(Response.Status.NO_CONTENT).entity(notificationSent)
is contradictory: the response for a 204 status should not contain any body:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/204
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.
Needing an OpenAPI spec change and ML thread regarding this is a fair ask. Let me revert this out for now - maybe we can proceed without the result of the sendNotification
call first and then in parallel, I can start the ML thread for this.
Once we reach a consensus as a community, then we can go back and resolve the TODO.
...java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
Outdated
Show resolved
Hide resolved
...java/org/apache/polaris/service/catalog/iceberg/IcebergRestCatalogEventServiceDelegator.java
Outdated
Show resolved
Hide resolved
...rg/apache/polaris/service/catalog/iceberg/IcebergRestConfigurationEventServiceDelegator.java
Show resolved
Hide resolved
@@ -777,8 +777,8 @@ public Response sendNotification( | |||
securityContext, | |||
prefix, | |||
catalog -> { | |||
catalog.sendNotification(tableIdentifier, notificationRequest); | |||
return Response.status(Response.Status.NO_CONTENT).build(); | |||
boolean notificationSent = catalog.sendNotification(tableIdentifier, notificationRequest); |
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.
In this case this requires a modification of the OpenAPI spec. See my related comment:
https://github.com/apache/polaris/pull/2482/files#r2318079257
} | ||
|
||
private String getCatalogFromPrefix(String prefix, RealmContext realmContext) { | ||
return prefixParser.prefixToCatalogName(realmContext, prefix); |
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.
nit: inline.
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.
Changed.
runtime/service/src/main/java/org/apache/polaris/service/events/PolarisEventListener.java
Outdated
Show resolved
Hide resolved
import org.apache.polaris.service.events.AfterAttemptTaskEvent; | ||
import org.apache.polaris.service.events.BeforeAttemptTaskEvent; | ||
import org.apache.polaris.service.events.BeforeLimitRequestRateEvent; | ||
import org.apache.polaris.service.events.IcebergRestCatalogEvents; | ||
|
||
public abstract class PolarisPersistenceEventListener extends PolarisEventListener { | ||
|
||
// TODO: Ensure all events (except RateLimiter ones) call `addToBuffer` |
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.
Is the plan to tackle this later?
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.
BTW the comment is outdated:
// TODO: Ensure all events (except RateLimiter ones) call `addToBuffer` | |
// TODO: Ensure all events (except RateLimiter ones) call `processEvent` |
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.
Yes, the plan is to tackle in a separate PR - I would like to keep the focus of this PR on the events itself and the transformations will go in a further PR.
/** | ||
* Table Committed Events are already instrumented at a more granular level than the API itself. | ||
*/ |
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.
how and why , are it we tracking it per table ?? this seems like it doesn't follow the pattern
-- BeforEvent
-- do Something
-- After Event
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 TableCommittedEvent was previously merged and there are no changes to it as part of this PR. The idea is that all table commits that happened as part of the same Polaris API call (through the commitTransaction
API) will already be tied together through the same request ID and so a new Event for this API is not explicitly required.
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.
what is the on before and on after for this, would looks though ?
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.
On second thought, you are correct - the Table Committed events are triggered even for non-transactional events. Let me add this.
return delegate.createTable( | ||
prefix, namespace, createTableRequest, accessDelegationMode, realmContext, securityContext); | ||
String catalogName = prefixParser.prefixToCatalogName(realmContext, prefix); | ||
if (!createTableRequest.stageCreate()) { |
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.
why don't we emit anything for StageCreate ?
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.
My understanding is that when a table is stageCreated, then no actual table is made - and therefore there is no new (meta)data created. In that case, I don't think it makes sense to emit a AfterCreateTableEvent
if a table was not truly created.
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.
But we are not emitting a onBeforeCreateTable too ? never the less what happens when i stage create and then do /commit
?
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 did not realize this - have removed the flag around BeforeCreateTableEvent. Consumers of this event should see this is for a StageCreate
table and surface that information accordingly.
return delegate.listViews( | ||
prefix, namespace, pageToken, pageSize, realmContext, securityContext); | ||
String catalogName = prefixParser.prefixToCatalogName(realmContext, prefix); | ||
polarisEventListener.onBeforeListViews(new BeforeListViewsEvent(catalogName, namespace)); |
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.
are the nested namespace encoded by '%1F' in the final even ?
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.
This is a good callout - we should switch this to use Namespace
objects instead. Doing in the next revision.
return delegate.createTable( | ||
prefix, namespace, createTableRequest, accessDelegationMode, realmContext, securityContext); | ||
String catalogName = prefixParser.prefixToCatalogName(realmContext, prefix); | ||
if (!createTableRequest.stageCreate()) { |
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.
But we are not emitting a onBeforeCreateTable too ? never the less what happens when i stage create and then do /commit
?
/** | ||
* Table Committed Events are already instrumented at a more granular level than the API itself. | ||
*/ |
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.
what is the on before and on after for this, would looks though ?
polarisEventListener.onBeforeRenameView( | ||
new BeforeRenameViewEvent(catalogName, renameTableRequest)); |
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.
no namespace here ? wouldn't it be nice to know namespace before after ?
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.
renameTableRequest
has the before and after table identifiers, where an event listener can access that the namespace information.
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 code changes LGTM from IRC POV ! Thanks @adnanhemani
Orthogonal to the PR - I am a bit concerned with seeing the read events being instrumented too, as my understanding was we wanted write API's only (mirroring event's API), this increases load on persistence and the application in general since we use the same JDBC connection pool and we do batching in memory and reads can shoot these up.
My recommendation as part of follow-ups would be :
- Mark this feature experimental, when ever the E2E machinery is ready
- run benchmarks with polaris benchmarking tool (whats could be the potential degradation) to identify bottelnecks.
Thanks @singhpk234 - makes sense. When we finish the E2E mechanism, we will surely either run the benchmark or mark as experimental. |
This PR adds the Events instrumentation for the Iceberg REST Service APIs, surrounding the default delegated call to the business logic APIs.