weixin_39611072
2020-11-24 14:52 阅读 3

Make sure we get the profile messages we need from the social provider

According to our freedom social interface (https://github.com/freedomjs/freedom/blob/master/interface/social.json) There is no way to proactively get a single user-profile for a known user-id.

Without a guarentee that every newly online user (a user for whom there is a client online now, but there wasn't before) we get a profile message; we have to call getUsers for every new user that comes online, which seems like is going to do a lot of redundant roster network stuff.

The situation one might worry about is that after a call to getUsers and we get all the roster, we start seeing new onClientState messages for user's we don't know anything about. We don't want to have to call getUsers every time.

Two options come to mind: - Add a getUserProfile method that gets a given user-id's profile; we can then call this selectively for new onClientState messages. - Provide a guarantee that every newly online user (a user for whom there is a client online now, but there wasn't before) we get a profile message.

该提问来源于开源项目:UWNetworksLab/uProxy-p2p

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

20条回答 默认 最新

  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    thoughts?

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    I think it would make uProxy's life easier if we always got an onUserProfile before an onClientState events for that user, and likewise always got an onClientState before any onMessage events for that client. We have a lot of code right now to handle race conditions where these events arrive "out-of-order", and still keep running into issues with this.

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    Also currently uProxy doesn't call getUsers or getClients, and I'm not sure that we need a getUserProfile method. It seems to me that if we don't get an onUserProfile event for a user, then the social provider isn't going to have that user's profile, so it couldn't be returned by getUsers or getUserProfile.

    点赞 评论 复制链接分享
  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    that's a vote for option 2. But I think you might want to clarify that you want onUserProfile messages prior to onClientState online for the onClientState when a new client for a given user comes online? Or are you saying for some reason you want an onUserProfile for every onClientState (that seems too much, and not helpful to me... but maybe I'm missing something?)

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    Sort of... we should get an onUserProfile for every contact, almost immediately after login, regardless of whether they are ONLINE, OFFLINE, etc. uProxy (or anyone else using a freedom social module) should keep track of these profiles, then we won't need any later onUserProfile events for that userId unless they change their name or image.

    I believe that is actually how freedom-social-xmpp works now. The only problem with freedom-social-xmpp is that sometimes it will emit an onClientState before an onUserProfile for that user, or it will sometimes emit an onMessage before either an onClientState or onUserProfile for that user/client. To me these seem like race conditions in freedom-social-xmpp that uProxy is working around, and it would be nicer if these were handled in freedom-social-xmpp (I don't believe freedom-for-firebase will have these issues for example)

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    in other words, the way onUserProfile should work is that: - it is emitted for every user who is a contact, immediately after login, regardless of what statuses their clients have (or even if they have no clients at all) - it is emitted any time a user changes their name or picture. - ideally (not sure if this works yet): it is emitted if a new contact is added (e.g. through GTalk within GMail). - ideally (this definitely doesn't work yet): it is always emitted before onClientState events for that userId

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    So I don't think the original description of this issue is accurate.. AFAIK we receive an onUserProfile for every contact we can interact with in uProxy (if we don't thats a bug specific to the social provider that needs fixing and not an issue with the interface).

    点赞 评论 复制链接分享
  • weixin_39622988 weixin_39622988 2020-11-24 14:52

    It sounds then like the answer is the second option (plus a few additional cases), and perhaps the real issue is tracking down which providers/scenarios fail to do this and debug/fix. I've been working on getting the firebase provider functioning in Firefox, and it's likely not satisfying all of these cases at the moment (still need to get it logging in for Firefox actually). Maybe we should create profile message related issues in each provider repo to put specific logs/debugging, and track the overall progress here.

    点赞 评论 复制链接分享
  • weixin_39588252 weixin_39588252 2020-11-24 14:52

    I'm not sure it makes sense to enforce this constraint on the XMPP social provider. The way both onClientState and onUserProfile messages work is that they are emitted anytime we get any new information about a user. For example, it is very common for you to get an onUserProfile message when you learn about the user's name, and then a second one when you learn about a user's image. There are 2 ways we can get onUserProfile events: as a response to iq:roster queries, and vcard queries. We get onClientState events as a response to presence messages. Because there is no ordering guarantee right now, (we just report it when we see it), if an onClientState is emitted before an onUserProfile, that is equivalent to just initializing the user's profile to be {userid: string}, because we don't have any other information yet.

    I think calling getUsers is an orthogonal issue. getUsers does not guarantee that you get your complete roster or a complete profile about any user. It merely returns any profile information it is aware of at the moment.

    My proposal would be a third option. If you get an onClientState before an onUserProfile, just initialize the userProfile to be {userid: string}. Then you can either filter all users with no name field when displaying the buddylist, or just display the userId until we get a name.

    点赞 评论 复制链接分享
  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    I like the idea of getting all user profiles independently of status, and getting one before any onClientState messages. This issue to just to: 1. clarify what semantics we want, 2. document it, and 3. make sure all our social provider implementations meet it.

    Chatting with I agree that we may be able to remove getUsers and getClients from the API and simplify things a bit.

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    Regarding the third option " If you get an onClientState before an onUserProfile, just initialize the userProfile to be {userid: string}." - this is approximately what we are doing now. The problem is we don't have a name for the user and just use 'pending', which has resulted in a few bugs for us. Likewise we do currently handle getting onMessage events before the corresponding onClientState. But we have had to write a decent amount of code to handle this, and it is fragile and keeps resulting in bugs.

    Also it is very easy to make the firebase provider enforce userProfiles before clientStates, and clientStates before messages - it would be nice if freedom-social-xmpp could do the same.

    Regarding getUsers and getClients, uProxy doesn't use these at all, and assuming we store everything from onUserProfile and onClientState I'm not sure why we would ever need these methods.

    On Thu Feb 19 2015 at 5:13:47 PM iislucas notifications.com wrote:

    I like the idea of getting all user profiles independently of status, and getting one before any onClientState messages. This issue to just to: 1. clarify what semantics we want, 2. document it, and 3. make sure all our social provider implementations meet it.

    Chatting with https://github.com/dborkan I agree that we may be able to remove getUsers and getClients from the API and simplify things a bit.

    — Reply to this email directly or view it on GitHub https://github.com/uProxy/uproxy/issues/947#issuecomment-75149817.

    点赞 评论 复制链接分享
  • weixin_39588252 weixin_39588252 2020-11-24 14:52

    Do we have reason to believe that trying to solve this inside freedom-social-xmpp vs handling it in uProxy would be less buggy? It's the same queuing logic right?

    Plus, I'm hesitant to add more guarantees along the social interface unless we know for certain what we want. Right now we don't provide any guarantees on ordering of events.

    For example, I could easily add code to make onUserProfile events be emitted before onClientState, with only the userId. Would that solve it? There's also, name, image, and URL fields. Do you want all onClientState events to wait until all fields are populated? What if some fields are missing? What if we don't know which fields are missing apriori?

    Similarly for onClientState before onMessage. Do we have to wait until the user is ONLINE before receiving any messages?

    点赞 评论 复制链接分享
  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    I'm not sure what of the various suggestions your responding to. :/

    I think there's a lot of different things being talked about on this thread. Lets name them and be more specific about the which one which argument is related to. 1. asking for social interface to guarantee that we get an onUserProfile for every contact independently of whether they are online/offline. 2. asking for an onUserProfile before any onClientState to be received for that user. 3. asking for an onClientState before any onMessage for that user.

    For 1: I don't think you have any argument against this, is that right?

    For 2 and 3 (which have been suggested a few times before also); I think one could quite easily write a wrapper for an arbitrary social provider that enforces the ordering constraints. So maybe we don't force social providers to do that, but we do always run it through the interface wrapper that imposes the orderings that make usage easier?

    I don't think there is any suggestion that onUserProfile cannot also arrive after onClientState messages.

    点赞 评论 复制链接分享
  • weixin_39588252 weixin_39588252 2020-11-24 14:52

    Re: 1. There's no guarantee that we can get every contact, especially those that are offline. From what I remember, iq:roster queries only return a limited number of contacts, biased towards online users. We are made aware of a good number of users from presence messages, which we don't get for every offline user.

    Re 2 & 3: I'm responding most directly to 's most recent comment. My understanding from this comment is that uProxy wants every user to have a name before handling onClientState events. Thus, if freedom-social-xmpp emits an onUserProfile event with no name (and only a userId) before any onClientState, that doesn't address what was asking for in the first place.

    Why are names special? Why can we get images in a subsequent onUserProfile event but not names? I feel like our code would be more robust if we handled events in an order independent way.

    点赞 评论 复制链接分享
  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    Thanks for clarification!

    For uProxy names are special because they let us put something in the roster.

    If we can't have (1) then I think we have to have one of the solution initially proposed.

    Sounds like a meeting on this might speed things up. I'll schedule something.

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    From a UX standpoint I think its fine to display the user with their name, but have their image (and URL if we ever use that) appear later. I don't think its fine to just show the user's ID (typically its some random string .talk.google.com) or show 'pending' which is our current default name.

    Regarding code complexity, part of the problem has been the way we use storage to load + save our User objects. Things have gotten better with https://github.com/uProxy/uproxy/pull/923, but there is still some complexity in the code. For example we could have these sequence of events: 1. get an onClientState for a userId where we don't have a user 2. create a placeholder User object with name='pending' and a userId 3. start to load info for that User from storage (async) 4. before storage load completes, get an onUserProfile for that userId, update the User object (in the past we had issues where this could clobber the original User object and create a new User with no clients, this should be fixed now) 5. have storage load complete, replace the User's name/image with what we get from storage (hopefully they match, not sure what happens if they don't). 6. only after storage loading completes do we send the User to the UI

    AFAIK this all works now, but we went through a lot of iterations try to handle race conditions with onUserProfile, onClientState and onMessage (the last 2 can both result in a 'pending' User), combined with race conditions due to async storage reading and writing.. There more guarantees regarding ordering we can get by the social provider, the less of this uProxy has to handle. Although I do see the point that if we handle it once uProxy (once we finally have that working right), we don't have to worry about it again for each social provider.

    点赞 评论 复制链接分享
  • weixin_39622988 weixin_39622988 2020-11-24 14:52

    I think another point worth considering for the "how much should the provider guarantee?" question is that having freedom require more things from social providers makes it more difficult to create those providers, possibly ultimately limiting that ecosystem. Certainly some requirements make sense and our goal should be to figure out which, but I am leaning towards not having the ordering constraints be part of the provider directly. I do like the idea of the lightweight wrapper approach (at least for those problems/calls where it's feasible).

    点赞 评论 复制链接分享
  • weixin_39781326 weixin_39781326 2020-11-24 14:52

    I'm changing this to P2, since it is not blocking for public launch.

    点赞 评论 复制链接分享
  • weixin_39611072 weixin_39611072 2020-11-24 14:52

    Update from discussion: - A shim that ensures ordering guarantees is a good way to standardize lots of work that would otherwise be done in the consumer (or provider). - Turning the events into streams (1. get a user profile 2. get client online. 3 (a). get stream of messages. 3(b) get profile updates. 4. get offline state) with explicit state transitions would enable async responses to the events (e.g. promise return values for act_on_user_profile that have to resolve before get_client state events happen). This can be done in the shim too. - There are lots of notions of adding friends we could and might support and some more work is needed to figure out how/if they should change the Social API. Key concepts: - we'd like to support, for the providers that that it can work for, adding contacts via the uproxy roster UI. e.g. type in someone's email and be able to have them as a contact on the Firebase provider (or the Quiver provider, and maybe XMPP too).

    点赞 评论 复制链接分享
  • weixin_39624873 weixin_39624873 2020-11-24 14:52

    Closing as this is not currently a priority.

    点赞 评论 复制链接分享

相关推荐