Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC with inline client #428

Open
vitalvas opened this issue Aug 26, 2024 · 5 comments
Open

RPC with inline client #428

vitalvas opened this issue Aug 26, 2024 · 5 comments

Comments

@vitalvas
Copy link

Hello,

I'm trying to use a library to implement RPC (client-server architecture, mqtt is used as a transport instead of http).
I encountered the following problem - the "server.Publish" function does not have the ability to set Properties.

An example of what I need with paho.golang:

requestID := uuid.New().String()

publish := &paho.Publish{
  Topic: "agent/myagent/request",
  Payload: []byte("{'name':'test'}"),
  Properties: &paho.PublishProperties{
    ContentType: "application/json",
    CorrelationData: []byte(requestID),
    ResponseTopic: fmt.Sprintf("agent/myagent/response/%s", requestID),
  },
}
@thedevop
Copy link
Collaborator

You can use server.InjectPacket to have full control over the packet properties. In fact, server.Publish just creates the packet and calls InjectPacket.

server/server.go

Lines 753 to 768 in 830de14

func (s *Server) Publish(topic string, payload []byte, retain bool, qos byte) error {
if !s.Options.InlineClient {
return ErrInlineClientNotEnabled
}
return s.InjectPacket(s.inlineClient, packets.Packet{
FixedHeader: packets.FixedHeader{
Type: packets.Publish,
Qos: qos,
Retain: retain,
},
TopicName: topic,
Payload: payload,
PacketID: uint16(qos), // we never process the inbound qos, but we need a packet id for validity checks.
})
}

@vitalvas
Copy link
Author

Yes, but s.inlineClient is a private variable. I don't want to implement a custom client for this.

Maybe add a new publish function like it is implemented in paho.golang?

@thedevop
Copy link
Collaborator

thedevop commented Aug 28, 2024

You do not need to use that inlineClient to publish. In fact, prior to introduction of inlineClient for subscription, a new inlineClient is created for every call to Publish.

	cl := s.NewClient(nil, "local", "inline", true)

	return s.InjectPacket(cl, packets.Packet{

@vitalvas
Copy link
Author

vitalvas commented Sep 3, 2024

My suggestion is to do something like this:

type PublishRequest struct {
        Retain     bool
        Qos        byte
	Topic      string
	Payload    []byte
	Properties packets.Properties
}

func (s *Server) PublishV2(request *PublishRequest) error {
	if !s.Options.InlineClient {
		return ErrInlineClientNotEnabled
	}

	return s.InjectPacket(s.inlineClient, packets.Packet{
		FixedHeader: packets.FixedHeader{
			Type:   packets.Publish,
			Retain: request.Retain,
			Qos:    request.Qos,
		},
		TopicName:  request.Topic,
		Payload:    request.Payload,
		PacketID:   uint16(request.Qos),
		Properties: request.Properties,
	})
}

@TheCount
Copy link

TheCount commented Sep 4, 2024

@vitalvas Given @thedevop's explanation, I don't think we need a PublishV2. However, some additional documentation or even an example might be helpful. Along the lines:

  • Publish is a convenience function, use InjectPacket for more complex stuff … (this is actually already in the docs),
  • NewClient accepts nil connections for inline clients …
  • InjectPackage accepts inline clients, see [NewClient]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@TheCount @vitalvas @thedevop and others