github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/components/requestreply/requestreply.go (about) 1 package requestreply 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/wfusion/gofusion/common/infra/watermill/message" 9 ) 10 11 // NoResult is a result type for commands that don't have result. 12 type NoResult = struct{} 13 14 type Reply[Result any] struct { 15 // HandlerResult contains the handler result. 16 // It's preset only when NewCommandHandlerWithResult is used. If NewCommandHandler is used, HandlerResult is empty. 17 // 18 // Result is sent even if the handler returns an error. 19 HandlerResult Result 20 21 // Error contains the error returned by the command handler or the Backend when handling notification fails. 22 // Handling the notification can fail, for example, when unmarshaling the message or if there's a timeout. 23 // If listening for a reply times out or the context is canceled, the Error is ReplyTimeoutError. 24 // 25 // If an error from the handler is returned, CommandHandlerError is returned. 26 // If processing was successful, Error is nil. 27 Error error 28 29 // NotificationMessage contains the notification message sent after the command is handled. 30 // It's present only if the request/reply backend uses a Pub/Sub for notifications (for example, PubSubBackend). 31 // 32 // Warning: NotificationMessage is nil if a timeout occurs. 33 NotificationMessage *message.Message 34 } 35 36 type Backend[Result any] interface { 37 ListenForNotifications(ctx context.Context, params BackendListenForNotificationsParams) (<-chan Reply[Result], error) 38 OnCommandProcessed(ctx context.Context, params BackendOnCommandProcessedParams[Result]) error 39 } 40 41 type BackendListenForNotificationsParams struct { 42 Command any 43 OperationID OperationID 44 } 45 46 type BackendOnCommandProcessedParams[Result any] struct { 47 Command any 48 CommandMessage *message.Message 49 50 HandlerResult Result 51 HandleErr error 52 } 53 54 // OperationID is a unique identifier of a command. 55 // It correlates commands with replies between the bus and the handler. 56 type OperationID string 57 58 // ReplyTimeoutError is returned when the reply timeout is exceeded. 59 type ReplyTimeoutError struct { 60 Duration time.Duration 61 Err error 62 } 63 64 func (e ReplyTimeoutError) Error() string { 65 return fmt.Sprintf("reply timeout after %s: %s", e.Duration, e.Err) 66 } 67 68 type ReplyUnmarshalError struct { 69 Err error 70 } 71 72 func (r ReplyUnmarshalError) Error() string { 73 return fmt.Sprintf("cannot unmarshal reply: %s", r.Err) 74 } 75 76 func (r ReplyUnmarshalError) Unwrap() error { 77 return r.Err 78 } 79 80 // CommandHandlerError is returned when the command handler returns an error. 81 type CommandHandlerError struct { 82 Err error 83 } 84 85 func (e CommandHandlerError) Error() string { 86 return e.Err.Error() 87 } 88 89 func (e CommandHandlerError) Unwrap() error { 90 return e.Err 91 }