[SERVER-60764] Change stream getMore still reports non-zero cursor ID in response including invalidate event Created: 15/Oct/21 Updated: 06/Dec/22 |
|
| Status: | Backlog |
| Project: | Core Server |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Jeremy Mikola | Assignee: | Backlog - Query Execution |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | change-streams-improvements | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Assigned Teams: |
Query Execution
|
| Operating System: | ALL |
| Participants: |
| Description |
| Comments |
| Comment by Jeremy Mikola [ 22/Oct/21 ] |
I'm not aware of any drivers introspecting documents returned by a change stream. At the very least, that doesn't seem to be discussed in the specification. I was assuming that an application would stop iterating the change stream after an "invalidate" event. Applications don't have any direct knowledge of when a getMore might be issued. Drivers do so as needed during iteration. If an application simply stops iterating after encountering an "invalidate" event, I expect they might destroy the change stream object and then a driver might issue a killCursors command in an attempt to clean up the cursor (presumed alive because the last seen ID was non-zero). That is generally how drivers handle cursor cleanup for other query cursors. Granted, this isn't really specified anywhere to my knowledge, as we don't have a dedicated cursor spec (Find, getMore and killCursors commands may be the closest thing, but it doesn't really discuss cleanup). |
| Comment by Bernard Gorman [ 22/Oct/21 ] |
Do the drivers introspect the contents of each change stream message to check whether it's an invalidate? Or did you mean that the user application might stop issuing getMore when they see an invalidate?
Change stream cursors are treated just like any other cursor, so the periodic reaper would clean them up once the session expires. |
| Comment by Kyle Suarez [ 22/Oct/21 ] |
|
Thanks for the further context jmikola, we're going to keep this ticket open for another round of discussion at the next triage. bernard.gorman, do you see this scenario as a plausible risk: a user initiates a change stream, gets an invalidate, and then never issues another getMore, thereby "leaking" cursor resources that will accumulate and never be cleaned up? Or do you think that the periodic cursor reaper would clean up those exhausted change stream cursors? |
| Comment by Jeremy Mikola [ 22/Oct/21 ] |
|
kyle.suarez: thanks for confirming. I don't expect drivers would have any reason to issue another getMore after an invalidate event, so I imagine the cursor would either remain open until mongos decides to kill it or the change stream object in the driver gets destroyed and a killCursors is executed (since the last seen cursor ID would have been non-zero). I suppose we can just punt on this for now and revisit if this proves problematic any any driver down the line. FWIW, The particular PHPLIB test that prompted this ticket was just testing that our driver frees internal resources when the cursor is closed (and we were using an "invalidate" even to trigger that). In this case, the cursor remains open so we're just skipping the test on mongos 5.1+. |
| Comment by Kyle Suarez [ 22/Oct/21 ] |
|
jmikola, this is a change to the invalidation mechanism that came in from the $changeStream optimization project. As of 5.1, we do not necessarily close the cursor on the same getMore that delivered the invalidate event. The actual cursor closing should occur on the subsequent getMore. Unless this is causing an actual problem, we are inclined to keep this behavior. CC bernard.gorman |