SAP / node-rfc

Asynchronous, non-blocking SAP NW RFC SDK bindings for Node.js
Apache License 2.0
251 stars 73 forks source link

can't get data from RFC call randomly #184

Closed gimapei closed 3 years ago

gimapei commented 3 years ago

hi.

here is my sample code.

"use strict";
const Client = require("node-rfc").Client;

// ABAP system RFC connection parameters
const abapSystem = {
    user: "DAP01",
    passwd: "",
    ashost: "",
    sysnr: "02",
    client: "100",
    lang: "KO",
};

// create new client
const client = new Client(abapSystem);

// open connection
client.connect(function (err) {
    if (err) {
        // check for login/connection errors
        return console.error("could not connect to server", err);
    }

    // echo SAP NWRFC SDK and nodejs/RFC binding version
console.log("id:"+client.id+", isAlive:"+client.alive);
// console.log(client.environment);

try {
    client.invoke(
        "Z02SD_GET_POINT_ID",
        { I_DATE_FR:"20200101",
        I_DATE_FR:"20200102"},
        function (err, res) {
            if (err) {
                return console.error("Error RFC Call:", err);
            }
            // console.log("STFC_STRUCTURE call result:", res);
            console.log('call success');
        }
    )
    } catch(error) {
        console.log("ab error:"+error);
    }
});

some results

PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\rfctest.js
id:1, isAlive:true

==========================================================================

[ my environment]

{
  platform: { name: 'win32', arch: 'x64', release: '10.0.18363' },
  env: {
    SAPNWRFC_HOME: 'C:\\Users\\joe.c\\Desktop\\nwrfc750P_7-70002755_win\\nwrfcsdk',
    RFC_INI: '',
    nwrfcsdk_lib_on_path: true
  },
  versions: {
    node: '14.15.0',
    v8: '8.4.371.19-node.17',
    uv: '1.40.0',
    zlib: '1.2.11',
    brotli: '1.0.9',
    ares: '1.16.1',
    modules: '83',
    nghttp2: '1.41.0',
    napi: '7',
    llhttp: '2.1.3',
    openssl: '1.1.1g',
    cldr: '37.0',
    icu: '67.1',
    tz: '2020a',
    unicode: '13.0'
  },
  noderfc: {
    version: '2.3.0',
    nwrfcsdk: { major: 7500, minor: 0, patchLevel: 7 }
  }
}

Looking at the results, the result is success for RFC Call randomly. some time success, some time error, but same import and same data sets for RFC call How can I find error? How can I debug the node-rfc code?

Could you help me?

Note, RFC Function response simple three columns

thanks

bsrdjan commented 3 years ago

The console log does not show any error, only success in some cases. Is the console log complete, any error ever returned?

Could you please test with standard BAPI and post the console output:

bapitest.js

// create new client
const client = new Client(abapSystem);

// open connection
client.connect(function (err) {
    if (err) {
        // check for login/connection errors
        return console.error("could not connect to server", err);
    }

    // echo SAP NWRFC SDK and nodejs/RFC binding version
    console.log("id:" + client.id + ", isAlive:" + client.alive);
    // console.log(client.environment);

    try {
        client.invoke("BAPI_USER_GET_DETAIL", { USERNAME: client.connectionInfo.user }, function (
            err,
            res
        ) {
            if (err) {
                return console.error("Error RFC Call:", err);
            }
            // console.log("STFC_STRUCTURE call result:", res);
            console.log("call success");
        });
    } catch (error) {
        console.log("ab error:" + error);
    }
});
gimapei commented 3 years ago

thanks your feed. ' yes if there an error, it doesn't show an error, just crash the program. so when I using with node-red. it crashes my node-red process. and I think, It occurs for specific programs, not all programs I don't know the difference.

tomorrow, I can test bapitest.js and report for you.

bsrdjan commented 3 years ago

Could you please share more info on how the NodeRED is involved because the node-rfc is not supported on NodeRED: #161

I tried to reproduce by repeatedly calling node bapitest.js from Windows PowerShell and nothing happened. Is there anything missing in my test scenario? More info on complete test scenario would be very helpful for analysis.

gimapei commented 3 years ago

Hello. here is my test result. As seen from the above.

It occurs randomly. but node-rfc doesn't throw exception, just crash.

