1
1
package saga
2
2
3
3
import (
4
+ "context"
4
5
"database/sql"
5
6
"errors"
6
7
"fmt"
7
8
"reflect"
8
9
"strings"
9
10
"sync"
10
11
12
+ "github.com/opentracing/opentracing-go"
13
+ slog "github.com/opentracing/opentracing-go/log"
11
14
"github.com/sirupsen/logrus"
12
15
"github.com/wework/grabbit/gbus"
13
16
"github.com/wework/grabbit/gbus/metrics"
@@ -98,7 +101,8 @@ func (imsm *Glue) getDefsForMsgName(msgName string) []*Def {
98
101
return defs
99
102
}
100
103
101
- func (imsm * Glue ) handler (invocation gbus.Invocation , message * gbus.BusMessage ) error {
104
+ //SagaHandler is the generic handler invoking saga instances
105
+ func (imsm * Glue ) SagaHandler (invocation gbus.Invocation , message * gbus.BusMessage ) error {
102
106
103
107
imsm .lock .Lock ()
104
108
defer imsm .lock .Unlock ()
@@ -117,11 +121,12 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
117
121
*/
118
122
startNew := def .shouldStartNewSaga (message )
119
123
if startNew {
124
+
120
125
newInstance := def .newInstance ()
121
126
imsm .Log ().
122
127
WithFields (logrus.Fields {"saga_def" : def .String (), "saga_id" : newInstance .ID }).
123
128
Info ("created new saga" )
124
- if invkErr := imsm .invokeSagaInstance (newInstance , invocation , message ); invkErr != nil {
129
+ if invkErr := imsm .invokeSagaInstance (def , newInstance , invocation , message ); invkErr != nil {
125
130
imsm .Log ().WithError (invkErr ).WithField ("saga_id" , newInstance .ID ).Error ("failed to invoke saga" )
126
131
return invkErr
127
132
}
@@ -154,7 +159,7 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
154
159
return e
155
160
}
156
161
def .configureSaga (instance )
157
- if invkErr := imsm .invokeSagaInstance (instance , invocation , message ); invkErr != nil {
162
+ if invkErr := imsm .invokeSagaInstance (def , instance , invocation , message ); invkErr != nil {
158
163
imsm .Log ().WithError (invkErr ).WithField ("saga_id" , instance .ID ).Error ("failed to invoke saga" )
159
164
return invkErr
160
165
}
@@ -176,7 +181,7 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
176
181
177
182
for _ , instance := range instances {
178
183
def .configureSaga (instance )
179
- if invkErr := imsm .invokeSagaInstance (instance , invocation , message ); invkErr != nil {
184
+ if invkErr := imsm .invokeSagaInstance (def , instance , invocation , message ); invkErr != nil {
180
185
imsm .Log ().WithError (invkErr ).WithField ("saga_id" , instance .ID ).Error ("failed to invoke saga" )
181
186
return invkErr
182
187
}
@@ -191,13 +196,16 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
191
196
return nil
192
197
}
193
198
194
- func (imsm * Glue ) invokeSagaInstance (instance * Instance , invocation gbus.Invocation , message * gbus.BusMessage ) error {
199
+ func (imsm * Glue ) invokeSagaInstance (def * Def , instance * Instance , invocation gbus.Invocation , message * gbus.BusMessage ) error {
200
+
201
+ span , sctx := opentracing .StartSpanFromContext (invocation .Ctx (), def .String ())
202
+ defer span .Finish ()
195
203
sginv := & sagaInvocation {
196
204
decoratedBus : invocation .Bus (),
197
205
decoratedInvocation : invocation ,
198
206
inboundMsg : message ,
199
207
sagaID : instance .ID ,
200
- ctx : invocation . Ctx () ,
208
+ ctx : sctx ,
201
209
invokingService : imsm .svcName ,
202
210
}
203
211
sginv .SetLogger (imsm .Log ().WithFields (logrus.Fields {
@@ -207,7 +215,11 @@ func (imsm *Glue) invokeSagaInstance(instance *Instance, invocation gbus.Invocat
207
215
}))
208
216
209
217
exchange , routingKey := invocation .Routing ()
210
- return instance .invoke (exchange , routingKey , sginv , message )
218
+ err := instance .invoke (exchange , routingKey , sginv , message )
219
+ if err != nil {
220
+ span .LogFields (slog .Error (err ))
221
+ }
222
+ return err
211
223
}
212
224
213
225
func (imsm * Glue ) completeOrUpdateSaga (tx * sql.Tx , instance * Instance ) error {
@@ -232,7 +244,7 @@ func (imsm *Glue) registerMessage(message gbus.Message) error {
232
244
return nil
233
245
}
234
246
imsm .alreadyRegistred [message .SchemaName ()] = true
235
- return imsm .bus .HandleMessage (message , imsm .handler )
247
+ return imsm .bus .HandleMessage (message , imsm .SagaHandler )
236
248
}
237
249
238
250
func (imsm * Glue ) registerEvent (exchange , topic string , event gbus.Message ) error {
@@ -241,7 +253,7 @@ func (imsm *Glue) registerEvent(exchange, topic string, event gbus.Message) erro
241
253
return nil
242
254
}
243
255
imsm .alreadyRegistred [event .SchemaName ()] = true
244
- return imsm .bus .HandleEvent (exchange , topic , event , imsm .handler )
256
+ return imsm .bus .HandleEvent (exchange , topic , event , imsm .SagaHandler )
245
257
}
246
258
247
259
//TimeoutSaga fetches a saga instance and calls its timeout interface
@@ -257,7 +269,12 @@ func (imsm *Glue) TimeoutSaga(tx *sql.Tx, sagaID string) error {
257
269
if err != nil {
258
270
return err
259
271
}
272
+
273
+ span , _ := opentracing .StartSpanFromContext (context .Background (), "SagaTimeout" )
274
+ span .SetTag ("saga_type" , saga .String ())
275
+ defer span .Finish ()
260
276
timeoutErr := saga .timeout (tx , imsm .bus )
277
+
261
278
if timeoutErr != nil {
262
279
imsm .Log ().WithError (timeoutErr ).WithField ("sagaID" , sagaID ).Error ("failed to timeout saga" )
263
280
return timeoutErr
0 commit comments