69
69
// GreeterHandler provides a NATS subscription handler that can serve a
70
70
// subscription using a given GreeterServer implementation.
71
71
type GreeterHandler struct {
72
- ctx context.Context
73
- nc nrpc.NatsConn
74
- server GreeterServer
72
+ ctx context.Context
73
+ workers * nrpc.WorkerPool
74
+ nc nrpc.NatsConn
75
+ server GreeterServer
75
76
}
76
77
77
78
func NewGreeterHandler (ctx context.Context , nc nrpc.NatsConn , s GreeterServer ) * GreeterHandler {
@@ -82,13 +83,26 @@ func NewGreeterHandler(ctx context.Context, nc nrpc.NatsConn, s GreeterServer) *
82
83
}
83
84
}
84
85
86
+ func NewGreeterConcurrentHandler (workers * nrpc.WorkerPool , nc nrpc.NatsConn , s GreeterServer ) * GreeterHandler {
87
+ return & GreeterHandler {
88
+ workers : workers ,
89
+ nc : nc ,
90
+ server : s ,
91
+ }
92
+ }
93
+
85
94
func (h * GreeterHandler ) Subject () string {
86
95
return "helloworld.Greeter.>"
87
96
}
88
97
89
98
func (h * GreeterHandler ) Handler (msg * nats.Msg ) {
90
- var encoding string
91
- var noreply bool
99
+ var ctx context.Context
100
+ if h .workers != nil {
101
+ ctx = h .workers .Context
102
+ } else {
103
+ ctx = h .ctx
104
+ }
105
+ request := nrpc .NewRequest (ctx , h .nc , msg .Subject , msg .Reply )
92
106
// extract method name & encoding from subject
93
107
_ , _ , name , tail , err := nrpc .ParseSubject (
94
108
"helloworld" , 0 , "Greeter" , 0 , msg .Subject )
@@ -97,71 +111,83 @@ func (h *GreeterHandler) Handler(msg *nats.Msg) {
97
111
return
98
112
}
99
113
100
- ctx := h .ctx
114
+ request .MethodName = name
115
+ request .SubjectTail = tail
116
+
101
117
// call handler and form response
102
- var resp proto.Message
103
- var replyError * nrpc.Error
104
- var elapsed float64
118
+ var immediateError * nrpc.Error
105
119
switch name {
106
120
case "SayHello" :
107
- _ , encoding , err = nrpc .ParseSubjectTail (0 , tail )
121
+ _ , request . Encoding , err = nrpc .ParseSubjectTail (0 , request . SubjectTail )
108
122
if err != nil {
109
123
log .Printf ("SayHelloHanlder: SayHello subject parsing failed: %v" , err )
110
124
break
111
125
}
112
126
var req HelloRequest
113
- if err := nrpc .Unmarshal (encoding , msg .Data , & req ); err != nil {
127
+ if err := nrpc .Unmarshal (request . Encoding , msg .Data , & req ); err != nil {
114
128
log .Printf ("SayHelloHandler: SayHello request unmarshal failed: %v" , err )
115
- replyError = & nrpc.Error {
129
+ immediateError = & nrpc.Error {
116
130
Type : nrpc .Error_CLIENT ,
117
131
Message : "bad request received: " + err .Error (),
118
132
}
119
133
serverRequestsForGreeter .WithLabelValues (
120
- "SayHello" , encoding , "unmarshal_fail" ).Inc ()
134
+ "SayHello" , request . Encoding , "unmarshal_fail" ).Inc ()
121
135
} else {
122
- start := time .Now ()
123
- resp , replyError = nrpc .CaptureErrors (
124
- func ()(proto.Message , error ){
125
- innerResp , err := h .server .SayHello (ctx , req )
126
- if err != nil {
127
- return nil , err
128
- }
129
- return & innerResp , err
130
- })
131
- elapsed = time .Since (start ).Seconds ()
132
- if replyError != nil {
133
- log .Printf ("SayHelloHandler: SayHello handler failed: %s" , replyError .Error ())
134
- serverRequestsForGreeter .WithLabelValues (
135
- "SayHello" , encoding , "handler_fail" ).Inc ()
136
+ request .Handler = func (ctx context.Context )(proto.Message , error ){
137
+ innerResp , err := h .server .SayHello (ctx , req )
138
+ if err != nil {
139
+ return nil , err
140
+ }
141
+ return & innerResp , err
136
142
}
137
143
}
138
144
default :
139
145
log .Printf ("GreeterHandler: unknown name %q" , name )
140
- replyError = & nrpc.Error {
146
+ immediateError = & nrpc.Error {
141
147
Type : nrpc .Error_CLIENT ,
142
148
Message : "unknown name: " + name ,
143
149
}
144
150
serverRequestsForGreeter .WithLabelValues (
145
- "Greeter" , encoding , "name_fail" ).Inc ()
151
+ "Greeter" , request . Encoding , "name_fail" ).Inc ()
146
152
}
147
-
148
-
149
- if ! noreply {
150
- // encode and send response
151
- err = nrpc .Publish (resp , replyError , h .nc , msg .Reply , encoding ) // error is logged
152
- } else {
153
- err = nil
153
+ request .AfterReply = func (request * nrpc.Request , success , replySuccess bool ) {
154
+ if ! replySuccess {
155
+ serverRequestsForGreeter .WithLabelValues (
156
+ request .MethodName , request .Encoding , "sendreply_fail" ).Inc ()
157
+ }
158
+ if success {
159
+ serverRequestsForGreeter .WithLabelValues (
160
+ request .MethodName , request .Encoding , "success" ).Inc ()
161
+ } else {
162
+ serverRequestsForGreeter .WithLabelValues (
163
+ request .MethodName , request .Encoding , "handler_fail" ).Inc ()
164
+ }
165
+ // report metric to Prometheus
166
+ serverHETForGreeter .WithLabelValues (request .MethodName ).Observe (
167
+ request .Elapsed ().Seconds ())
154
168
}
155
- if err != nil {
156
- serverRequestsForGreeter .WithLabelValues (
157
- name , encoding , "sendreply_fail" ).Inc ()
158
- } else if replyError == nil {
159
- serverRequestsForGreeter .WithLabelValues (
160
- name , encoding , "success" ).Inc ()
169
+ if immediateError == nil {
170
+ if h .workers != nil {
171
+ // Try queuing the request
172
+ if err := h .workers .QueueRequest (request ); err != nil {
173
+ log .Printf ("nrpc: Error queuing the request: %s" , err )
174
+ }
175
+ } else {
176
+ // Run the handler synchronously
177
+ request .RunAndReply ()
178
+ }
161
179
}
162
180
163
- // report metric to Prometheus
164
- serverHETForGreeter .WithLabelValues (name ).Observe (elapsed )
181
+ if immediateError != nil {
182
+ if err := request .SendReply (nil , immediateError ); err != nil {
183
+ log .Printf ("GreeterHandler: Greeter handler failed to publish the response: %s" , err )
184
+ serverRequestsForGreeter .WithLabelValues (
185
+ request .MethodName , request .Encoding , "handler_fail" ).Inc ()
186
+ }
187
+ serverHETForGreeter .WithLabelValues (request .MethodName ).Observe (
188
+ request .Elapsed ().Seconds ())
189
+ } else {
190
+ }
165
191
}
166
192
167
193
type GreeterClient struct {
0 commit comments