id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> node .\bapitest.js
id:1, isAlive:true
call success

and this is my story. I used node-rfc 1.2.0 version in several projects with node-red. and sometimes RFC Handle error occurs, and I think there is a memory leak by RFC error. so I try to apply node-rfc 2.3.0. and test results are as written in above. A specific RFC is causing a problem, but node-rfc does not throw an exception,

if node-rfc can throw exception from error . i can coding regression logic to my node(s/w), maybe five times... thanks

gimapei commented 3 years ago

hi, another test. I write some logs into node_modules/node-rfc/lib/wrapper/sapnwrfc-client.js like this.

 invoke(rfmName, rfmParams, callback, callOptions) {
        console.log('------------------inside -----------------');

        try {
            if (typeof callback !== "function") {
                throw new TypeError("Callback function must be supplied");
            }
            if (arguments.length < 3) {
                throw new TypeError("Client invoke() argument missing: RFM name, parameters or callback");
            }
            if (typeof rfmName !== "string") {
                throw new TypeError("Client invoke() 1st argument (remote function module name) must be an string");
            }
            if (typeof rfmParams !== "object") {
                throw new TypeError("Client invoke() 2nd argument (remote function module parameters) must be an object");
            }
            if (arguments.length === 4 && typeof callOptions !== "object") {
                throw new TypeError("Call options argument must be an object");
            }
            this.__client.invoke(rfmName, rfmParams, callback, callOptions);
            console.log(this.__client);
            console.log('complete');
            callback();
        }
        catch (ex) {
            if (typeof callback !== "function") {
                throw ex;
            }
            else {
                callback(ex);
            }
        }
    }

[ error case log ]

------------------inside -----------------
undefined
Client {}
complete
STFC_STRUCTURE call result: undefined
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> 

[ success case log ]

------------------inside -----------------
undefined
Client {}
complete
STFC_STRUCTURE call result: Object
call success
call success
PS C:\Users\joe.c\Desktop\prj-ehanglas-iocatcher\prj-ehanglas-iocatcher\test> 

