[ 
https://issues.apache.org/jira/browse/IGNITE-26927?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Pavel Pereslegin updated IGNITE-26927:
--------------------------------------
    Description: 
Consider the following example:
{code:java}
  var rs = sql.executeAsync(null, "SELECT...").join();

  rs.fetchNextPage(); // SQL_CURSOR_NEXT_PAGE
  rs.close(); // SQL_CURSOR_CLOSE
{code}
In the above case, the {{SQL_CURSOR_CLOSE}} request is sent to the server 
before the result of the {{SQL_CURSOR_NEXT_PAGE}} request is received.

The {{SQL_CURSOR_NEXT_PAGE}} request handler, if the last requested page 
removes the client resource (see {{ClientSqlCursorNextPageRequest.process()}})
The {{SQL_CURSOR_CLOSE}} request handler may fail with the error "Failed to 
find resource with id" if {{SQL_CURSOR_NEXT_PAGE}} has already removed this 
resource.

The problem is even more important for the synchronous API due to optimization, 
which always requests the next data page in the background.

Reproducer:
{code:java}
  @Test
  void resourceNotFoundOnClose() {
      IgniteSql sql = client().sql();

      Statement stmt = sql.statementBuilder()
              .query("SELECT * FROM TABLE(SYSTEM_RANGE(0, 1))") // 2 rows
              .pageSize(1) // 1 row
              .build();

      for (int attempt = 0; attempt < 1000; attempt++) {
          var rs = sql.execute(null, stmt); // preloads 2-nd page in the 
background (see SyncResultSetAdapter.IteratorImpl constructor)
          rs.close(); // Fails with "Failed to find resource"
      }
  }
{code}
Stacktrace:
{noformat}
Caused by: org.apache.ignite.internal.lang.IgniteInternalException: 
IGN-CMN-65535 Failed to find resource with id: 23 TraceId:e40ee6a7
  at 
org.apache.ignite.client.handler.ClientResourceRegistry.remove(ClientResourceRegistry.java:95)
  at 
org.apache.ignite.client.handler.requests.sql.ClientSqlCursorCloseRequest.process(ClientSqlCursorCloseRequest.java:35)
  at 
org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperation(ClientInboundMessageHandler.java:994)
  at 
org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperationInternal(ClientInboundMessageHandler.java:1103)
{noformat}
We need to fix this issue properly.

Some thoughts worth considering:
 * Completely ignoring the exception is bad, because we might miss another 
resource leak problem.
 * Removing background preloading in SyncResultSetAdapter is bad because it 
negatively affects performance.

  was:
Consider the following example:
{code:java}
  var rs = sql.executeAsync(null, "SELECT...").join();

  rs.fetchNextPage(); // SQL_CURSOR_NEXT_PAGE
  rs.close(); // SQL_CURSOR_CLOSE
{code}

In the above case, the SQL_CURSOR_CLOSE request is sent to the server before 
the result of the SQL_CURSOR_NEXT_PAGE request is received.

The SQL_CURSOR_NEXT_PAGE request handler, if the last requested page removes 
the client resource (see ClientSqlCursorNextPageRequest.process())
The SQL_CURSOR_CLOSE request handler may fail with the error "Failed to find 
resource with id" if SQL_CURSOR_NEXT_PAGE has already removed this resource.

The problem is even more important for the synchronous API due to optimization, 
which always requests the next data page in the background.

Reproducer:
{code:java}
  @Test
  void resourceNotFoundOnClose() {
      IgniteSql sql = client().sql();

      Statement stmt = sql.statementBuilder()
              .query("SELECT * FROM TABLE(SYSTEM_RANGE(0, 1))") // 2 rows
              .pageSize(1) // 1 row
              .build();

      for (int attempt = 0; attempt < 1000; attempt++) {
          var rs = sql.execute(null, stmt); // preloads 2-nd page in the 
background (see SyncResultSetAdapter.IteratorImpl constructor)
          rs.close(); // Fails with "Failed to find resource"
      }
  }
{code}

Stacktrace:
{noformat}
Caused by: org.apache.ignite.internal.lang.IgniteInternalException: 
IGN-CMN-65535 Failed to find resource with id: 23 TraceId:e40ee6a7
  at 
org.apache.ignite.client.handler.ClientResourceRegistry.remove(ClientResourceRegistry.java:95)
  at 
org.apache.ignite.client.handler.requests.sql.ClientSqlCursorCloseRequest.process(ClientSqlCursorCloseRequest.java:35)
  at 
org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperation(ClientInboundMessageHandler.java:994)
  at 
org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperationInternal(ClientInboundMessageHandler.java:1103)
{noformat}

We need to fix this issue properly.

Some thoughts worth considering:
* Completely ignoring the exception is bad, because we might miss another 
resource leak problem.
* Removing background preloading in SyncResultSetAdapter is bad because it 
negatively affects performance.


> Java thin. Sql. A race between close() and fetchNextPage() in ResultSet may 
> result in an error
> ----------------------------------------------------------------------------------------------
>
>                 Key: IGNITE-26927
>                 URL: https://issues.apache.org/jira/browse/IGNITE-26927
>             Project: Ignite
>          Issue Type: Bug
>          Components: sql ai3, thin clients ai3
>            Reporter: Pavel Pereslegin
>            Priority: Major
>              Labels: ignite-3
>
> Consider the following example:
> {code:java}
>   var rs = sql.executeAsync(null, "SELECT...").join();
>   rs.fetchNextPage(); // SQL_CURSOR_NEXT_PAGE
>   rs.close(); // SQL_CURSOR_CLOSE
> {code}
> In the above case, the {{SQL_CURSOR_CLOSE}} request is sent to the server 
> before the result of the {{SQL_CURSOR_NEXT_PAGE}} request is received.
> The {{SQL_CURSOR_NEXT_PAGE}} request handler, if the last requested page 
> removes the client resource (see {{ClientSqlCursorNextPageRequest.process()}})
> The {{SQL_CURSOR_CLOSE}} request handler may fail with the error "Failed to 
> find resource with id" if {{SQL_CURSOR_NEXT_PAGE}} has already removed this 
> resource.
> The problem is even more important for the synchronous API due to 
> optimization, which always requests the next data page in the background.
> Reproducer:
> {code:java}
>   @Test
>   void resourceNotFoundOnClose() {
>       IgniteSql sql = client().sql();
>       Statement stmt = sql.statementBuilder()
>               .query("SELECT * FROM TABLE(SYSTEM_RANGE(0, 1))") // 2 rows
>               .pageSize(1) // 1 row
>               .build();
>       for (int attempt = 0; attempt < 1000; attempt++) {
>           var rs = sql.execute(null, stmt); // preloads 2-nd page in the 
> background (see SyncResultSetAdapter.IteratorImpl constructor)
>           rs.close(); // Fails with "Failed to find resource"
>       }
>   }
> {code}
> Stacktrace:
> {noformat}
> Caused by: org.apache.ignite.internal.lang.IgniteInternalException: 
> IGN-CMN-65535 Failed to find resource with id: 23 TraceId:e40ee6a7
>   at 
> org.apache.ignite.client.handler.ClientResourceRegistry.remove(ClientResourceRegistry.java:95)
>   at 
> org.apache.ignite.client.handler.requests.sql.ClientSqlCursorCloseRequest.process(ClientSqlCursorCloseRequest.java:35)
>   at 
> org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperation(ClientInboundMessageHandler.java:994)
>   at 
> org.apache.ignite.client.handler.ClientInboundMessageHandler.processOperationInternal(ClientInboundMessageHandler.java:1103)
> {noformat}
> We need to fix this issue properly.
> Some thoughts worth considering:
>  * Completely ignoring the exception is bad, because we might miss another 
> resource leak problem.
>  * Removing background preloading in SyncResultSetAdapter is bad because it 
> negatively affects performance.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to