@@ -3,55 +3,25 @@ local vshard = require('vshard')
33local errors = require (' errors' )
44
55local dev_checks = require (' crud.common.dev_checks' )
6- local registry = require (' crud.common.registry' )
76local utils = require (' crud.common.utils' )
87
98local CallError = errors .new_class (' Call' )
109local NotInitializedError = errors .new_class (' NotInitialized' )
1110
1211local call = {}
1312
14- local CALL_FUNC_NAME = ' __call'
15-
1613local DEFAULT_VSHARD_CALL_TIMEOUT = 2
1714
18- --- Initializes call on node
19- --
20- -- Wrapper function is registered to call functions remotely.
21- --
22- -- @function init
23- --
24- function call .init ()
25- local function call (opts )
26- dev_checks ({
27- func_name = ' string' ,
28- func_args = ' ?table' ,
29- })
30-
31- local func = registry .get (opts .func_name ) or rawget (_G , opts .func_name )
32-
33- if type (func ) ~= ' function' then
34- return nil , CallError :new (' Function %s is not registered' , opts .func_name )
35- end
36-
37- return func (unpack (opts .func_args or {}))
38- end
39-
40- -- register global function
41- rawset (_G , CALL_FUNC_NAME , call )
42- end
43-
4415local function call_on_replicaset (replicaset , channel , vshard_call , func_name , func_args , opts )
45- local elect_call_arg = {
46- func_name = func_name ,
47- func_args = func_args ,
48- }
49-
5016 -- replicaset:<vshard_call>(func_name,...)
51- local func_ret , err = replicaset [vshard_call ](replicaset , CALL_FUNC_NAME , { elect_call_arg } , opts )
17+ local func_ret , err = replicaset [vshard_call ](replicaset , func_name , func_args , opts )
5218 if type (err ) == ' table' and err .type == ' ClientError' and type (err .message ) == ' string' then
53- if err .message == string.format (" Procedure '%s' is not defined" , CALL_FUNC_NAME ) then
54- err = NotInitializedError :new (" crud isn't initialized on replicaset" )
19+ if err .message == string.format (" Procedure '%s' is not defined" , func_name ) then
20+ if func_name :startswith (' _crud.' ) then
21+ err = NotInitializedError :new (" crud isn't initialized on replicaset" )
22+ else
23+ err = NotInitializedError :new (" Function %s is not registered" , func_name )
24+ end
5525 end
5626 end
5727
@@ -165,4 +135,41 @@ function call.ro(func_name, func_args, opts)
165135 return call_impl (' callro' , func_name , func_args , opts )
166136end
167137
138+ --- Calls specified function on a node according to bucket_id.
139+ --
140+ -- Exactly mimics the contract of vshard.router.callrw, but adds
141+ -- better error hangling
142+ --
143+ -- @function rw_single
144+ --
145+ function call .rw_single (bucket_id , func_name , func_args , options )
146+ local res , err = vshard .router .callrw (bucket_id , func_name , func_args , options )
147+
148+ -- This is a workaround, until vshard supports telling us where the error happened
149+ if err ~= nil then
150+ if type (err ) == ' table' and err .type == ' ClientError' and type (err .message ) == ' string' then
151+ if err .message == string.format (" Procedure '%s' is not defined" , func_name ) then
152+ err = NotInitializedError :new (" crud isn't initialized on replicaset" )
153+ end
154+ end
155+
156+ local replicaset , _ = vshard .router .route (bucket_id )
157+ if replicaset == nil then
158+ return nil , CallError :new (
159+ " Function returned an error, but we couldn't figure out the replicaset: %s" , err
160+ )
161+ end
162+
163+ return nil , CallError :new (utils .format_replicaset_error (
164+ replicaset .uuid , " Function returned an error: %s" , err
165+ ))
166+ end
167+
168+ if res == box .NULL then
169+ return nil
170+ end
171+
172+ return res
173+ end
174+
168175return call
0 commit comments