@@ -4,11 +4,12 @@ use common::try_spawn;
4
4
use enclose:: enclose;
5
5
use ethcore:: client:: { BlockChainClient , BlockId , ChainNotify , ChainRouteType , NewBlocks } ;
6
6
use ethcore:: miner;
7
- use failure:: { Error , ResultExt } ;
8
- use futures:: future:: lazy;
7
+ use ethereum_types:: H256 ;
8
+ use failure:: { format_err, Error } ;
9
+ use futures:: future:: { err, lazy} ;
9
10
use handler:: { Handler , Sender } ;
10
11
use parity_runtime:: Executor ;
11
- use rabbitmq_adaptor:: { ConsumerResult , RabbitConnection , RabbitExt } ;
12
+ use rabbitmq_adaptor:: { ConsumerResult , DeliveryExt , RabbitConnection , RabbitExt } ;
12
13
use serde:: Deserialize ;
13
14
use serde_json;
14
15
use std:: sync:: Arc ;
@@ -21,7 +22,10 @@ use DEFAULT_REPLY_QUEUE;
21
22
use LOG_TARGET ;
22
23
use NEW_BLOCK_EXCHANGE_NAME ;
23
24
use NEW_BLOCK_ROUTING_KEY ;
25
+ use OPERATION_ID ;
24
26
use PUBLIC_TRANSACTION_QUEUE ;
27
+ use TX_ERROR_EXCHANGE_NAME ;
28
+ use TX_ERROR_ROUTING_KEY ;
25
29
26
30
#[ derive( Debug , Default , Clone , PartialEq ) ]
27
31
pub struct RabbitMqConfig {
@@ -38,6 +42,20 @@ pub struct PubSubClient<C> {
38
42
#[ derive( Deserialize ) ]
39
43
struct TransactionMessage {
40
44
pub data : Bytes ,
45
+ pub transaction_hash : H256 ,
46
+ }
47
+
48
+ #[ derive( Serialize ) ]
49
+ struct TransactionErrorMessage {
50
+ pub transaction_hash : H256 ,
51
+ pub error_message : String ,
52
+ pub error_type : ErrorType ,
53
+ }
54
+
55
+ #[ derive( Serialize ) ]
56
+ pub enum ErrorType {
57
+ LocalTransactionError ,
58
+ TransactionRejected ,
41
59
}
42
60
43
61
impl < C : ' static + miner:: BlockChainClient + BlockChainClient > PubSubClient < C > {
@@ -58,21 +76,42 @@ impl<C: 'static + miner::BlockChainClient + BlockChainClient> PubSubClient<C> {
58
76
. clone ( )
59
77
. register_consumer (
60
78
PUBLIC_TRANSACTION_QUEUE . to_string ( ) ,
61
- enclose ! ( ( ) move |message| {
62
- Box :: new( std:: str :: from_utf8( & message. data)
63
- . map_err( Error :: from)
64
- . and_then( |payload| {
65
- serde_json:: from_str( payload)
66
- . context( "Could not deserialize AMQP message payload" )
67
- . map_err( Error :: from)
68
- } )
69
- . and_then( |transaction_message: TransactionMessage | {
70
- sender_handler. send_transaction( transaction_message. data)
71
- . context( format!( "Failed to send transaction" ) )
72
- . map_err( Error :: from)
73
- } )
79
+ enclose ! ( ( rabbit) move |message| {
80
+ let operation_id = message. get_header( OPERATION_ID ) ;
81
+ if operation_id. is_none( ) {
82
+ return Box :: new( err( format_err!( "Missing protocol-id header" ) ) ) ;
83
+ }
84
+ let operation_id = operation_id. unwrap( ) ;
85
+ let payload = std:: str :: from_utf8( & message. data) ;
86
+ if payload. is_err( ) {
87
+ return Box :: new( err( format_err!( "Could not parse AMQP message" ) ) ) ;
88
+ }
89
+ let payload = payload. unwrap( ) ;
90
+ let transaction_message = serde_json:: from_str( payload) ;
91
+ if transaction_message. is_err( ) {
92
+ return Box :: new( err( format_err!( "Could not deserialize AMQP message payload" ) ) ) ;
93
+ }
94
+ let transaction_message: TransactionMessage = transaction_message. unwrap( ) ;
95
+ let transaction_hash = transaction_message. transaction_hash;
96
+ Box :: new( sender_handler. send_transaction( transaction_message. data)
97
+ . map( |_| ( ) )
74
98
. into_future( )
75
- . map( |_| ConsumerResult :: ACK ) )
99
+ . or_else( enclose!( ( rabbit) move |error| {
100
+ let tx_error = TransactionErrorMessage {
101
+ transaction_hash,
102
+ error_message: format!( "{}" , error) ,
103
+ error_type: ErrorType :: LocalTransactionError ,
104
+ } ;
105
+ let serialized_message = serde_json:: to_string( & tx_error) . unwrap( ) ;
106
+ rabbit. clone( ) . publish(
107
+ TX_ERROR_EXCHANGE_NAME . to_string( ) ,
108
+ TX_ERROR_ROUTING_KEY . to_string( ) ,
109
+ serialized_message. into( ) ,
110
+ vec![ ( OPERATION_ID . to_string( ) , operation_id) ] ,
111
+ ) . map( |_| ( ) )
112
+ } ) )
113
+ . map( |_| ConsumerResult :: ACK )
114
+ )
76
115
} ) ,
77
116
)
78
117
. map_err ( Error :: from)
0 commit comments