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

send to client-id or user-id #134

Closed
bplatz opened this issue Jun 7, 2015 · 8 comments
Closed

send to client-id or user-id #134

bplatz opened this issue Jun 7, 2015 · 8 comments

Comments

@bplatz
Copy link

bplatz commented Jun 7, 2015

The concept of sente with a central user-id across all devices is great idea, and I also understand you can make it behave as a client-id as well, however I think the real need is to have both. I'd like to suggest sente natively supports the concept of both.

Client-d use case: push page view-specific events to a client. This may be a reactive query that is needed by a specific React component, for example.

User-id use case: push alerts, chat messages, or other things you'd want all clients to know about.

While not directly related to supporting issue #133, they both poke at the idea of opening up client-id focused messaging.

@ptaoussanis
Copy link
Member

Hi there,

Sente's design allows you to model any kind of user identity mechanism you'd like (that is possible to do at least semi securely). Please see the docs here for more info.

Let me know if that helps?

@bplatz
Copy link
Author

bplatz commented Jun 8, 2015

I believe I understand the support, which seems to be either user-id as a user, or user-id as a client. The use case I'd like to see support of is both simultaneously. I believe the only way to do this today is to set up as user-id as a client, and write wrappers on top to track true users and their respective connections, including activations and deactivations of clients.

This is fine to do, however it is exactly what sente is already doing with the conn_ atom. But to my knowledge there is no direct way to sending to individual connections, unless you set things up as user-id as a client, but then you forgo sending messages to all of a user's connections (without writing it on your own).

I hope that makes better sense.

@ptaoussanis
Copy link
Member

A user-id is just an arbitrarily defined set of 0, 1, or more client ids. How client ids are determined is configurable, and how the user-id [set] is determined is configurable.

The broadcast API sends to a user-id [client-id set], and the callback API sends to a specific client-id.

A broadcast API that sends to a specific client-id (without user-id == client-id) is something I'd potentially be open to for a future release.

First step would be some describing a concrete, clearly-defined use case that is both secure and impossible with the current API.

@bplatz
Copy link
Author

bplatz commented Jun 8, 2015

It looks like interface/send! will do per-client messages? You mention a callback API to send to a specific client-id, which I'm not aware of.

But yes, I'm interested in a broadcast to a client-id1 where user-id = [client-id1, client-id2, ...].

The use case is a user has multiple devices connected (say mobile device and desktop browser). There are two categories of server-initiated messages to send to these clients:

  1. A new task has been assigned. Both devices will want to display an alert to the user, regardless of the current device's view-state. (chsk-send! user-id [:event/task "new task details"]) works here in a single-server environment.

  2. The desktop browser is currently displaying a streaming chart, it is interested in a stream of updates from the server that relate to the current view-state of the client. ??? (chsk-client-send! client-id [:chart/stream ...])

@ptaoussanis
Copy link
Member

It looks like interface/send! will do per-client messages? You mention a callback API to send to a specific client-id, which I'm not aware of.

Client-initiated requests can take an optional callback fn. That callback fn will receive a client-specific response from the server.

The use case is [...]

Two possible implementations with the current API:

  1. Create >1 concurrent chsk with a user-id per subscription set.
  2. Server broadcasts to all a user's clients to announce the availability of new data; interested (subscribed) clients respond to that broadcast with a callback request through which they'll actually receive the payload.

Just a friendly heads-up that I'm going to be signing off on these topics for today. Best of luck with your project!

@bplatz
Copy link
Author

bplatz commented Jun 8, 2015

Thanks for the comments. I maybe should have been clear I'm suggesting this as a feature addition. The use case, at least to me, seems common and needed. My approach will be to make user-id===client-id and write a atom that maintains client-ids for a user, and perform a doseq on that when desired to send out to all connections for a user. This will essentially replicate what you are already doing with the conn_ atom therefore I'm making an atom on top of the atom designed to do identical work. For that reason it felt like Sente would benefit from the support natively, of what otherwise feels like a hack.

One of the things I found attractive about Sente was the notion of one user -> many devices capability built-in, but I've found I'm unable to use this feature both for this use case and for the load balanced use-case. So my suggestions are in hopes to still make this still a feature, but work in a broader set of circumstances.

I appreciate all the work you've done with Sente, and having spent a good amount of time now in the source I know it isn't trivial. I will likely still use Sente, but I need to decide if I fork and build this in more natively so it doesn't feel like such a hack, or write a hack on top of it in hopes that there is more native support in the future.

You can close, and again thanks for your work here and support.

@ptaoussanis
Copy link
Member

So my position on this for the moment is: I'm not entirely closed to the idea of extending the async push API to support pushing to individual client ids.

But there would be significant costs involved in such an addition, and I'm not sure that people would get the result that they're expecting. Client ids are designed (by the intrinsic nature of what we're dealing with here) to be ephemeral. This isn't an arbitrary property; it's necessary to buy us important things like security, performance, and API consistency over different protocols.

Again, not closed to the idea of paying the costs involved if there's a compelling reason to. But there'd need to be an unambiguously compelling reason to.

Step 1 in moving this forward would be a concrete, clearly defined use case that:

  1. Cannot be implemented with the current API.
  2. Is secure.

By "clearly defined", I mean a full description of how one would intend to securely assign client ids, store client ids, atomically maintain client ids in the face of long polling and disconnects, and do this in a way that's amenable to working in a distributed environment as the current API is.

Your particular use case (as I've understood it), can be reasonably accommodated by the current API in the two ways I described before. Even if you could send to client ids directly, I'd still recommend using one of the two ways described since you'd get better reliability, and a simpler server-side design.

I'm pretty limited on time at the moment, so going to be closing this for now. Would happily welcome a proof of concept that unambiguously demonstrates a need for an API extension of this magnitude and cost (most notably re: negative impact on code flexibility).

Appreciate all your input. Apologies if this reply was more terse than it could have been, have a headache + a bit overworked atm.

@bplatz
Copy link
Author

bplatz commented Jun 9, 2015

Peter, as the design Sente currently provides allows granularity at the client level there won't be a use case that it cannot support. If the capability stopped there then I think things would almost be simpler.

Sente took it a step farther, and provided the concept of a channel/topic but restricted it to a user, and when using that capability you inherently loose the per-client capability (without additional work). In addition I think the concept breaks down a bit in a clustered environment. So my opinion is that Sente is sitting on the fence here, and the product would be best served by being on one side or the other.

I think the side Sente should be on is to actually support channels/topics by opening up what is already there. I think it is mostly what people want out of a solution like this and I think many of the inquiries I see into Sente poke at this issue.

So my take on this is that (chsk-send! user-id [...]), should become (chsk-send! channel-id [...]) where n channels <-> n clients is supported. I think this approach would provide 100% of today's capability and I believe be completely backwards-compatible.

  • Individual clients can be their own channel if per-client granularity is desired, which can help preserve your security concerns as it essentially would continue to work as it does today. Messages are still sent to the channel, not the direct client connection
  • Per-user channels would be rudimentary to implement (as it is already today), supporting multiple clients per user.
  • New channels can be created, and a subscribe-function option will process a subscription and accept/reject the addition of a client into a channel.

The most popular socket libraries support this functionality and I think for a reason. I like the idea of stopping at the client level as well and leaving channels/topics implementation up to the programmer but (a) I think there are already decent options out there that do this in clojure and (b) IMO Sente has already broken that boundary already, just part-way and closed.

Anyhow, building this on top of Sente isn't the end of the world, but I think for the reasons above building it into Sente would be cleaner and a welcome feature that aligns with what I understood to be Sente's goals.

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

2 participants