Uploaded image for project: 'Couchbase Server'
  1. Couchbase Server
  2. MB-59228

Execution of JS UDF fails with error in some scenarios when iterator is closed.

    XMLWordPrintable

Details

    • Untriaged
    • 0
    • Unknown

    Description

      There are currently two ways to reproduce the issue, as highlighted below.

      Repro-1 (from Rishit Chaudhary):

      Create a cluster with Data, Index, and Query services.

      1. Create a bucket named “customer” - without any documents
      2. Create the following UDF "func1" in a global library "lib1"

      function func1() {
                  var selectQuery = SELECT * from customer;
                  var q = [];
                  for (const row of selectQuery) {
                      q.push(row);
                  }
                       
          /* The below 3 lines are optional. The error can be reproduced without them, as well. However, a fix must be tested with a variant containing these three lines, as well. */                                    selectQuery.close();       selectQuery.close();            
              selectQuery.close();             
              return q;
      } 

      3. Create the N1QL mapping for the UDF (this can also be done through the Couchbase web UI)

      CREATE FUNCTION func1() LANGUAGE JAVASCRIPT AS "func1" AT "lib1";

      4. Execute the UDF (either via the shell or via the web UI)

      EXECUTE FUNCTION func1();

      5. Observe the query fails with error:

      {
                  "code": 10109,
                  "msg": "Error executing function 'func1' (lib1:func1)",
                  "reason": "Evaluator error Internal error, see cause field : Internal server error"
      } 

       

      Note: Repeat the same steps above after inserting at least 1 document in the bucket “customer(any scope or collection is fine). The UDF executes successfully with no error and the output is as expected.

      This error is being returned from the Evaluate call made from Query to js-evaluator - link to query call site

       

      Observations:

      1. Analysing the WireShark output shows that the query iterator connection is made to the local query proxy as expected.
      2. No exceptions or errors appear to be raised in the query logs.
      3. Further investigation would be needed to verify if the C++ layer is crashing and being restarted.
      4. The commenting out the two lines highlighted in the comments section of this issue, solve the problem.
        1. We are reviewing them further to ascertain why these statements led to this issue. 
      5. From Repro-1, it appears that any interaction with an empty iterator after its creation causes the "Internal server error" issue.
      6. The issue appears to happen only in the case where we have an empty iterator. All other cases, where the iterator has atleast one element appear to work as expected.

       

      —————————————————————————————————

       

      Repro-2

      1. Create a bucket named "customer".
      2. Create the following JS UDF "external1" in a global library "lib1". 

      The following JS UDF performs an UPDATE on the bucket. And then performs a SELECT on the same bucket.

      		function external1() {
      			// DML - UPDATE query
      			var updateQuery = UPDATE customer SET test = 1;
      			updateQuery.close();
      			updateQuery.close();
      			updateQuery.close();
      			updateQuery.close();
      			updateQuery.close();
      		
      			// SELECT query
      			var selectQuery = SELECT * from customer;
      			
      			var q = [];
      			for (const row of selectQuery) {
      				q.push(row);
      			}
      		
      			selectQuery.close();
      			updateQuery.close();
      			updateQuery.close();
      		
      			return q;
      		} 

       

      3. Create the N1QL function mapped to the JS UDF.

      CREATE OR REPLACE FUNCTION externalJS1() LANGUAGE JAVASCRIPT AS "external1" AT "lib1"; 

      4.  Execute the function. 

      ( If the error is not returned - Repeat the execution of the above UDF repeatedly in a sequence to see the issue )

      EXECUTE FUNCTION externalJS1(); 

      The query returns this error:

      "errors": [
              {
                  "code": 10109,
                  "msg": "Error executing function 'external1' (lib1:external1)",
                  "reason": "Evaluator error Internal error, see cause field : Internal server error"               }
      ] 

       

      ( Note that - this issue was observed by Sitaram in query unit tests for the following UDF -  where the updateQuery iterator was explicitly closed only once.  But I was only able to reproduce it with the above UDF definition. )

      // Function that performs a SELECT after a DML operation on the same bucket
              function external3() {
                  // DML - UPDATE query
                  var updateQuery = UPDATE customer SET externalChangeId = 1 WHERE test_id = "udf";
                  updateQuery.close()
              
                  // SELECT query
                  var selectQuery = SELECT externalChangeId, COUNT(*) as count from customer WHERE test_id = "udf" GROUP BY externalChangeId;
                  
                  var q = [];
                  for (const row of selectQuery) {
                      q.push(row);
                  }
              
                  selectQuery.close();
              
                  return q;
       }

       

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              pierre.regazzoni Pierre Regazzoni
              dhanya.gowrish Dhanya Gowrish
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes

                  PagerDuty