Delete PIT changes#3401
Conversation
20520b2 to
0b44292
Compare
|
❌ Gradle Check failure 20520b22af5cdee3a7d8daad50ef088a501eca5f |
|
❌ Gradle Check failure 0b442923704bb5e32c317ca97777f9fa677f77f3 |
0b44292 to
9f382e7
Compare
|
❌ Gradle Check failure 9f382e7e2ec70f681a76f642e8f697c955bbd173 |
9f382e7 to
53ee52c
Compare
|
✅ Gradle Check success 53ee52c3e77d01232ecd2a021cc83c87e21cea6b |
53ee52c to
8229655
Compare
|
❌ Gradle Check failure 8229655db3ae8ccacbf564a691aaa33899f5822d |
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
8229655 to
25cc2b1
Compare
|
Regarding the API, #1147 describes |
Since PIT ID is quite large, and we are supporting deletion of list of pit ids, we made this change to support only list of pit ids in body. Similar APIs like clear scroll also forms a similar pattern. ( though it supports passing id as part of params, now its deprecated ) Behavior: Invalid IDs: |
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
| highLevelClient()::deletePit, | ||
| highLevelClient()::deletePitAsync | ||
| ); | ||
| assertTrue(deletePitResponse.isSucceeded()); |
There was a problem hiding this comment.
let's verify that searchservice map of activeReader is empty on each node
There was a problem hiding this comment.
we can use 'list all pits api' to verify active pits as part of 'list all pits' pr.
eirsep
left a comment
There was a problem hiding this comment.
Thanks for making this changes Bharat.
I have requested some
- changes in Delete PIT logic
- suggested an optimization for delete PIt contexts to reduce transport calls
Apart from that have a few minor comments.
Some points to ponder over:
- should we rename from delete PIT to clear PIT. that would in keeping with how scroll is named.
- we could avoid using the term reader context in documentation and rest layer as it might only confuse people. That's a transport layer or service layer construct. As a user I will be only worried if PIT is deleted or not. I wouldn't be wanting to know fi contexts are cleared or not. Just if my operation succeeded.
Will review tests after this batch of comments are addressed
| "delete_pit":{ | ||
| "documentation":{ | ||
| "url":"https://opensearch.org/docs/latest/opensearch/rest-api/point_in_time/", | ||
| "description":"Deletes one or more point in time contexts." |
There was a problem hiding this comment.
Can be worded differently. Maybe something more on the lines of "Deletes all point-in-time whose id is passed"?
Deletes one or more point in time contexts sounds confusing
User wants an api to delete a PIT. Contexts might be confusing.
| "delete_all_pits":{ | ||
| "documentation":{ | ||
| "url":"https://opensearch.org/docs/latest/opensearch/rest-api/point_in_time/", | ||
| "description":"Deletes all active point in time contexts." |
There was a problem hiding this comment.
context is used as part of scroll as well - 'Explicitly clears the search context for a scroll.'
i think just saying point of time will be confusing, we can take a second opinion here.
| import org.opensearch.action.ActionType; | ||
|
|
||
| /** | ||
| * Action type for deleting PIT reader contexts |
There was a problem hiding this comment.
same as above. let's talk about deleting point-in-time's
the fact that PIT contexts are deleted could be an abstraction to the rest and transport layer.
This description seems to hint we can deleted contexts selectively.
There was a problem hiding this comment.
let's talk about deleting point-in-time's
I would consider using "point-in-time search" as the noun form to disambiguate from future point-in-times (e.g. point-in-time restore). It also aligns with the _search/point_in_time resource path.
server/src/main/java/org/opensearch/action/search/DeletePitResponse.java
Outdated
Show resolved
Hide resolved
| pitIds = Arrays.asList(in.readStringArray()); | ||
| } | ||
|
|
||
| public DeletePitRequest(String... pitIds) { |
There was a problem hiding this comment.
public DeletePitRequest(List<String> pitIds) should suffice right?
There was a problem hiding this comment.
As we use "_all" , this will be needed.
| import java.util.List; | ||
|
|
||
| /** | ||
| * Transport action for deleting pit reader context - supports deleting list and all pit contexts |
There was a problem hiding this comment.
we are deleting a point in time. Let's not say "deleting pit reader context".
Supports deletion of a list of PIT by their Id's or all PITs
| /** | ||
| * Helper class for common search functions | ||
| */ | ||
| public class SearchUtils { |
There was a problem hiding this comment.
still not sure why deletePitContexts is not present in PITController and why CreatePitController is not just called PitController or PitService catering to all things PIT
There was a problem hiding this comment.
Not a big fan of Utils with static method, any reason why we can't have them encapsulated in a service
There was a problem hiding this comment.
Made the change to make it a separate service. One challenge with just putting everything in create pit controller is that there are too many dependencies and integ tests fail with inject errors ( sometimes even on the classes which are existing ). So created a new lightweight service file which will have the common methods. Create pit controller will continue to cater create pit specific methods.
| @Override | ||
| protected void doExecute(Task task, DeletePitRequest request, ActionListener<DeletePitResponse> listener) { | ||
| List<String> pitIds = request.getPitIds(); | ||
| if (pitIds.size() == 1 && "_all".equals(pitIds.get(0))) { |
There was a problem hiding this comment.
what happens if some one passes PIT Id1, PIT Id2, _all i.e. size!=1 but contains _all ?
There was a problem hiding this comment.
we will throw exception when '_all' is passed as part of body as its not a valid encoded pit id. Current implementation accepts '_all' as part of params as its in line with other similar impl such as clear scrolls.
| listener.onResponse(new DeletePitResponse(false)); | ||
| } | ||
| }, e -> { | ||
| logger.debug("Delete PITs failed ", e); |
server/src/main/java/org/opensearch/action/search/TransportDeletePitAction.java
Show resolved
Hide resolved
|
re: Behavior:
As an example, take a look at the documentation for the DynamoDB BatchWriteItem API. It clearly defines how partial success is handled and cases where the entire batch will be rejected. We'll want to think through all those same cases here. |
| } | ||
|
|
||
| public DeletePitRequest(List<String> pitIds) { | ||
| if (pitIds != null) { |
There was a problem hiding this comment.
Is null really valid input here? I'd consider just letting this fail with an NPE (or throwing an IllegalArgumentException).
| } | ||
| } | ||
|
|
||
| public void addPitId(String pitId) { |
There was a problem hiding this comment.
Do you need to expose this as a public method? I'd consider simplifying this class by:
- remove this method
- make
pitIdsfinal, and assign it to an empty list in the default constructor case - in
fromXContentclearpidIdsand then add to it directly instead of calling this method
|
|
||
| public DeletePitRequest(List<String> pitIds) { | ||
| if (pitIds != null) { | ||
| this.pitIds = pitIds; |
There was a problem hiding this comment.
Should we make a defensive copy of the list in this case? This is vulnerable to the action-at-a-distance problem if the caller later modifies the list that was passed here.
server/src/main/java/org/opensearch/rest/action/search/RestDeletePitAction.java
Outdated
Show resolved
Hide resolved
|
❌ Gradle Check failure 2219aebc9219391ad9f38b80a56560b04b8f56a0 |
9a4f707 to
0ffc780
Compare
|
❌ Gradle Check failure 0ffc780b8e21378b4fe470bc4ea44f8e31c33b77 |
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
0ffc780 to
e482053
Compare
|
❌ Gradle Check failure 36dcd86b4348ea030271053abe31388f7418f439 |
|
❌ Gradle Check failure a569b07903830a8e764d9a40fa61734f79f34d8e |
a569b07 to
f9db591
Compare
|
❌ Gradle Check failure f9db591aec235045f91c909589e1bf069c83b64d |
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
f9db591 to
93f8db7
Compare
|
❌ Gradle Check failure 2e4c56c4118d1d1c902a2bce6cb440b4ccb1fd65 |
2e4c56c to
758aaac
Compare
|
❌ Gradle Check failure 758aaaca96d6507390904a8648c31840df1bcae4 |
758aaac to
2a25a8a
Compare
|
❌ Gradle Check failure 2a25a8a099c7a42131f6146ab0ebffe8d26abbaa |
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
2a25a8a to
d4ecca2
Compare
| // and create pit request keep alive is less than that, keep alive is set to 1 second, (max of 2 keep alives) | ||
| // so reader context will clear up after 1 second | ||
| Thread.sleep(1000); | ||
| Thread.sleep(1200); |
There was a problem hiding this comment.
Thread.sleep() calls make a test flaky. As everything depends on the state of the server at the time tests are running and CPU context switch that is happening, the code that we expect to finish in 1200ms may take more than that. Is there any way to provide listener?
| if (!logger.isDebugEnabled()) return; | ||
| for (DeletePitInfo deletePitInfo : response.getDeletePitResults()) { | ||
| if (!deletePitInfo.isSucceeded()) { | ||
| logger.debug(() -> new ParameterizedMessage("Failed to delete PIT ID {}", deletePitInfo.getPitId())); |
There was a problem hiding this comment.
Why debug, should this be warn instead?. Lets have a single log line with concatenated ids?
| /** | ||
| * This will be true if PIT reader contexts are deleted ond also if contexts are not found. | ||
| */ | ||
| private final boolean succeeded; |
| @Override | ||
| public ActionRequestValidationException validate() { | ||
| ActionRequestValidationException validationException = null; | ||
| if (pitIds == null || pitIds.isEmpty()) { |
There was a problem hiding this comment.
collection utils works on arrays , since this is list, keeping the checks same
| /** | ||
| * Helper class for common search functions | ||
| */ | ||
| public class SearchUtils { |
There was a problem hiding this comment.
Not a big fan of Utils with static method, any reason why we can't have them encapsulated in a service
| private void deletePits(ActionListener<DeletePitResponse> listener, DeletePitRequest request) { | ||
| Map<String, List<PitSearchContextIdForNode>> nodeToContextsMap = new HashMap<>(); | ||
| for (String pitId : request.getPitIds()) { | ||
| SearchContextId contextId = SearchContextId.decode(namedWriteableRegistry, pitId); | ||
| for (SearchContextIdForNode contextIdForNode : contextId.shards().values()) { | ||
| PitSearchContextIdForNode pitSearchContext = new PitSearchContextIdForNode(pitId, contextIdForNode); | ||
| List<PitSearchContextIdForNode> contexts = nodeToContextsMap.getOrDefault(contextIdForNode.getNode(), new ArrayList<>()); | ||
| contexts.add(pitSearchContext); | ||
| nodeToContextsMap.put(contextIdForNode.getNode(), contexts); | ||
| } | ||
| } | ||
| SearchUtils.deletePitContexts(nodeToContextsMap, listener, clusterService.state(), searchTransportService); | ||
| } | ||
|
|
There was a problem hiding this comment.
Lets move this to a Service
There was a problem hiding this comment.
Made the change to make it a separate service. One challenge with just putting everything in create pit controller is that there are too many dependencies and integ tests fail with inject errors ( sometimes even on the classes which are existing ). So created a new lightweight service file which will have the common methods. Create pit controller will continue to cater create pit specific methods.
5d62ef1 to
17419e8
Compare
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
17419e8 to
beacfc1
Compare
* Delete PIT changes Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
Description
This PR contains Delete PIT API changes. User can use '_all' to delete all pit contexts, or pass list of pit IDs as part of body to delete PITs.
Create PIT PR : #2745
Request:
Response:
Issues Resolved
#1147
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.