Matt
Matt

Reputation: 4752

Loose request outside of an expired connection

I am trying to perform the following pg-promise query, but receive this error:

Loose request outside of an expired connection

The query actually succeeds, but, even so, I would like to get rid of the error message.

The pg-promise query

 db.task(t => {
          t.oneOrNone(queries.insertUser, [profile.id])
          .then(id =>{ 
          if (id) {
            t.none(queries.insertUserGoogle, [
              profile.id,
              profile.emails[0].value,
              profile.name.givenName,
              profile.name.familyName,
              profile.displayName
            ])
          }})
          .catch(err => console.log(err))

The SQL

const insertUser = `INSERT INTO users (google_id) 
    VALUES ($1) 
    ON CONFLICT (google_id) DO NOTHING
    RETURNING user_id`;

const insertUserGoogle = `INSERT INTO users_google (google_id, email, first_name, last_name, display_name) 
    VALUES ($1, $2, $3, $4, $5)`;

Upvotes: 1

Views: 629

Answers (1)

vitaly-t
vitaly-t

Reputation: 25820

I'm the author of pg-promise.


You fail to chain promises returned by the query methods, which in turn executes them outside of the task context, which results in that error.

Here's the right way to do it:

db.task(t => {
    return t.oneOrNone(queries.insertUser, [profile.id])
        .then(id => {
            if (id) {
                return t.none(queries.insertUserGoogle, [values])
            }
        })
})
    .catch(err => {
        console.log(err);
    });

Promises must always be chained. And in the context of a task they must be chained to the task.

Failure to do so results in loose promises, and in the context of the database task - loose query requests that are trying to execute after the task has finished and released its connection.

Also, a good approach is to use .catch on the result of the task, as shown, not inside the task.

Other Hints

  • Since both of your queries inside the task are inserts, then perhaps you should be using method tx for transaction, and not task, if you care about the data integrity that is.
  • It makes for much cleaner and more efficient code to store SQL in external files and access them as Query Files instead. See also: pg-promise-demo.

UPDATE

However, if your task uses a generator, then you do not need to chain anything inside the task:

db.task(function* (t) {
    const id = yield t.oneOrNone(queries.insertUser, [profile.id]);
    if (id) {
        yield t.none(queries.insertUserGoogle, [values]);
    }
})
    .catch(err => {
        console.log(err);
    });

...you only chain the task's result.

UPDATE

In version 6.5.4 the error message was refactored into Querying against a released or lost connection.

Upvotes: 2

Related Questions