Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction is not working #144

Closed
alickmail opened this issue Jan 24, 2019 · 3 comments
Closed

Transaction is not working #144

alickmail opened this issue Jan 24, 2019 · 3 comments

Comments

@alickmail
Copy link

alickmail commented Jan 24, 2019

I am not able to use transaction for model update, the transaction.commit().then() is fired, but the data on google console did not updated.

I have tried the Model.update function without using transaction, the data on google console is updated successfully

i am following the example from gitbook:
Link

Here is update model code:

function transferCoins(fromUser, toUser, coins) {
  return new Promise((resolve, reject) => {
    let fromUserObj = fromUser.plain();
    let toUserObj = toUser.plain();

    let transaction = gstore.transaction();
    transaction.run().then(() => {
      User.update(fromUserObj.id, {
        name : 'asdsadfssssf',
        coins: fromUserObj.coins - 1000
      }, null, null, transaction);

      transaction.commit().then((x) => {
        resolve();
      }).catch(err => {
        console.log({err});
      });

      // User.update(toUserObj.id, toUserObj.coins + 1000, null, null, transaction);
    }).catch(err => {
      transaction.rollback();
      reject(err);
    });
  });
}

Here is the model file

const gstore = require('gstore-node')();
const Schema = gstore.Schema;
const Joi = require('joi');

const userSchema = new Schema({
  name        : {joi: Joi.string().required()},
  lastname    : {joi: Joi.string()},
  password    : {joi: Joi.string()},
  coins       : {joi: Joi.number().integer().min(0)},
  email       : {joi: Joi.string().email()},
  createdAt   : {joi: Joi.date()},
  access_token: {joi: [Joi.string(), Joi.number()]},
  birthyear   : {joi: Joi.number().integer().min(1900).max(2013)},
}, {joi: true});


const User = gstore.model('User', userSchema);

module.exports = User;

Please help, thanks!

@sebelga
Copy link
Owner

sebelga commented Jan 25, 2019

Hello,
Thanks for reporting, your code looks ok so I will try to reproduce and let you know.
cheers

@sebelga
Copy link
Owner

sebelga commented Feb 4, 2019

Hi @alickmail

I just released v5.0.0 that should fix this bug. There was indeed a bug in the Model.update() method when using transaction.

Once you update the gstore version (make sure you update how you instantiate gstore, there is a breaking change), you will need to make a small change in your code:

...
function transferCoins(fromUser, toUser, amount) {
    const transaction = gstore.transaction();
    return transaction.run()
        .then(async () => {
            await User.update(fromUser.entityKey.id, {
                coins: fromUser.coins - amount,
            }, null, null, transaction);

            await User.update(toUser.entityKey.id, {
                coins: toUser.coins + amount,
            }, null, null, transaction);

            return transaction.commit();
        }).catch((err) => {
            transaction.rollback();
            throw err;
        });
}


// ----------------------------
// Or without "async" and "waiting" if you already have fetched the entity data previously

function transferCoins(fromUser, toUser, amount) {
    const transaction = gstore.transaction();
    return transaction.run()
        .then(() => {
            const fromUserUpdated = new User({
                ...fromUser.entityData,
                coins: fromUser.coins - amount},
                fromUser.entityKey.id
            );

            const toUserUpdated = new User({
                ...toUser.entityData,
                coins: toUser.coins + amount},
                toUser.entityKey.id
            );

            fromUserUpdated.save(transaction);
            toUserUpdated.save(transaction);

            return transaction.commit();
        }).catch((err) => {
            transaction.rollback();
            throw err;
        });
}

@sebelga
Copy link
Owner

sebelga commented Feb 4, 2019

You use case made me think that it'd be useful to add a sort of updater() or increment functionality to dyncamically update a value.

Be careful that you might run in a race condition if 2 requests fetch the fromUser entity at the same time, (so they both have the same initial "coins" value) and then try to update the same user at slightly different times...
You might want to think in a way to "lock" an entity when fetching the user so when a second request tries to update the user and the lock version mismatch you cancel the second request.

Closing the issue. Feel free to reopen if you still have a problem.

@sebelga sebelga closed this as completed Feb 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants