EdgexAgent/device-ble-go/vendor/github.com/openziti/channel/v4/envelope.go
2025-07-10 20:40:32 +08:00

377 lines
7.6 KiB
Go

package channel
import (
"context"
"github.com/michaelquigley/pfxlog"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"time"
)
type priorityEnvelopeImpl struct {
msg *Message
p Priority
}
func (self *priorityEnvelopeImpl) SetSequence(seq int32) {
self.msg.SetSequence(seq)
}
func (self *priorityEnvelopeImpl) Sequence() int32 {
return self.msg.sequence
}
func (self *priorityEnvelopeImpl) Send(sender Sender) error {
return sender.Send(self)
}
func (self *priorityEnvelopeImpl) ReplyTo(msg *Message) Envelope {
self.msg.ReplyTo(msg)
return self
}
func (self *priorityEnvelopeImpl) Msg() *Message {
return self.msg
}
func (self *priorityEnvelopeImpl) Context() context.Context {
return self.msg.Context()
}
func (self *priorityEnvelopeImpl) SendListener() SendListener {
return self.msg.SendListener()
}
func (self *priorityEnvelopeImpl) ReplyReceiver() ReplyReceiver {
return nil
}
func (self *priorityEnvelopeImpl) ToSendable() Sendable {
return self
}
func (self *priorityEnvelopeImpl) Priority() Priority {
return self.p
}
func (self *priorityEnvelopeImpl) WithPriority(p Priority) Envelope {
self.p = p
return self
}
func (self *priorityEnvelopeImpl) WithTimeout(duration time.Duration) TimeoutEnvelope {
ctx, cancelF := context.WithTimeout(context.Background(), duration)
return &envelopeImpl{
msg: self.msg,
p: self.p,
context: ctx,
cancelF: cancelF,
}
}
func (self *priorityEnvelopeImpl) WithContext(c context.Context) TimeoutEnvelope {
ctx, cancelF := context.WithCancel(c)
return &envelopeImpl{
msg: self.msg,
p: self.p,
context: ctx,
cancelF: cancelF,
}
}
type envelopeImpl struct {
msg *Message
p Priority
context context.Context
cancelF context.CancelFunc
}
func (self *envelopeImpl) SetSequence(seq int32) {
self.msg.SetSequence(seq)
}
func (self *envelopeImpl) Sequence() int32 {
return self.msg.sequence
}
func (self *envelopeImpl) Msg() *Message {
return self.msg
}
func (self *envelopeImpl) ReplyTo(msg *Message) Envelope {
self.msg.ReplyTo(msg)
return self
}
func (self *envelopeImpl) ReplyReceiver() ReplyReceiver {
return nil
}
func (self *envelopeImpl) ToSendable() Sendable {
return self
}
func (self *envelopeImpl) SendListener() SendListener {
return self
}
func (self *envelopeImpl) NotifyQueued() {}
func (self *envelopeImpl) NotifyBeforeWrite() {}
func (self *envelopeImpl) NotifyAfterWrite() {
if self.cancelF != nil {
self.cancelF()
}
}
func (self *envelopeImpl) NotifyErr(error) {}
func (self *envelopeImpl) Priority() Priority {
return self.p
}
func (self *envelopeImpl) WithPriority(p Priority) Envelope {
self.p = p
return self
}
func (self *envelopeImpl) Context() context.Context {
return self.context
}
func (self *envelopeImpl) WithTimeout(duration time.Duration) TimeoutEnvelope {
parent := self.context
if parent == nil {
parent = context.Background()
}
self.context, self.cancelF = context.WithTimeout(parent, duration)
return self
}
func (self *envelopeImpl) WithContext(c context.Context) TimeoutEnvelope {
self.context, self.cancelF = context.WithCancel(c)
return self
}
func (self *envelopeImpl) Send(sender Sender) error {
return sender.Send(self)
}
func (self *envelopeImpl) SendAndWaitForWire(sender Sender) error {
waitSendContext := &sendWaitEnvelope{envelopeImpl: self}
return waitSendContext.WaitForWire(sender)
}
func (self *envelopeImpl) SendForReply(sender Sender) (*Message, error) {
replyContext := &replyEnvelope{envelopeImpl: self}
return replyContext.WaitForReply(sender)
}
type sendWaitEnvelope struct {
*envelopeImpl
errC chan error
}
func (self *sendWaitEnvelope) ToSendable() Sendable {
return self
}
func (self *sendWaitEnvelope) SendListener() SendListener {
return self
}
func (self *sendWaitEnvelope) NotifyAfterWrite() {
close(self.errC)
}
func (self *sendWaitEnvelope) NotifyErr(err error) {
self.errC <- err
}
func (self *sendWaitEnvelope) WaitForWire(sender Sender) error {
if err := self.context.Err(); err != nil {
return err
}
defer self.cancelF()
self.errC = make(chan error, 1)
if err := sender.Send(self); err != nil {
return err
}
select {
case err := <-self.errC:
return err
case <-self.context.Done():
if err := self.context.Err(); err != nil {
return TimeoutError{errors.Wrap(err, "timeout waiting for message to be written to wire")}
}
return errors.New("timeout waiting for message to be written to wire")
}
}
type replyEnvelope struct {
*envelopeImpl
errC chan error
replyC chan *Message
}
func (self *replyEnvelope) ToSendable() Sendable {
return self
}
func (self *replyEnvelope) SendListener() SendListener {
return self
}
func (self *replyEnvelope) ReplyReceiver() ReplyReceiver {
return self
}
func (self *replyEnvelope) NotifyAfterWrite() {}
func (self *replyEnvelope) AcceptReply(message *Message) {
select {
case self.replyC <- message:
default:
logrus.
WithField("seq", message.Sequence()).
WithField("replyFor", message.ReplyFor()).
WithField("contentType", message.ContentType).
Error("could not send reply on reply channel, channel was busy")
}
}
func (self *replyEnvelope) NotifyErr(err error) {
self.errC <- err
}
func (self *replyEnvelope) WaitForReply(sender Sender) (*Message, error) {
if err := self.context.Err(); err != nil {
return nil, err
}
defer self.cancelF()
self.errC = make(chan error, 1)
self.replyC = make(chan *Message, 1)
if err := sender.Send(self); err != nil {
return nil, err
}
select {
case err := <-self.errC:
return nil, err
case <-self.context.Done():
if err := self.context.Err(); err != nil {
return nil, TimeoutError{errors.Wrap(err, "timeout waiting for message reply")}
}
return nil, errors.New("timeout waiting for message reply")
case reply := <-self.replyC:
return reply, nil
}
}
func NewErrorEnvelope(err error) Envelope {
return &errorEnvelope{
ctx: NewErrorContext(err),
}
}
type errorEnvelope struct {
ctx context.Context
}
func (self *errorEnvelope) SetSequence(int32) {}
func (self *errorEnvelope) Sequence() int32 {
return 0
}
func (self *errorEnvelope) Msg() *Message {
return nil
}
func (self *errorEnvelope) ReplyTo(*Message) Envelope {
return self
}
func (self *errorEnvelope) Priority() Priority {
return Standard
}
func (self *errorEnvelope) Context() context.Context {
return self.ctx
}
func (self *errorEnvelope) SendListener() SendListener {
return BaseSendListener{}
}
func (self *errorEnvelope) ReplyReceiver() ReplyReceiver {
return nil
}
func (self *errorEnvelope) ToSendable() Sendable {
return self
}
func (self *errorEnvelope) SendAndWaitForWire(Sender) error {
return self.ctx.Err()
}
func (self *errorEnvelope) SendForReply(Sender) (*Message, error) {
return nil, self.ctx.Err()
}
func (self *errorEnvelope) WithTimeout(time.Duration) TimeoutEnvelope {
return self
}
func (self *errorEnvelope) WithContext(context.Context) TimeoutEnvelope {
return self
}
func (self *errorEnvelope) Send(Sender) error {
return self.ctx.Err()
}
func (self *errorEnvelope) WithPriority(Priority) Envelope {
return self
}
func NewErrorContext(err error) context.Context {
result := &errorContext{
err: err,
closedC: make(chan struct{}),
}
close(result.closedC)
return result
}
type errorContext struct {
err error
closedC chan struct{}
}
func (self *errorContext) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (self *errorContext) Done() <-chan struct{} {
return self.closedC
}
func (self *errorContext) Err() error {
return self.err
}
func (self *errorContext) Value(interface{}) interface{} {
// ignore for now. may need an implementation at some point
pfxlog.Logger().Error("errorContext.Value called, but not implemented!!!")
return nil
}