11package saga
22
33import (
4+ "context"
45 "database/sql"
56 "errors"
67 "fmt"
78 "reflect"
89 "strings"
910 "sync"
1011
12+ "github.com/opentracing/opentracing-go"
13+ slog "github.com/opentracing/opentracing-go/log"
1114 "github.com/sirupsen/logrus"
1215 "github.com/wework/grabbit/gbus"
1316 "github.com/wework/grabbit/gbus/metrics"
@@ -98,7 +101,8 @@ func (imsm *Glue) getDefsForMsgName(msgName string) []*Def {
98101 return defs
99102}
100103
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 {
102106
103107 imsm .lock .Lock ()
104108 defer imsm .lock .Unlock ()
@@ -117,11 +121,12 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
117121 */
118122 startNew := def .shouldStartNewSaga (message )
119123 if startNew {
124+
120125 newInstance := def .newInstance ()
121126 imsm .Log ().
122127 WithFields (logrus.Fields {"saga_def" : def .String (), "saga_id" : newInstance .ID }).
123128 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 {
125130 imsm .Log ().WithError (invkErr ).WithField ("saga_id" , newInstance .ID ).Error ("failed to invoke saga" )
126131 return invkErr
127132 }
@@ -154,7 +159,7 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
154159 return e
155160 }
156161 def .configureSaga (instance )
157- if invkErr := imsm .invokeSagaInstance (instance , invocation , message ); invkErr != nil {
162+ if invkErr := imsm .invokeSagaInstance (def , instance , invocation , message ); invkErr != nil {
158163 imsm .Log ().WithError (invkErr ).WithField ("saga_id" , instance .ID ).Error ("failed to invoke saga" )
159164 return invkErr
160165 }
@@ -176,7 +181,7 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
176181
177182 for _ , instance := range instances {
178183 def .configureSaga (instance )
179- if invkErr := imsm .invokeSagaInstance (instance , invocation , message ); invkErr != nil {
184+ if invkErr := imsm .invokeSagaInstance (def , instance , invocation , message ); invkErr != nil {
180185 imsm .Log ().WithError (invkErr ).WithField ("saga_id" , instance .ID ).Error ("failed to invoke saga" )
181186 return invkErr
182187 }
@@ -191,13 +196,16 @@ func (imsm *Glue) handler(invocation gbus.Invocation, message *gbus.BusMessage)
191196 return nil
192197}
193198
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 ()
195203 sginv := & sagaInvocation {
196204 decoratedBus : invocation .Bus (),
197205 decoratedInvocation : invocation ,
198206 inboundMsg : message ,
199207 sagaID : instance .ID ,
200- ctx : invocation . Ctx () ,
208+ ctx : sctx ,
201209 invokingService : imsm .svcName ,
202210 }
203211 sginv .SetLogger (imsm .Log ().WithFields (logrus.Fields {
@@ -207,7 +215,11 @@ func (imsm *Glue) invokeSagaInstance(instance *Instance, invocation gbus.Invocat
207215 }))
208216
209217 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
211223}
212224
213225func (imsm * Glue ) completeOrUpdateSaga (tx * sql.Tx , instance * Instance ) error {
@@ -232,7 +244,7 @@ func (imsm *Glue) registerMessage(message gbus.Message) error {
232244 return nil
233245 }
234246 imsm .alreadyRegistred [message .SchemaName ()] = true
235- return imsm .bus .HandleMessage (message , imsm .handler )
247+ return imsm .bus .HandleMessage (message , imsm .SagaHandler )
236248}
237249
238250func (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
241253 return nil
242254 }
243255 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 )
245257}
246258
247259//TimeoutSaga fetches a saga instance and calls its timeout interface
@@ -257,7 +269,12 @@ func (imsm *Glue) TimeoutSaga(tx *sql.Tx, sagaID string) error {
257269 if err != nil {
258270 return err
259271 }
272+
273+ span , _ := opentracing .StartSpanFromContext (context .Background (), "SagaTimeout" )
274+ span .SetTag ("saga_type" , saga .String ())
275+ defer span .Finish ()
260276 timeoutErr := saga .timeout (tx , imsm .bus )
277+
261278 if timeoutErr != nil {
262279 imsm .Log ().WithError (timeoutErr ).WithField ("sagaID" , sagaID ).Error ("failed to timeout saga" )
263280 return timeoutErr
0 commit comments