From 292cd479ba29cb9e28f1972f1917715291a1815e Mon Sep 17 00:00:00 2001
From: Ilya <markovilya197@gmail.com>
Date: Fri, 16 Jun 2017 18:21:57 +0300
Subject: [PATCH] Add a wrapper for box.begin/box.commit call

Add box.atomic(fun, arg) wrapper to execute fun(arg) in a transaction.

Closes #818
---
 src/box/lua/schema.lua        | 15 +++++++
 test/box/misc.result          |  3 +-
 test/box/transaction.result   | 80 +++++++++++++++++++++++++++++++++++
 test/box/transaction.test.lua | 42 ++++++++++++++++++
 4 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 0041286b63..88c912f6cc 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -228,6 +228,21 @@ box.begin = function()
         box.error()
     end
 end
+
+local function atomic_tail(status, ...)
+    if not status then
+        box.rollback()
+        error((...), 2)
+     end
+     box.commit()
+     return ...
+end
+
+box.atomic = function(fun, ...)
+    box.begin()
+    return atomic_tail(pcall(fun, ...))
+end
+
 -- box.commit yields, so it's defined as Lua/C binding
 -- box.rollback yields as well
 
diff --git a/test/box/misc.result b/test/box/misc.result
index e8ff143619..cf56fd4750 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -55,7 +55,8 @@ t = {} for n in pairs(box) do table.insert(t, tostring(n)) end table.sort(t)
 ...
 t
 ---
-- - backup
+- - atomic
+  - backup
   - begin
   - cfg
   - commit
diff --git a/test/box/transaction.result b/test/box/transaction.result
index 9c24d1f7b2..746f7e12c2 100644
--- a/test/box/transaction.result
+++ b/test/box/transaction.result
@@ -423,3 +423,83 @@ function gh_1638() box.begin(); box.rollback() end
 for i = 1, 1000 do fiber.create(function() gh_1638() end) end
 ---
 ...
+--
+--gh-818 add atomic()
+--
+space = box.schema.space.create('atomic')
+---
+...
+index = space:create_index('primary')
+---
+...
+test_run:cmd("setopt delimiter ';'")
+---
+- true
+...
+function args(...)
+    return 'args', ...
+end;
+---
+...
+box.atomic(args, 1, 2, 3, 4, 5);
+---
+- args
+- 1
+- 2
+- 3
+- 4
+- 5
+...
+function tx()
+    space:auto_increment{'first row'}
+    space:auto_increment{'second row'}
+    return space:select{}
+end;
+---
+...
+box.atomic(tx);
+---
+- - [1, 'first row']
+  - [2, 'second row']
+...
+function tx_error(space)
+    space:auto_increment{'third'}
+    space:auto_increment{'fourth'}
+    error("some error")
+end;
+---
+...
+box.atomic(tx_error, space);
+---
+- error: '[string "function tx_error(space)     space:auto_incre..."]:1: some error'
+...
+function nested(space)
+    box.begin()
+end;
+---
+...
+box.atomic(nested, space);
+---
+- error: 'Operation is not permitted when there is an active transaction '
+...
+function rollback(space)
+    space:auto_increment{'fifth'}
+    box.rollback()
+end;
+---
+...
+box.atomic(rollback, space);
+---
+...
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
+space:select{}
+---
+- - [1, 'first row']
+  - [2, 'second row']
+...
+space:drop()
+---
+...
diff --git a/test/box/transaction.test.lua b/test/box/transaction.test.lua
index 22e6e6cca9..cda0eb151a 100644
--- a/test/box/transaction.test.lua
+++ b/test/box/transaction.test.lua
@@ -195,3 +195,45 @@ box.space.test:drop()
 --
 function gh_1638() box.begin(); box.rollback() end
 for i = 1, 1000 do fiber.create(function() gh_1638() end) end
+
+--
+--gh-818 add atomic()
+--
+space = box.schema.space.create('atomic')
+index = space:create_index('primary')
+test_run:cmd("setopt delimiter ';'")
+
+function args(...)
+    return 'args', ...
+end;
+box.atomic(args, 1, 2, 3, 4, 5);
+
+function tx()
+    space:auto_increment{'first row'}
+    space:auto_increment{'second row'}
+    return space:select{}
+end;
+box.atomic(tx);
+
+function tx_error(space)
+    space:auto_increment{'third'}
+    space:auto_increment{'fourth'}
+    error("some error")
+end;
+box.atomic(tx_error, space);
+
+function nested(space)
+    box.begin()
+end;
+box.atomic(nested, space);
+
+function rollback(space)
+    space:auto_increment{'fifth'}
+    box.rollback()
+end;
+box.atomic(rollback, space);
+
+test_run:cmd("setopt delimiter ''");
+space:select{}
+
+space:drop()
-- 
GitLab