sagiegurari / simple-oracledb

Extend capabilities of oracledb with simplified API for quicker development.
Apache License 2.0
36 stars 4 forks source link

DPI-1040: LOB was already closed #34

Open ShowmanStone opened 2 years ago

ShowmanStone commented 2 years ago

node version: 8.17.0 nodeoracledb version: 4.2.0 simple-oracledb version: 1.4.2 Hi, my application has recently got 'DPI-1040: LOB was already closed' error twice, which causes application crash. after google, I notice this error happens when you try to wirte into a lob stream after it's been closed. but the lob stream is created when connection.execute and will be closed after write finish, I also checked the TCP dump between application and database and it looks fine before application down and close the TCP connection. I can't figure out how this error happen and what to do to prevent it, have you meet this before or any suggestion I can track? looking forward to your reply!

sagiegurari commented 2 years ago

I would need some test case to run so i'll be able to reproduce and solve. otherwise, with the description alone, its not enough to help.

ShowmanStone commented 2 years ago

the application runs several years and only recently this error happens, it's hard to reproduce as i don't know in what situation where this happen. my code is like below: var sql='UPDATE xtable SET xclob = EMPTY_CLOB() WHERE id = :cid'; simpleOracleDB.pool.run(function(conn, cb){ connection.update(sql,{ cid: 111, json: some string}, { autoCommit: true, lobMetaInfo: {xclob:'json'} }, cb); },callback);

I add writableStream.close() before writableStream.end(data, 'utf8', onWrite) in stream.js, but can't reproduce this error

sagiegurari commented 2 years ago

I created another stability test with your scenario but couldn't repo it. i have to admit, that if you are facing a crash, it means something went wrong in the c++ layer of oracledb (simple-oracledb doesn't have any native code, only js). so worth maybe posting a question there. it might be hard for them to understand the issue but maybe with some manual code review they might find the problem. crashes should never happen.

my hunch is that you had some network issue that caused it and the c++ code didn't react that well. but... its a hunch.

cjbj commented 2 years ago

We'd ask for a complete testcase.

@sagiegurari can you check your streaming code and compare with our current 'best practices', see the example. Make sure the connection isn't being closed too early.

sagiegurari commented 2 years ago

good idea

ShowmanStone commented 2 years ago

https://github.com/oracle/node-oracledb/blob/main/examples/lobstream1.js I tried close connection before doStream in the example lobstream1, and reproduce this error which been catched. so maybe we can add a try-catch in simple-oracledb to prevent app crash?

ShowmanStone commented 2 years ago

there is a firewall between app and database, will the ping function in pool.getconnection notice if the firewall close the connection?

sagiegurari commented 2 years ago

what do you mean crash? the node.js app died with some core dump due to native error? if so, you cant catch it in the js layer.

ShowmanStone commented 2 years ago

I mean it's an uncaughtexception, but when i try to close connection in your connection.js before recordWriter.write i can only reproduce DPI-1010, and it will be caught in writableStream.once('error', onError). so i still don't know how DPI-1040 happen and where to try-catch it

sagiegurari commented 2 years ago

oh, ok, js err thrown. i guess you don't have a stack trace? you could catch all uncaught exceptions in node.js and log them so you will have a stack when it happens and you can prevent the app from crashing and do some automatic recovery. once you have a stack I might be able to help more and understand the right way to resolve it. i didnt have a change to reread the docs as cjbj suggested, but it should be ok or this would have happened a lot more to many people. still, I'll do it to make sure

ShowmanStone commented 2 years ago

I have reproduced this DPI-1040 uncaught error by close connection in connection.js before recordWriter.write then run writableStream.end two times, the first time error will be caught by onError, but onError is an once listener, so the second time error will not been caught. maybe we can change the 'once' to 'on'?

sagiegurari commented 2 years ago

interesting, i'll take a look but this could happen in many places and lead to strange other issues. so need to be careful.

cjbj commented 2 years ago

@sagiegurari would it safer (and faster for apps) if you exposed fetchAsString and fetchAsBuffer? https://oracle.github.io/node-oracledb/doc/api.html#queryinglobs

sagiegurari commented 2 years ago

I don't hide/prevent such setup. i only add more functions to the prototype. so anyone can still set the fetch flags and it should work. if those existed at first release, i would probably not even written this lib :)

sagiegurari commented 2 years ago

@ShowmanStone I looked at your explanation. Currently after 'end' event i remove the 'error' listener (for cleanup). After 'end' there shouldn't be anything for that stream, but in your explanation you changed the code to call 'end' twice which shouldn't happen. I could put some noop as 'error' listener (since callback was already fired in the first end), but that would just hide errors.

my recommendation would be to catch unhandled errors in the node.js process and log them. then inspect and decide how to handle. if there are things wrong inside simple-oracledb, you can provide a stack trace and test case for me to use. but my guess is that your example is not whats happening and at the moment "fixing" it there might just not help.

ShowmanStone commented 2 years ago

actually I had a uncaughtexception listener in my node.js process and logged error.stack, but in this prod situation I only got ‘DPI-1040: LOB was already closed’ with no more call stack, so I can only try any possibilities to reproduce

sagiegurari commented 2 years ago

thanks for the info. I'm guessing that only frame was in the stream.js?

ShowmanStone commented 2 years ago

I suppose so, as the process only use simple-oracledb to connect to the database to select/update/insert and this error related to lob

sagiegurari commented 2 years ago

let me try to see if i can do something....