Node-Firebird Invalid transaction handle

653 views Asked by At

I got an error when trying to commit in sequence with the same transaction. I am using Node-firebird lib. The first time is committed, but the second time I got the following message:

Error:

> invalid transaction handle (expecting explicit transaction start) at
> doCallback
> (C:\Ultra\PreVendaServerV2\node_modules\node-firebird\lib\index.js:1297:21)
> at
> C:\Ultra\PreVendaServerV2\node_modules\node-firebird\lib\index.js:3019:25
> at
> C:\Ultra\PreVendaServerV2\node_modules\node-firebird\lib\messages.js:151:25
> at search
> (C:\Ultra\PreVendaServerV2\node_modules\node-firebird\lib\messages.js:117:13)
> at
> C:\Ultra\PreVendaServerV2\node_modules\node-firebird\lib\messages.js:54:21
> at FSReqCallback.wrapper [as oncomplete] (fs.js:520:5) at
> FSReqCallback.callbackTrampoline (internal/async_hooks.js:126:14) {
> gdscode: 335544332, gdsparams: undefined

I am trying to insert the CHILDREN when I get the error message with the same transaction.

    public static async getTransaction(db: Database, ISOLATION_LEVEL?: number[]): Promise<Firebird.Transaction> {
        if (!db) throw "There is no Connection with the database!";
        const ISOLATION = ISOLATION_LEVEL ? ISOLATION_LEVEL : Firebird.ISOLATION_READ_COMMITED;

        return new Promise(
            (resolve, reject) => {
                db.transaction(ISOLATION, function (err, transaction) {
                    if (err && LOG_SQL) { console.log(err) };
                    if (err) reject(err);
                    resolve(transaction);
                });
            });
    }

    public static async asyncInsert(insertSQL: string, params?: any[], insertChildrenCallback?: any, originObject?: any, transaction?: Firebird.Transaction, commit?: boolean) {
        try {
            const db = await FirebirdPromise.attach();
            if (!transaction) transaction = await this.getTransaction(db);

            const insertedId = await this.execQueryWithTransaction(insertSQL, transaction, params, originObject);

            if (insertChildrenCallback) await insertChildrenCallback(insertedId, originObject, transaction, db);
            if (commit) await this.tryCommit(transaction, db);

            return new DatabaseResult({
                status: DatabaseResult.RESULT_OK, message: null, data: insertedId
            });
        } catch (error) {
            return new DatabaseResult({
                status: DatabaseResult.RESULT_ERROR, message: error, data: null
            });
        }
    }



public static async tryCommit(transaction: Firebird.Transaction, db: Database): Promise<Boolean> {
    return new Promise(
        (resolve, reject) => {
            transaction.commit(function (err) {
                if (err) {
                    if (LOG_SQL) console.log(err);
                    transaction.rollback();
                    reject(err);
                    throw err;
                }
                db.detach();
                resolve(true);
            });
        });
}
1

There are 1 answers

2
tbking On

It seems like you are trying to reuse a transaction in multiple function calls. Try doing this:

const db = await FirebirdPromise.attach();
transaction = await this.getTransaction(db);

Instead of getting transaction from the argument, and committing it multiple times, you should generate the transaction every time and then commit it. For the next insert, generate another transaction.