question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Promises don't behave as expected in migrations

See original GitHub issue

(This may be a duplicate of #312)

A migration file like so:

exports.up = function(knex, Promise) {
  var first = knex.schema.createTable('first', function(table) {
    table.increments('id');
    table.string('name');
  });

  var second = first.then(function() {
    return knex.schema.createTable('second', function(table) {
      table.increments('id');
      table.string('name');
    });
  });

  return Promise.all([first, second]);
};

exports.down = function(knex, Promise) {

};

gives the following output:

{ __cid: '__cid1',
  sql: 'create table "first" ("id" serial primary key, "name" varchar(255))',
  bindings: [] }
{ __cid: '__cid2',
  sql: 'create table "first" ("id" serial primary key, "name" varchar(255))',
  bindings: [] }
{ __cid: '__cid3',
  sql: 'create table "second" ("id" serial primary key, "name" varchar(255))',
  bindings: [] }
error: duplicate key value violates unique constraint "pg_type_typname_nsp_index"
    at Connection.parseE (/home/sohum/node_modules/pg/lib/connection.js:526:11)
    at Connection.parseMessage (/home/sohum/node_modules/pg/lib/connection.js:356:17)
    at Socket.<anonymous> (/home/sohum/node_modules/pg/lib/connection.js:105:22)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Socket.<anonymous> (_stream_readable.js:745:14)
    at Socket.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:407:10)
    at emitReadable (_stream_readable.js:403:5)
    at readableAddChunk (_stream_readable.js:165:9)
    at Socket.Readable.push (_stream_readable.js:127:10)

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:10 (10 by maintainers)

github_iconTop GitHub Comments

5reactions
tgriessercommented, Jun 16, 2014

So the confusion here is that the createTable method does not return a promise, but rather it returns a SchemaBuilder object, which is a “thenable”, i.e. calling .then on the object will return a valid A+ promise, but the object its self is not a promise.

This was done specifically to allow you to use the syntax:

  return knex.schema.createTable('first', function(table) {
    table.increments('id');
    table.string('name');
  })
  .createTable('second', function(table) {
      table.increments('id');
      table.string('name');
  }).then(function() {
    // all done
  });

which should run the migrations as expected on the same connection in sequence.

Also, there is no need for Promise.all here, as this would accomplish the same:

exports.up = function(knex, Promise) {
  return knex.schema.createTable('first', function(table) {
    table.increments('id');
    table.string('name');
  }).then(function() {
    return knex.schema.createTable('second', function(table) {
      table.increments('id');
      table.string('name');
    });
  });
};

though if you wanted, you could do:

exports.up = function(knex, Promise) {
  var first = knex.schema.createTable('first', function(table) {
    table.increments('id');
    table.string('name');
  }).then(); // coerce thenable to a promise

  var second = first.then(function() {
    return knex.schema.createTable('second', function(table) {
      table.increments('id');
      table.string('name');
    });
  });

  return Promise.all([first, second]);
};

and things would work as defined by the spec.

0reactions
SohumBcommented, Jun 16, 2014

Yea, we have more complicated dependency graphs than that; this was just a minimal test case! Thanks for the help.

@johanneslumpe

sohum@diurnal ~ % cat test.js
var Promise = require('bluebird');

function promises() {
  var first = Promise.resolve('wee');
  var second = first.then(function() {
    console.log('delayin');
    return Promise.delay(1000);
  }).then(function() {
    console.log('done!');
  });
  return first;
}

promises().then(function() { console.log('yep, first is finished'); });

sohum@diurnal ~ % node test.js
delayin
yep, first is finished
done!
Read more comments on GitHub >

github_iconTop Results From Across the Web

TSLint - Promises must be handled appropriately with `finally`
This is a complaint from the no-floating-promises rule. As per its description: Creating a Promise and not storing or returning it may let ......
Read more >
More Than a DREAM (Act), Less Than a Promise
The first bill introduced in the 116th Congress to offer a path to legal status to DREAMers, the American Dream and Promise Act...
Read more >
Migrants, states, and EU citizenship's unfulfilled promise
A constant aim of EU citizenship, and indeed the entire project of European integration, has always been to lower barriers and create a...
Read more >
Migrating to v6.0.0 - ESLint - Pluggable JavaScript Linter
no -async-promise-executor disallows using an async function as the argument ... not behave as expected. no-prototype-builtins reports method calls like foo.
Read more >
The Dream Act: An Overview | American Immigration Council
The two senators introduced identical legislation in the previous two sessions of Congress. The Dream and Promise Act of 2021 was introduced on ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found