and if there is an error. ( i think, invoke actions doesn't get return values from RFC ) there is not call callback method.

In order

  1. call rfc functon ( invoke )
  2. RFC doesn't send return data.
  3. there is not callback.
  4. crash node-rfc
  5. crash node process

I think we need to find out why sometime there is a return and sometime not. and even if there is no return, node-rfc does not die or crash..

thanks

bsrdjan commented 3 years ago

Is NodeRED anyhow involved in your testing and is there any crash log or error message ?

If you add the trace: 3 to your connection parameters, the SAP NWRFC SDK trace files will be captured.

Could you please send me traces after one successful call and after one call with error?

gimapei commented 3 years ago

Currently, node-red is irrelevant. I plan to apply node-red when this test is complete.

and here is test results what you want.

rfctest.zip

bsrdjan commented 3 years ago

Thank you very much for traces. Some errors are captured, we need to analyse them.

In the meantime, if you have SAP NWRFC SDK PL6 at hand, could you please check if errors occur also with PL6?

bsrdjan commented 3 years ago

Sorry @gimapei, my instruction was incorrect and errorInfo I saw in traces are actually not errors.

Instead of setting the trace: 3 in connection parameters, please remove it from there and set the environment variable RFC_TRACE=3. That will generate the traces with the maximum level of SDK functions' details. Could you please send me these traces and, of possible, test with PL6.

gimapei commented 3 years ago

it's ok. I will try again. but I have not PL6, I have only PL7.

bsrdjan commented 3 years ago

Can you create SAP customer incident for the BC-MID-RFC-SDK component and refer to this issue? I could then send you the SDK libraries which should work for you, until the PL8 released.

gimapei commented 3 years ago

I requested issue registration to my boss. And below is full trace files for you.

rfctest.zip

gimapei commented 3 years ago

Hello we got the SAP incident number, 819279 can I get your plan or schedule?

bsrdjan commented 3 years ago

Thank you very much @gimapei. The ticket is processed by SAP standard support. Please mention in the ticket, if not already done, that the request is related to node-rfc issue.

bsrdjan commented 3 years ago

You can try this workaround in the meantime: https://github.com/SAP/node-rfc/issues/189#issuecomment-736527285

gimapei commented 3 years ago

I am sorry. it's not work for me

bsrdjan commented 3 years ago

Hi @gimapei,

I could not reproduce on Windows. Tried also with this PS script but no error:

run.ps1

1..10 | % { node .\bapitest.js }

Console

C:>\test .\run.ps1

To exclude one more possibility, could you please try with attached node-rfc build? Unpack the zip or tar archive and go to your project node_modules\node-rfc\lib\binding folder. Replace the sapnwrfc.node in that folder, with the sapnwrfc.node from zip or tar file: node-rfc-v2.3.1-napi-v7-win32-x64.tar.gz node-rfc-v2.3.1-napi-v7-win32-x64.zip

And one more question. The error occurs with repeated manual testing, from PowerShell console, correct? Could you please test with the script below, using Connection Pool instead of the direct Client? You can also run it via run.ps1 script:

bapitest.js

const Pool = require("node-rfc").Pool;

// add your ABAP system destination to sapnwrfc.ini file
abapSystem = { dest: "MME" }; 

const pool = new Pool({connectionParameters: abapSystem});

(async() => {
    try {
        var client = await pool.acquire();
        await client.call("BAPI_USER_GET_DETAIL", { USERNAME: client.connectionInfo.user});
        console.log("success", client.id);
    } catch (ex) {
        console.log("error", ex)
    } finally {
        client && client.release();
        console.log("release", client.id)
    }
})();

Please use the sapnwrfc.ini file like this, add your system parameters and leave the RFC_TRACE=3 in the DEFAULT section. The file should be in the node project root folder (where the bapitest.js is). In your node script you can use your system destination, like the MME in this example:

sapnwrfc.ini

DEFAULT
RFC_TRACE=3

DEST=MME
USER=demo
PASSWD=welcome
#ASHOST=coevi51
ASHOST=10.68.110.51
SYSNR=00
CLIENT=620
LANG=EN
#TRACE=3
gimapei commented 3 years ago

hello I was debugging source code nwrfcsdk.cc and I found bug from wrapString function.

At the end of the line. An error occurs where "free((char*)utf8)".

If I commented on that part, it does not occur what I mentioned above. Although memory usage will continue to increase.

I am not good at c++, so I don't know what to do about that, Can I get a recommendation?

Napi::Value wrapString(SAP_UC *uc, int length)
    {
        RFC_ERROR_INFO errorInfo;

        Napi::EscapableHandleScope scope(node_rfc::__env);

        if (length == -1)
        {
            length = strlenU(uc);
        }
        if (length == 0)
        {
            return Napi::String::New(node_rfc::__env, "");
        }
        // try with 3 bytes per unicode character
        uint_t utf8Size = length * 3;
        char *utf8 = (char *)malloc(utf8Size + 1);
        utf8[0] = '\0';
        uint_t resultLen = 0;
        RfcSAPUCToUTF8(uc, length, (RFC_BYTE *)utf8, &utf8Size, &resultLen, &errorInfo);
        //EDEBUG("len: ", length, " utf8Size: ", utf8Size, " resultLen: ", resultLen, " ", errorInfo.code);
        if (errorInfo.code != RFC_OK)
        {
            // not enough, try with 5
            free(utf8);
            utf8Size = length * 5;
            utf8 = (char *)malloc(utf8Size + 1);
            utf8[0] = '\0';
            resultLen = 0;
            RfcSAPUCToUTF8(uc, length, (RFC_BYTE *)utf8, &utf8Size, &resultLen, &errorInfo);
            if (errorInfo.code != RFC_OK)
            {
                free(utf8);
                return node_rfc::__env.Undefined();
            }
        }

        int i = resultLen - 1;
        while (i >= 0 && isspace(utf8[i]))
        {
            i--;
        }
        utf8[i + 1] = '\0';

        Napi::Value resultValue = Napi::String::New(node_rfc::__env, utf8);
        printf(" wrap #1 %s ",resultValue.As<Napi::String>().Utf8Value());
//        free(utf8);
//        delete utf8;
        printf(" wrap #2 \n");
        return scope.Escape(resultValue);
    }
gimapei commented 3 years ago

I think there is no problem with version 2.4.0.

bsrdjan commented 3 years ago

Thanks @gimapei for the update.