Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Unique Index Violation no error thrown #55

Open
SampsonCrowley opened this issue Jul 16, 2017 · 2 comments
Open

Unique Index Violation no error thrown #55

SampsonCrowley opened this issue Jul 16, 2017 · 2 comments

Comments

@SampsonCrowley
Copy link

In production, Unique Index violations from PG never throw an error, they just timeout;

So the client just sits there indefinitely

Function to get client:

import {native as pg} from 'pg';
....
const config = {
  user: auth[0],
  password: auth[1] || null,
  host: params.hostname,
  port: params.port,
  database: params.pathname.split('/')[1],
  max: 20,
  ssl: false,
  idleTimeoutMillis: 10000
};

const pool = new pg.Pool(config);

class DbConn {

...

transaction() {
    return pool.connect().then(client => {
      var transRB = this.rollback, transCM = this.cm;
      return client.query('BEGIN').then(res => {
        client.commit = async function(){
          return transCM(client)
        }

        client.rollback = async function(){
          return transRB(client)
        }

        return client;
      });
    })
  }

async commit(client) {
    await client.query('COMMIT')
    client.release()
    return true;
  }

  async rollback(client) {
    console.log(client);
    try {
      console.info('Rolling back Transaction');
      await client.query('ROLLBACK')
      return "Rolled Back"
    } catch(e) {
      console.log(e)
    } finally {
      client.release();
    }
  }
}

Function Creating transaction:

this.save = async function save(client = null){
      try {
        const changed = this.checkChanged()
        if(!changed) return this;
        this.client = client || await DB.transaction();
        console.log(this.client, client);
        await _runBeforeSave(); //COMPLETES
        await _save(); //NEVER COMPLETES OR THROWS ERROR IF INDEX VIOLATION
        await _runAfterSave() //NEVER GETS HERE

        if(!client) await this.client.commit();
        this.client = null;
        return this.proxy;
      } catch(e){
//THIS CATCH BLOCK IS NOT CALLED UNTIL THE SERVER CLOSES THE CONNECTION BY TIMEOUT
        console.log(e, 'Caught at save root');
        if(!client) this.client.rollback();
        this.client = null;
        if(typeof e === 'string') e = new Error(e);
        return Promise.reject(e);
      }
    }
    
    const _save = (async function _runSaveInstance() {
      try {
        await _runBelongsTo();
        (this.attributes.id ? await _update() : await _create())
        return _runHasMany()
      } catch(e){
        console.log('Caught in _save()', e);
        return Promise.reject(e)
      }
      // .catch(err => Promise.reject(err))
    }).bind(this)

    const _create = (async function _create(){
      let values = [],
          keys = Object.keys(this.changedAttributes),
          queryString = `INSERT INTO "${this.table}" (`;

      console.log('creating');

      for(var a = 0; a < keys.length; a++){
        const key = keys[a];
        if(dbAttributes[key]){
          queryString += `${key}${a === keys.length - 1 ? '' : ', '}`;
          values.push(this.attributes[key]);
        }
      }

      queryString += ') VALUES (';

      for(var v = 1; v <= values.length; v++){
        queryString += `$${v}${v === values.length ? '' : ', '}`;
      }
      queryString += `) RETURNING *;`;

      console.log('running save query: ', queryString, values); //ALWAYS MAKES IT HERE WITH THE CORRECT QUERY STRING AND VALUES
      try {
         //HANGS INDEFINITELY IF ERROR; COMPLETES ALMOST INSTANTLY WHEN NOT AN INDEX VIOLATION
        const result = await this.client.query(queryString, values);
      } catch(e){
        // 'e' is ALWAYS 'server unexpectedly closed connection' if there's and index violation
        console.log('Object Not Created', e);
        return Promise.reject(e)
      }
//NEVER MAKES IT HERE IF UNIQUE INDEX VIOLATION
      console.log('finished save query: ', result)

      if(!result || !result.rows) return Promise.reject('Object Not Saved');
      mapAttributes(result.rows[0]);
      setParentIds()

    }).bind(this)
@SampsonCrowley
Copy link
Author

Important to note I AM using PgPool-II which i think there have been previous reports of not working with parameterized queries and this library.

important to note that it's only a problem with the pg library on node. Rails/activerecord and a python app I built both have no issues with pgpool

@brianc
Copy link
Owner

brianc commented Jul 16, 2017

Sorry you're running into this issue. Could you break the code down into a smaller more self-contained example? If you can get me something small & reproducible I can take a look at it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants