Truly, I've completely forgot about mentions when writing this email!
Indeed, missed mentions are valid candidates to be included directly during
sync process. Also, maybe attention requests (like in XEP-0224), too, if
they are in the 'unread' portion of messages on server. Of course, it is
fully incompatible with E2E but I guess these folks can live without
servers helping them with these nice things.

вт, 4 июн. 2019 г. в 16:14, Kevin Smith <[email protected]>:

> There’s another aspect of unread/inbox that is worth thinking about while
> we’re trying to solve this, I think, which is that many modern systems have
> two levels of unread - unread message, and unread message that triggers a
> notification (e.g. @Kev @everyone), and we probably want to know that. Yes,
> that probably means doing server-side reference following, and has
> potential implications for E2E, but is worth thinking about.
>
> /K
>
> On 3 Jun 2019, at 15:31, Ненахов Андрей <[email protected]>
> wrote:
>
> On unread markers, having re-read the sent message, I think I wasn't clear
> enough. What was meant is that the last read message ID will likely point
> to a message that we don't yet have on device, and thus will be unable to
> calculate, how many messages we missed.
>
>
>
> пн, 3 июн. 2019 г. в 19:26, Ненахов Андрей <[email protected]
> >:
>
>> Ok, it took me some time to get to this. I think some preamble is
>> necessary, with explanation of our motives. *Those who're just
>> interested in stanza format can skip to big TL;DR header below. *
>>
>> The whole idea, and even utter necessity of such mechanics came to us
>> when we were preparing to make an XMPP client that is capable to work on
>> iOS. As you all know, basic XMPP works well enough when there is a
>> persistent connection with server. This persistent connection can be more
>> or less maintained on most modern OSs, even on Android (though it is more
>> and more difficult, later versions of Android really fight against any
>> persistent processes). But with iOS, there is no way other than to work
>> fully offline, relying on push notifications to wake up.
>>
>> Not only that, on iOS, an app has less than 30 seconds before it is shut
>> down, or brought into foreground by user. Thus, an iOS app has to quickly
>> connect, fetch all the necessary data, present, if necessary, all
>> notifications to a user, and prepare to go offline.
>>
>> The most direct approach to catch up what was missed is with offline
>> messages. It works more or less OK (more on that later) if a user is active
>> on a single device, but starts to fail utterly if user is trying to use
>> several devices simultaneously. Second approach is to fetch all messages
>> from an archive, between now and the latest message received from the
>> server. This *can* work more or less OK, if periods of disconnection are
>> relatively brief. (btw this is the method employed in current builds for
>> Xabber for iOS). However, there are scenarios when such approach will
>> clearly fail. Most of them revolve around device being offline for a
>> significant amount of time and a user being active on another device,
>> sending and receiving multiple messages in one conversation, 'burying'
>> incoming unread message from another conversation deeper than query to
>> message archive.
>>
>> To effectively tackle this problem we came up with an approach,
>> essentially orthogonal to what was tried with XMPP before: *instead of
>> an attempt to re-establish a stream, catching up on what was missed, we're
>> trying to receive a slice of a current account state*.
>>
>> This, naturally, leads to ideas about 'inbox' that are very alike to
>> Dave's proposal. True, with regular messages it is enough for us to build a
>> list of recent conversations and some delivered/read marker IDs. However,
>> we do not agree that unread message counter is not needed: if a client is
>> doing a cold sync, it'll only have the most recent message in a
>> conversation, and won't know how many are there until it loads the whole
>> history up to that point. As telegram channels show, there are often many
>> thousands of unread messages in some channels, and it is not a good idea to
>> make clients load all those messages only to present user a 4-digit number.
>>
>>
>> There are two more cases that we think should be accounted for: VoIP
>> calls and Message Editing/Deleting/Retracting.
>>
>> First, in VoIP. We've stumbled in this just recently, when it became
>> clear that if a user is called via XEP-0353, and a message with session
>> initiation ends up in an archive, it can be quickly followed by subsequent
>> messages, even from a same contact, which will inevitably 'bury' call in
>> some unfetched unread messages and recipient device would never know that
>> there was a call (or that there is still a call in progress!)
>>
>> Second, Message Editing (as we call it for now cause we didn't yet come
>> up with a proper name, thought we have a pretty nicely working
>> implementation). If you have 7 unread messages, 3 or them can very well be
>> edits to your previously received messages, and you'll never know that.
>>
>> One more thing to consider: we don't think this will work well as a
>> roster extension. Users generally want to be able to access chat history
>> even with those who are already deleted from their rosters, and maybe even
>> want to have separate chat threads with single contact. Great example for
>> this and most obvious use is separating chats with e2e and without them
>> into separate chats, like Telegram or WhatsApp do. So, instead of roster we
>> came up with entity we call 'conversation', and last message, unread
>> counter, message edits and VoIP calls are property of that entity.
>>
>> To make this work, a server intercepts all passing stanzas, and creates a
>> slice of current user account's state, based on messages, chat markers,
>> voip session messages, retract/edit messages.
>> Reconnecting client tells server the timestamp of the last message
>> received from the server (in our implementation all stanzas received from
>> the server are timestamped by the server, and clients rely on server time
>> to be correct for the needs of synchronization and message ordering), and
>> server responds with a list of conversations that was updated since that
>> time.
>>
>> TL;DR
>> Client initiates synchronization with sync request:
>>
>> <iq type='get' id=’id2'>
>>     <query xmlns='http://xabber.com/protocol/synchronization'
>> stamp=’1556111424456379’/>
>> </iq>
>>
>> Server responds with list of conversations updated since
>> '1556111424456379':
>>
>> <iq type=’result’ to=’[email protected]/Xabber-web’ from=’
>> redsolution.com’ id=’id1’>
>>     <synchronization xmlns=’http://xabber.com/protocol/synchronization’
>> stamp=’1556111424456980’>
>>         <conversation jid=’[email protected]’
>> thread=’1asd123sd’ stamp=’1556111424456980’>
>>             <retract version='3'>
>>             <unread count=’4’ after=’andrew_id_211’ />
>>             <displayed id=’andrey_id_210’ />
>>             <delivered id=’andrey_id_215’ />
>>             <call>
>>                 <propose xmlns='urn:xmpp:jingle-message:0'
>> id='a73sjjvkla37jfea'>
>>                 <description xmlns='urn:xmpp:jingle:apps:rtp:1'
>> media='audio'/>
>>                 </propose>
>>             </call>
>>             <last-message>
>>                 <message from=’[email protected]/Xabber-web’
>> to=’[email protected]/Xabber-web’ id=’andrew_id_214’>
>>                     <body>Hi!</body>
>>                     <stanza-id id=’id342’ by=’
>> [email protected]’ />
>>                 </message>
>>             </last-message>
>>         </conversation>
>>         <set xmlns='http://jabber.org/protocol/rsm'>
>>              <first index='0'>1556111424456980</first>
>>              <last>1556111424456980</last>
>>              <count>1</count>
>>         </set>
>>     </synchronization>
>> </iq>
>>
>> thread - name of a thread, or, 'conversation'. Same conversation should
>> have same thread, and default is nil, like, general converstion with a
>> person
>> displayed - AKA 'read' by remote chat partner
>> deliverred - received by remote partner's client
>> unread ... after - refers to an ID of a message of a last message read by
>> user
>> call - if there is an active call in progress, we pass all the propose
>> stanza, so client can immediately pick up the phone.
>> retract - versions of edits in this convesation
>>
>>
>>
>> In case of a cold start (like, first connection with new client), client
>> just asks for a synchoronization without timestamp, and receives full list
>> of conversations in return.
>>
>>
>>
>>
>>
>>
>> ср, 29 мая 2019 г. в 19:28, Dave Cridland <[email protected]>:
>>
>>>
>>>
>>> On Wed, 29 May 2019 at 12:27, Ненахов Андрей <
>>> [email protected]> wrote:
>>>
>>>> We have this (not exactly this, but for the very same purpose) mostly
>>>> implemented and already working, would be happy to share the results with
>>>> everyone. Currently, it's implemented on a server, client support (in Web
>>>> version of Xabber) will arrive in a week or two. We also plan to release an
>>>> open-source server (ejabberd fork) that will support this.
>>>>
>>>> Problem is, we definitely lack skills putting this as a 'XEP' formatted
>>>> thing with proper description, and, what's worse, current documentation is
>>>> mostly in Russian, but XMLs are in english and if someone would volunteer
>>>> help us putting it in a XEP-like way, I'll muster myself to translate
>>>> crucial bits into English.
>>>>
>>>>
>>> Right - I knew you had this but had forgotten. It'd be great to collate
>>> all these ideas and pick the best bits from them all.
>>>
>>> Just a high-level technical sketch would be really useful.
>>>
>>>
>>>> ср, 29 мая 2019 г. в 16:12, Dave Cridland <[email protected]>:
>>>>
>>>>> Having spent a while playing with - gasp! - non-XMPP based chat
>>>>> systems, I'm quite taken with the notion that some kind of Inbox might be
>>>>> rather useful to us.
>>>>>
>>>>> Currently, there is Erlang Solutions (ESL)'s Inbox, which is
>>>>> essentially a duplication of MAM with some chat state tracking. It's more
>>>>> than just that, of course, but the essential concept I see is that it's a
>>>>> different, but largely equivalent interface to MAM, with the concept of an
>>>>> unread counter added.
>>>>>
>>>>> Instagram, on the other hand, has no roster, as such, and its Inbox
>>>>> simply lists (recent) conversations, in much the same way as a client 
>>>>> might
>>>>> display them. Each record contains the conversation's participants, and 
>>>>> the
>>>>> most recent message. Things like presence subscription, in the Instagram
>>>>> model, are simply the open conversations.
>>>>>
>>>>> We do have a roster, of course, and we're putting more things into it
>>>>> - MIX channels, MUC Light in ESL's case, and so on.
>>>>>
>>>>> This makes me wonder if the right way to design an Inbox is actually
>>>>> to enhance our Roster with MAM and state awareness, and make it the
>>>>> conversation information hub for IM.
>>>>>
>>>>> Let's suppose that the nature of what is "unread" is equivalent across
>>>>> all clients of a particular user, to begin with.
>>>>>
>>>>> If a client requests the inbox "since" a particular point, it would
>>>>> then receive a series of records:
>>>>>
>>>>> First, a set of N records similar to a roster item, containing a jid,
>>>>> subscription state, the last archive-id received in the conversation, and
>>>>> the number of unacknowledged (by some definition) messages. Our roster 
>>>>> also
>>>>> includes groups and a name; we could also include the type (MUC, MIX, or a
>>>>> user), the full message, etc - these are all optimisations.
>>>>>
>>>>> We do not, actually, need the numbers of unread messages - a client
>>>>> seeing that the last archive-id isn't in its cache knows the conversation
>>>>> has messages that are unread to it, at least. But if we can track message
>>>>> read state, that's useful for multi-device.
>>>>>
>>>>> Finally, an update message to indicate the current point, where things
>>>>> change. I would use an archive-id again here - even if the thing causing
>>>>> the update isn't an archived message at all. This allows a client to ask
>>>>> for the archive either since a particular message, or since an event.
>>>>>
>>>>> You'll note I'm not building this directly on PubSub in the XEP-0060
>>>>> (or XEP-0163) sense - instead I'm proposing building this on the existing
>>>>> Roster and MAM.
>>>>>
>>>>> So:
>>>>>
>>>>> <iq type='get' id='some-id'>
>>>>>   <query xmlns='jabber:iq:roster' ver='last-archive-id'>
>>>>>     <inbox xmlns='urn:xmpp:inbox'><!-- Add enhanced inbox info -->
>>>>>       <messages/><!-- Include the entire last message? -->
>>>>>       <unread/><!-- Include unread count -->
>>>>>     </inbox>
>>>>>    </query>
>>>>> </iq>
>>>>>
>>>>> I'd dearly love to return updates using <message/>, MAM-style,
>>>>> actually. But let's say we stick with the roster design, the pushes look
>>>>> like:
>>>>>
>>>>> <iq from='[email protected]' id='b2gs90j5' to='[email protected]/home'
>>>>> type='set'>
>>>>>      <query xmlns='jabber:iq:roster' ver='ver42'>
>>>>>        <item jid='[email protected]' subscription='both'>
>>>>>           <unread count='4'/>
>>>>>           <stanza-id id='ver42' xmlns='...'/>
>>>>>           <message ...>
>>>>>                <body>Yeah, sure - whenever you like.</body>
>>>>>           </message>
>>>>>      </query>
>>>>>    </iq>
>>>>>
>>>>> Any message "counts" for updating the roster version, by dint of
>>>>> unifying the namespace of stanza-id (for archive) and roster version. So
>>>>> any new message arriving updates the current point of the roster as well,
>>>>> and any new change in the roster changes the archive pointer similarly.
>>>>>
>>>>> Updating the shared unread count could be by Carbonizing the
>>>>> read-receipts (or similar), and using the stanza-id from that, or by an
>>>>> explicit roster push. Either's good - I think the roster pushes are more
>>>>> explicit, which is helpful.
>>>>>
>>>>> I'm fully expecting some push-back here. Comments are, of course,
>>>>> welcome.
>>>>>
>>>>> Dave.
>>>>> _______________________________________________
>>>>> Standards mailing list
>>>>> Info: https://mail.jabber.org/mailman/listinfo/standards
>>>>> Unsubscribe: [email protected]
>>>>> _______________________________________________
>>>>>
>>>>
>>>>
>>>> --
>>>> Andrew Nenakhov
>>>> CEO, Redsolution, Inc.
>>>> https://redsolution.com <http://www.redsolution.com/>
>>>> _______________________________________________
>>>> Standards mailing list
>>>> Info: https://mail.jabber.org/mailman/listinfo/standards
>>>> Unsubscribe: [email protected]
>>>> _______________________________________________
>>>>
>>> _______________________________________________
>>> Standards mailing list
>>> Info: https://mail.jabber.org/mailman/listinfo/standards
>>> Unsubscribe: [email protected]
>>> _______________________________________________
>>>
>>
>>
>> --
>> Andrew Nenakhov
>> CEO, Redsolution, Inc.
>> https://redsolution.com <http://www.redsolution.com/>
>>
>
>
> --
> Andrew Nenakhov
> CEO, Redsolution, Inc.
> https://redsolution.com <http://www.redsolution.com/>
> _______________________________________________
> Standards mailing list
> Info: https://mail.jabber.org/mailman/listinfo/standards
> Unsubscribe: [email protected]
> _______________________________________________
>
>
> _______________________________________________
> Standards mailing list
> Info: https://mail.jabber.org/mailman/listinfo/standards
> Unsubscribe: [email protected]
> _______________________________________________
>


-- 
Andrew Nenakhov
CEO, Redsolution, Inc.
https://redsolution.com <http://www.redsolution.com>
_______________________________________________
Standards mailing list
Info: https://mail.jabber.org/mailman/listinfo/standards
Unsubscribe: [email protected]
_______________________________________________

Reply via email to