googleapis / nodejs-spanner

Node.js client for Google Cloud Spanner: the world’s first fully managed relational database service to offer both strong consistency and horizontal scalability.
https://cloud.google.com/spanner/
Apache License 2.0
136 stars 102 forks source link

Transaction Promise.all with multiple queries results in Error: stream.push() after EOF #1908

Closed mrichardEA closed 1 year ago

mrichardEA commented 1 year ago

Upgrading to 6.5.0, we started encountering an issue when using Promise.all with multiple queries in a transaction.

This issue only started as of 6.5.0, (6.4.0 and earlier do not encounter this issue).

Possible culprits:

Environment details

Steps to reproduce

  1. Create an async transaction that does 3 queries in a promise all:

        const spanner = new Spanner(<projectId>);
        const instance = spanner.instance(<instanceName>);
        const database = instance.database(<databaseName>);
    
        console.log('MJR instanceName', instanceName);
        console.log('MJR databaseName', databaseName);
    
        await database.runTransactionAsync(async (t) => {
            try {
                async function doRun(query: string): Promise<void> {
                    console.log('Starting ', query);
                    await t.run(query);
                    console.log('Finished ', query);
                }
    
                const query1 = 'select * from trigger_offer';
                const query2 = 'select * from offer_purchases';
                const query3 = 'select * from active_offer';
    
                await Promise.all([doRun(query1), doRun(query2), doRun(query3)]);
                await t.commit();
            } catch (err) {
                console.log('MJR snapshot err', JSON.stringify(err));
            } finally {
                t.end();
            }
        });
        // Close the database when finished.
        await database.close();
        spanner.close();
  2. Running the code produced this output:
    [node] MJR instanceName development
    [node] MJR databaseName development_mrichard_amp
    [node] Starting  select * from trigger_offer
    [node] Starting  select * from offer_purchases
    [node] Starting  select * from active_offer
    [node] Finished  select * from trigger_offer
    [node] uncaughtException stream.push() after EOF Error: stream.push() after EOF
    [node]     at new NodeError (node:internal/errors:399:5)
    [node]     at readableAddChunk (node:internal/streams/readable:285:30)
    [node]     at PassThrough.Readable.push (node:internal/streams/readable:234:10)
    [node]     at Immediate._onImmediate (/opt/amp/node_modules/@google-cloud/spanner/build/src/partial-result-stream.js:320:25)
    [node]     at processImmediate (node:internal/timers:476:21)
    [node]     at process.callbackTrampoline (node:internal/async_hooks:130:17)
    [node] child process died with code 1
    [node] restarting processes
mrichardEA commented 1 year ago

I can also confirm when I downgrade down to 6.4.0 and run the same code, I no longer get the Error: stream.push() after EOF.

Output when run on 6.4.0:

[node] MJR instanceName development
[node] MJR databaseName development_mrichard_amp
[node] Starting  select * from trigger_offer
[node] Starting  select * from offer_purchases
[node] Starting  select * from active_offer
[node] Finished  select * from trigger_offer
[node] Finished  select * from offer_purchases
[node] Finished  select * from active_offer
surbhigarg92 commented 1 year ago

Hi @mrichardEA Please allow us some time to look into the issue.