tarantool / crud

Easy assess to data stored in vshard cluster
BSD 2-Clause "Simplified" License
40 stars 14 forks source link

Implement interactive transactions #31

Open knazarov opened 3 years ago

knazarov commented 3 years ago

Interactive transactions have made it into the core recently. They allow us to open a transaction and do selects/updates with yield. I suggest that we add support for them to crud.

Unfortunately, we won't get multi-node transactions, but since we have an understanding of which shard the operation will go to, we can still allow transactional operations if they touch only one storage.

This should be pretty easy to implement: if we open a transaction, record which node the first operation goes to, then make sure all other operations in the transaction go to the same node. If not, abort the operation or the whole transaction.

knazarov commented 3 years ago

Usage scenario:

local transaction_id  = crud.transaction_begin({timeout=10}) -- seconds

local user = crud.get('user', 1)
local amount = 100

local saving = crud.select('account',
                           {{'=', 'user_id', user.id}, {'=', 'account_type', 'saving'}},
                           {transaction=transaction_id})

if saving.amount > amount then
    saving.amount = saving.amount - amount
    crud.replace('account', saving, {transaction=transaction_id})

    local primary = crud.select('account',
                                {{'=', 'user_id', user.id}, {'=', 'account_type', 'primary'}},
                                {transaction=transaction_id})
    primary.amount = primary.amount + amount

    crud.replace('account', primary, {transaction=transaction_id})
    crud.transaction_commit(transaction_id)
else
    crud.transaction_abort(transaction_id)
    log.error('Insufficient funds on saving account for user %s', user.name)
end
knazarov commented 3 years ago

This approach will also map quite well onto GraphQL in Data Grid.

Totktonada commented 3 years ago

Interactive transactions have made it into the core recently.

Just note: https://github.com/tarantool/tarantool/issues/4897 is done (we consider it as beta now), https://github.com/tarantool/tarantool/issues/2016 is not.

knazarov commented 3 years ago

@Totktonada for crud we don’t need support from iproto.

knazarov commented 3 years ago

This is how to use interactive transactions

#!/usr/bin/env tarantool

local fiber = require('fiber')

-- If you just use box.cfg{}, this app will fail
box.cfg{memtx_use_mvcc_engine=true}
--box.cfg{}

box.schema.space.create('account', {if_not_exists=true})
box.space.account:format({ {name='id',type='unsigned'},
      {name='first_name',type='string'},
      {name='last_name',type='string'},
})

box.begin()
box.space.account:put({2, "John", "Doe"})

print("sleeping")
fiber.sleep(1)
print("woke up")

box.space.account:put({3, "Ivan", "Ivanov"})

box.commit()

os.exit(0)