Repository navigation
REST: Add freshness-aware loading to RESTTableOperations - #18188
raunaqmorarka wants to merge 1 commit into
Conversation
9098d9d to
52e3d86
Compare
|
Isn't this solving the same as #17832? |
Different problem. #17832 restores the lazy snapshots supplier and the |
gaborkaszab
left a comment
There was a problem hiding this comment.
Hi @raunaqmorarka ,
I'm trying to refresh my memories since I was involved with this. Couple of questions:
- Isn't the ETag redundant now: There is one kept in the table cache and one in ops. Also, they can get out of sync, right?
- In terms of the table cache, this is an in-place operation, right? Executing ops.refresh() also refreshes the TableMetadata in the table cache through ops, right?
- I recall one complication might be that credentials and configs are also returned by the get request not just table metadata and ETag. Since these are incorporated into FileIO and RESTClient, they are not refreshed, right? Since the age of the table in the cache is not affected here, probably we are fine with this, just want to double check.
cc @nastra @danielcweeks Might be a useful addition. I always dragged this as a potential future addition to freshness-aware loading. Would you mind also taking a look?
|
52e3d86 to
d230af1
Compare
gaborkaszab
left a comment
There was a problem hiding this comment.
Thanks!
I did a pass on the non-test part. Will cover tests later.
d230af1 to
61d65c0
Compare
adaac70 to
9e5fd3c
Compare
gaborkaszab
left a comment
There was a problem hiding this comment.
I went another round, this time also checked tests
| BaseTable table = (BaseTable) restCatalog.loadTable(TABLE); | ||
| TableMetadata loaded = table.operations().current(); | ||
|
|
||
| // the adapter hashes query params into the ETag, so the first refresh gets a full response |
There was a problem hiding this comment.
What are the params used by the catalog adapter that aren't the same used by ops?
Is this deviation of params general and expected between the catalog client and ops? Because if we expect this to be the case, then there isn't much point of constructing ops passing an ETag from RESTSessionCatalog, because anyway the first refresh() is expected to be a full load.
There was a problem hiding this comment.
Good question. The difference was the snapshots param. loadTable sends snapshots=all, while refresh() omits it. The test adapter hashed those params into the ETag, so the two never matched. Both requests return the same content, so I updated the adapter to treat a missing snapshots as all. The first refresh after loadTable now gets a 304. Only snapshot-loading-mode=refs still does a full first refresh, since its content differs.
| table.refresh(); | ||
|
|
||
| // refresh() also runs on stale reads and commit retries, and sends no snapshots parameter | ||
| String eTag = |
There was a problem hiding this comment.
Whenever we decide to send a new query param, this test will fail on the header verification because of how we calculate the ETag.
Also, the comment above is pretty misleading together with this new code because the comment says not sending snapshots param, but we anyway use it right below the comment. (I know why it's needed, but still might be misleading for the reader)
Do you think you can figure out a more flexible verification? For instance ETag content is not that relevant for this test, we still make changes so that we can make the rigid way of our message verification pass. Would be nice to have a way saying "I'm not interested verifying the outgoing headers" or "I'm just verifying the name of the outgoing headers but not their values"
There was a problem hiding this comment.
Agreed, that was brittle. I restored this test to how it is on main. I also added a containsHeaders overload to RequestMatcher that checks the query params and only the headers the test names. The test no longer depends on the ETag.
| assertThat(ops.refresh()).isSameAs(loaded); | ||
|
|
||
| // the commit response carries an ETag, but the refresh response after it does not | ||
| table.updateProperties().set("key", "value").commit(); |
There was a problem hiding this comment.
I'm not entirely sure what coverage we add with this test. The step with the commit() probably is not needed. I guess to point is to see what happens when the server sends no ETag. Then the plan for this test might be:
- Construct server not to send ETag
- Create and load table through catalog
- do a refresh()
- Verify refresh() didn't send and didn't receive an ETag
- Verify that the table metadata is as we expect
There was a problem hiding this comment.
Thanks for the outline, I followed it. The test is now refreshWithoutETag, with no commit step. It checks that refresh sends no If-None-Match and keeps the loaded metadata.
9e5fd3c to
8c89c36
Compare
8c89c36 to
21f10ed
Compare
Reuse the ETag from loadTable and commit responses so an unchanged table refreshes with a 304 instead of a full metadata body.
21f10ed to
8e5921e
Compare
RESTTableOperations.refresh()always issued an unconditionalGETand parsed the full metadata body, even though the same catalog already does freshness-aware loading forloadTablethroughRESTTableCache. Servers that honourIf-None-Match(for example Polaris) answer with304 Not Modified, so a refresh of an unchanged table only needs a header round trip.RESTTableOperationsnow takes theETagof the load response through its constructor, updates it from every successful refresh and commit response, sends it asIf-None-Matchonrefresh(), and returnscurrent()on a304without parsing a body. When the server sends noETag, refresh behaves as before. TheRESTTableCacheentry is left untouched, since the ETag there pairs with the metadata captured by the cached supplier.RESTSessionCatalog.newTableOpsgets a new overload with aneTagparameter. The existing one is deprecated and delegates withnull.Note:
commit()now uses theRESTClient.postoverload that returns response headers.BaseHTTPClientsupports it. A customRESTClientrelying only on the interface default would need to implement it.Tests in
TestFreshnessAwareLoadingcover a304on refresh afterloadTable, a changed table refreshing fully and adopting the newETag, a commitETagbeing reused, and servers that send noETag. The test adapter now treats a missingsnapshotsparam asallwhen computing theETag, as the spec says.