Search code examples
rethinkdbrethinkdb-javascript

`waitForIndex` does not work correctly


When starting script below, I got an error that stuck on

Something bad heppened while waiting for index created
Index `createdAt` was not found on table `olive.todos`
r.table("todos").indexWait("createdAt")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

but starting script again, I have no problem.

Is this RethinkDB's problem or mine? And tell me the solution.

const createIndex = (conn, tableName, indexName) =>
  r.table(tableName).indexList().contains(indexName)
    .do(containsIndex =>
      r.branch(
        containsIndex,
        { created: 0 },
        r.table(tableName).indexCreate(indexName)
      )
    )
    ...

const waitForIndex = (conn, tableName, indexName) =>
  r.table(tableName).indexWait(indexName)
    ...

export const setup = startApp => {
  r.connect(config.rethinkdb)
    ...
    .then(conn => {
      Promise.all([
        createIndex(conn, 'todos', 'createdAt'),
        createIndex(conn, 'days', 'date'),
      ]);
      return conn;
    })
    .then(conn =>
      Promise.all([
        waitForIndex(conn, 'todos', 'createdAt'),
        waitForIndex(conn, 'days', 'date'),
      ])
    )
    ...
};

Solution

  • You seems mixed the API of different Promise API. I don't see you import Promise from anywhere. I supposed you are using built-in JavaScript Promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    When you use Promise.all, you have to chain it with then, instead of using return as next statement. Chain to then with resolver/reject.

    Your code use return so right after Promise.all but you don't call then, so it returns instanly and the index hasn't ready to be created yet.

    This code works:

    import r from 'rethinkdb';
    import config from '../config';
    
    const createDatabase = (conn, name) =>
      r.dbList().contains(name)
        .do(containsDb =>
          r.branch(
            containsDb,
            { created: 0 },
            r.dbCreate(name)
          )
        )
        .run(conn)
        .error(err => {
          console.log(`Could not create ${name} DB`);
          console.log(err.message || 'Something bad happened');
          process.exit(1);
        });
    
    const createTable = (conn, name) =>
      r.tableList().contains(name)
        .do(containsTable =>
          r.branch(
            containsTable,
            { created: 0 },
            r.tableCreate(name)
          )
        )
        .run(conn)
        .error(err => {
          console.log(`Could not create ${name} table`);
          console.log(err.message || 'Somthing bad happened');
          process.exit(1);
        });
    
    const createIndex = (conn, tableName, indexName) =>
      r.table(tableName).indexList().contains(indexName)
        .do(containsIndex =>
          r.branch(
            containsIndex,
            { created: 0 },
            r.table(tableName).indexCreate(indexName)
          )
        )
        .run(conn)
        .error(err => {
          console.log(`Could not crate index ${indexName} in ${tableName}`);
          console.log(err.message || 'Something bad happened');
          process.exit(1);
        });
    
    const waitForIndex = (conn, tableName, indexName) =>
      r.table(tableName).indexWait(indexName)
        .run(conn)
        .error(err => {
          console.log('Something bad happened while waiting for index created');
          console.log(err.message || 'Something bad happened');
          process.exit(1);
        });
    
    export const setup = startApp => {
      r.connect(config.rethinkdb)
        .then(conn => {
          createDatabase(conn, 'test');
          return conn;
        })
        .then(conn => {
          return Promise.all([
            createTable(conn, 'todos'),
            createTable(conn, 'days'),
          ]).then((result) => conn, (reason) => conn)
        })
        .then(conn => {
          return Promise.all([
            createIndex(conn, 'todos', 'createdAt'),
            createIndex(conn, 'days', 'date'),
          ]).then(() =>  conn, () => conn)
        })
        .then(conn => {
            return Promise.all([
              waitForIndex(conn, 'todos', 'createdAt'),
              waitForIndex(conn, 'days', 'date'),
            ])
          }
        )
        .then(() => {
          console.log('DB and tables are available, starting Koa ...');
          startApp();
        })
        .error(err => {
          console.log('Could not open a connection to initiailize the database');
          console.log(err.message || 'Something bad happened');
          process.exit(1);
        });
    };
    
    setup()
    

    Notice that we have to use then to pass down conn object, not by returning