Best Practices

Choose a suitable connection type

The decision between a single connection and a connection pool depends on expected traffic, workload volatility, and performance requirements. While a connection pool offers advantages in managing multiple concurrent connections efficiently, a single connection might be preferred for simplicity, resource optimization, and predictable transactional behavior. For more details, see Connect to the NuoDB Database.

Implement type safety

Implement type safety to detect type-related errors at compile-time or runtime and to ensure that a program behaves as expected and avoids unexpected behavior or crashes.

To implement type safety:

  • Use try/catch, callback, and Promise semantics

    The NuoDB Node.js driver supports try/catch, callback, and Promise semantics that can be used to ensure that type-related errors or other exceptions are appropriately addressed, preventing unhandled exceptions.

  • Verify the availability of data and catch error at the operation level, and not in an operation within a block.

  • Use finally block

    Any try/catch block must be followed by a finally block for performing cleanup tasks, such as releasing resources, closing files, or cleaning up database connections. Cleaning up NuoDB resources in a try block can lead to NuoDB resources in an inconsistent or unreleased state.

Implement retry operations

For critical operations, process transient failures by implementing a retry mechanism. A transient condition is a condition that temporarily prevents an operation from succeeding, but retrying the operation may improve the chances of success. If an exception occurs, catch it, perform the clean-up operations, and retry the operations. To allow some time margin between retries, increase the delay between retries.

Retrying a Deadlock Exception

NuoDB has a distributed deadlock detection system that detects deadlocks and then picks one of the transactions to sacrifice (force abort), which is properly done when you execute a rollback. A deadlock is an example of a transient condition. Use retry operations to prevent these scenarios and enforce transactions to be committed. Limit the amount of retries. For more information on NuoDB’s expected behavior during concurrent transaction updates, please refer to the Transaction Isolation Level documentation.

Here is an example implementing retry operation:

async function() => {
    let retry = false;
    let retryLimit = 3;
    let retryCount = 0;
    let autoCommit = conn.autoCommit;
    conn.autoCommit = false;    // temporarily set autoCommit to `false`

    do {
        retryCount = retryCount + 1;

        try {
            await txn();
            await conn.commit();

        } catch (e) {
            let retry = false;

            if ((e.message.includes('deadlock')) || e.message.includes('update conflict')) {
                await conn.rollback();
                retry = true;
            }
            if (!retry) { throw e }
        }
    } while (retry && (retryCount < retryLimit));

    conn.autoCommit = autoCommit;   // set autoCommit to previous value
}