@@ -2130,32 +2130,46 @@ def processRequest(self, request: Request, frm: str):
2130
2130
# TODO: What if the reply was a REQNACK? Its not gonna be found in the
2131
2131
# replies.
2132
2132
2133
- if request .operation [TXN_TYPE ] == GET_TXN :
2133
+ txn_type = request .operation [TXN_TYPE ]
2134
+
2135
+ if self .is_action (txn_type ):
2136
+ self .process_action (request , frm )
2137
+
2138
+ elif txn_type == GET_TXN :
2134
2139
self .handle_get_txn_req (request , frm )
2135
2140
self .total_read_request_number += 1
2136
- return
2137
-
2138
- ledger_id = self .ledger_id_for_request (request )
2139
- ledger = self .getLedger (ledger_id )
2140
2141
2141
- if self .is_query (request . operation [ TXN_TYPE ] ):
2142
+ elif self .is_query (txn_type ):
2142
2143
self .process_query (request , frm )
2143
- return
2144
+ self . total_read_request_number += 1
2144
2145
2145
- reply = self .getReplyFromLedger (ledger , request )
2146
- if reply :
2147
- logger .debug ("{} returning REPLY from already processed "
2148
- "REQUEST: {}" .format (self , request ))
2149
- self .transmitToClient (reply , frm )
2150
- return
2146
+ elif self .is_txn_writable (txn_type ):
2147
+ reply = self .getReplyFromLedgerForRequest (request )
2148
+ if reply :
2149
+ logger .debug ("{} returning REPLY from already processed "
2150
+ "REQUEST: {}" .format (self , request ))
2151
+ self .transmitToClient (reply , frm )
2152
+ return
2151
2153
2152
- # If the node is not already processing the request
2153
- if not self .isProcessingReq (request .key ):
2154
- self .startedProcessingReq (request .key , frm )
2155
- # If not already got the propagate request(PROPAGATE) for the
2156
- # corresponding client request(REQUEST)
2157
- self .recordAndPropagate (request , frm )
2158
- self .send_ack_to_client ((request .identifier , request .reqId ), frm )
2154
+ # If the node is not already processing the request
2155
+ if not self .isProcessingReq (request .key ):
2156
+ self .startedProcessingReq (request .key , frm )
2157
+ if request .isForced ():
2158
+ # forced request should be processed before consensus
2159
+ req_handler = self .get_req_handler (txn_type = txn_type )
2160
+ req_handler .validate (request )
2161
+ req_handler .applyForced (request )
2162
+
2163
+ # If not already got the propagate request(PROPAGATE) for the
2164
+ # corresponding client request(REQUEST)
2165
+ self .recordAndPropagate (request , frm )
2166
+ self .send_ack_to_client ((request .identifier , request .reqId ), frm )
2167
+
2168
+ else :
2169
+ raise InvalidClientRequest (
2170
+ request .identifier ,
2171
+ request .reqId ,
2172
+ 'Pool is in readonly mode, try again in 60 seconds' )
2159
2173
2160
2174
def is_query (self , txn_type ) -> bool :
2161
2175
# Does the transaction type correspond to a read?
@@ -2167,6 +2181,9 @@ def is_query(self, txn_type) -> bool:
2167
2181
def is_action (self , txn_type ) -> bool :
2168
2182
return txn_type in self .actionReqHandler .operation_types
2169
2183
2184
+ def is_txn_writable (self , txn_type ):
2185
+ return True
2186
+
2170
2187
def process_query (self , request : Request , frm : str ):
2171
2188
# Process a read request from client
2172
2189
handler = self .get_req_handler (txn_type = request .operation [TXN_TYPE ])
@@ -2213,13 +2230,19 @@ def processPropagate(self, msg: Propagate, frm):
2213
2230
2214
2231
if not self .isProcessingReq (request .key ):
2215
2232
ledger_id , seq_no = self .seqNoDB .get (request .key )
2216
- if seq_no is not None :
2233
+ if ledger_id is not None and seq_no is not None :
2217
2234
logger .debug ("{} ignoring propagated request {} "
2218
2235
"since it has been already ordered"
2219
2236
.format (self .name , msg ))
2220
2237
return
2221
2238
2222
2239
self .startedProcessingReq (request .key , clientName )
2240
+ if request .isForced ():
2241
+ # forced request should be processed before consensus
2242
+ req_handler = self .get_req_handler (
2243
+ txn_type = request .operation [TXN_TYPE ])
2244
+ req_handler .validate (request )
2245
+ req_handler .applyForced (request )
2223
2246
2224
2247
else :
2225
2248
if clientName is not None and \
@@ -2264,17 +2287,20 @@ def handle_get_txn_req(self, request: Request, frm: str):
2264
2287
'Invalid ledger id {}' .format (ledger_id ),
2265
2288
frm )
2266
2289
return
2290
+
2267
2291
seq_no = request .operation .get (DATA )
2268
2292
self .send_ack_to_client ((request .identifier , request .reqId ), frm )
2269
2293
ledger = self .getLedger (ledger_id )
2294
+
2270
2295
try :
2271
- txn = self .getReplyFromLedger (ledger = ledger ,
2272
- seq_no = seq_no )
2296
+ txn = self .getReplyFromLedger (ledger , seq_no )
2273
2297
except KeyError :
2298
+ txn = None
2299
+
2300
+ if txn is None :
2274
2301
logger .debug (
2275
2302
"{} can not handle GET_TXN request: ledger doesn't "
2276
2303
"have txn with seqNo={}" . format (self , str (seq_no )))
2277
- txn = None
2278
2304
2279
2305
result = {
2280
2306
f .IDENTIFIER .nm : request .identifier ,
@@ -3029,17 +3055,24 @@ def sendToNodes(self, msg: Any, names: Iterable[str] = None, message_splitter=No
3029
3055
) if r .name in names ] if names else []
3030
3056
self .send (msg , * rids , message_splitter = message_splitter )
3031
3057
3032
- def getReplyFromLedger (self , ledger , request = None , seq_no = None ):
3058
+ def getReplyFromLedgerForRequest (self , request ):
3059
+ ledger_id , seq_no = self .seqNoDB .get (request .digest )
3060
+ if ledger_id is not None and seq_no is not None :
3061
+ ledger = self .getLedger (ledger_id )
3062
+ return self .getReplyFromLedger (ledger , seq_no )
3063
+ else :
3064
+ return None
3065
+
3066
+ def getReplyFromLedger (self , ledger , seq_no ):
3033
3067
# DoS attack vector, client requesting already processed request id
3034
3068
# results in iterating over ledger (or its subset)
3035
- if seq_no is None :
3036
- ledger_id , seq_no = self .seqNoDB .get (request .digest )
3037
- if seq_no :
3038
- txn = ledger .getBySeqNo (int (seq_no ))
3039
- if txn :
3040
- txn .update (ledger .merkleInfo (seq_no ))
3041
- txn = self .update_txn_with_extra_data (txn )
3042
- return Reply (txn )
3069
+ txn = ledger .getBySeqNo (int (seq_no ))
3070
+ if txn :
3071
+ txn .update (ledger .merkleInfo (seq_no ))
3072
+ txn = self .update_txn_with_extra_data (txn )
3073
+ return Reply (txn )
3074
+ else :
3075
+ return None
3043
3076
3044
3077
def update_txn_with_extra_data (self , txn ):
3045
3078
"""
0 commit comments