centrifugal / centrifuge-go

Go client SDK for bidirectional communication with Centrifugo and Centrifuge-based server over WebSocket
MIT License
204 stars 49 forks source link

Tags for Publish #87

Open shaunco opened 10 months ago

shaunco commented 10 months ago

When OnPublished is called for a message received on a subscribed channel, the Publication struct has a Tags member which matches up with tags as described on https://centrifugal.dev/docs/transports/client_api ("optional tags, this is a map with string keys and string values"), however when client.Publish or subscription.Publish is called, there is no field allowing for tags to be added.

Am I misunderstanding the client API vs the server API? Can tags only be specified on the server side?

FZambia commented 10 months ago

Hello @shaunco

Yes, at this point tags can only be attached to Publication using server API. Centrifugo model is mostly built around using server API for publishing (as you can find here). Also, while technically possible, I am not sure that we want tags in client API because it will mean more possible fields for backend to validate before accepting a publication.

shaunco commented 10 months ago

Thanks @FZambia! I think my confusion arises from not seeing another go library for use between the App backend <---> Centrifugo (in the idiomatic usage link you provided) that makes use of the server API, which means if I have go based backend apps/services publishing to (subscribing) to Centrifugo and go based clients subscribing to various channels, both end up using this centrifuge-go library.

Since my particular usecase is sending protobuf payloads, I will just embed the additional fields I was thinking of putting into tags into my protobuf payload.

shaunco commented 10 months ago

To expand on that further, there are many pub/sub use cases where there is no need to "validate before accepting a publication" - simply holding a valid token usable by Centrifugo is enough validation. The two examples that come to mind are:

  1. Two App backend services that are both publishing and subscribing to channels
  2. IoT uses cases where the client is some form of edge gateway (running code written and managed by the same entity that writes the App backend) is publishing events/data to a Centrifugo channel that are picked up by an App backend that is subscribing to device-specific channels. Conversely, the edge gateway also subscribes to receive commands that are published by the App backend. (This IoT use case is one of the more popular use cases for PubNub)

Neither case has the concept of an untrusted client that needs a different API or to have its publications validated before going to Centrifugo, but from an SDK standpoint, centrifuge-go appears to be the best (and only) option for a go package. I understand that gRPC can be used directly (as shown here) the generated gRPC client is missing things like auto-reconnect (with exponential backoff), auto-resubscribe, auto-recovery, and more that makes it fine when an App backend is doing an occasional publish, but not very useful if the App backend needs to subscribe.

Am I missing something here?

FZambia commented 10 months ago

All the thoughts are totally valid, some things I can add:

So before adding Tags to client API in some way, I suppose it's required to think how to add them to current permission model, probably we can make propagating tags explicit somehow - so backend does not have a chance to forget about tags field and propagate them without validation.

So let's think more whether it's possible, and keep this issue open. It's not a quick addition, so probably for now you need to use alternative way with adding information to data payload or using server API client.

shaunco commented 10 months ago

Thanks! I had missed gocent. Happy to move this from an Issue to a Discussion, or keep it here, but I appreciate the openness to thinking about IoT use cases!

We have a dedicated Envelope protobuf message that wraps all the actual protobuf messages we put into the data field, so we can just move ahead with adding our various headers to our Envelope rather than using tags.