@@ -24,6 +24,17 @@ defmodule Srh.Http.CommandHandler do
2424 end
2525 end
2626
27+ def handle_command_transaction_array ( conn , token ) do
28+ # Transactions use the same body format as pipelines, so we can use the same validator
29+ case RequestValidator . validate_pipeline_redis_body ( conn . body_params ) do
30+ { :ok , array_of_command_arrays } ->
31+ do_handle_command_transaction_array ( array_of_command_arrays , token )
32+
33+ { :error , error_message } ->
34+ { :malformed_data , error_message }
35+ end
36+ end
37+
2738 defp do_handle_command ( command_array , token ) do
2839 case TokenResolver . resolve ( token ) do
2940 { :ok , connection_info } ->
@@ -44,6 +55,16 @@ defmodule Srh.Http.CommandHandler do
4455 end
4556 end
4657
58+ defp do_handle_command_transaction_array ( array_of_command_arrays , token ) do
59+ case TokenResolver . resolve ( token ) do
60+ { :ok , connection_info } ->
61+ dispatch_command_transaction_array ( array_of_command_arrays , connection_info )
62+
63+ { :error , msg } ->
64+ { :not_authorized , msg }
65+ end
66+ end
67+
4768 defp dispatch_command_array ( _arr , _connection_info , responses \\ [ ] )
4869
4970 defp dispatch_command_array ( [ current | rest ] , connection_info , responses ) do
@@ -52,9 +73,8 @@ defmodule Srh.Http.CommandHandler do
5273 { :ok , result_map } ->
5374 [ result_map | responses ]
5475
55- { :malformed_data , result_json } ->
56- # TODO: change up the chain to json this at the last moment, so this isn't here
57- [ Jason . decode! ( result_json ) | responses ]
76+ { :redis_error , result } ->
77+ [ result | responses ]
5878 end
5979
6080 dispatch_command_array ( rest , connection_info , updated_responses )
@@ -65,6 +85,61 @@ defmodule Srh.Http.CommandHandler do
6585 { :ok , Enum . reverse ( responses ) }
6686 end
6787
88+ defp dispatch_command_transaction_array (
89+ command_array ,
90+ % { "srh_id" => srh_id , "max_connections" => max_connections } = connection_info ,
91+ responses \\ [ ]
92+ ) do
93+ case GenRegistry . lookup_or_start ( Client , srh_id , [ max_connections , connection_info ] ) do
94+ { :ok , client_pid } ->
95+ # Borrow a client, then run all of the commands (wrapped in MULTI and EXEC)
96+ worker_pid = Client . borrow_worker ( client_pid )
97+
98+ wrapped_command_array = [ [ "MULTI" ] | command_array ]
99+ do_dispatch_command_transaction_array ( wrapped_command_array , worker_pid , responses )
100+
101+ # Now manually run the EXEC - this is what contains the information to form the response, not the above
102+ result = case ClientWorker . redis_command ( worker_pid , [ "EXEC" ] ) do
103+ { :ok , res } ->
104+ {
105+ :ok ,
106+ res
107+ |> Enum . map ( & ( % { result: & 1 } ) )
108+ }
109+ # TODO: Can there be any inline errors here? Wouldn't they fail the whole tx?
110+
111+ { :error , error } ->
112+ { :redis_error , % { error: error . message } }
113+ end
114+
115+ Client . return_worker ( client_pid , worker_pid )
116+
117+ result
118+ { :error , msg } ->
119+ { :server_error , msg }
120+ end
121+ end
122+
123+ defp do_dispatch_command_transaction_array ( [ current | rest ] , worker_pid , responses ) when is_pid ( worker_pid ) do
124+ updated_responses = case ClientWorker . redis_command ( worker_pid , current ) do
125+ { :ok , res } ->
126+ [ % { result: res } | responses ]
127+
128+ { :error , error } ->
129+ [
130+ % {
131+ error: error . message
132+ } | responses
133+ ]
134+ end
135+
136+ do_dispatch_command_transaction_array ( rest , worker_pid , updated_responses )
137+ end
138+
139+ defp do_dispatch_command_transaction_array ( [ ] , worker_pid , responses ) when is_pid ( worker_pid ) do
140+ { :ok , Enum . reverse ( responses ) }
141+ end
142+
68143 defp dispatch_command (
69144 command_array ,
70145 % { "srh_id" => srh_id , "max_connections" => max_connections } = connection_info
@@ -80,10 +155,10 @@ defmodule Srh.Http.CommandHandler do
80155
81156 { :error , error } ->
82157 {
83- :malformed_data ,
84- Jason . encode! ( % {
158+ :redis_error ,
159+ % {
85160 error: error . message
86- } )
161+ }
87162 }
88163 end
89164
0 commit comments