GROUP-89 Added Initial State Support #22
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description of Changes
This pull requests introduces several enhancements to how group updates are sent to users via Group Sync instances, most of which help simplify how clients keep up to date with the latest group info. The changes here are part of a larger cross-service effort to simplify loading and synchronization for clients.
Group Initial State Service
One of the major changes here is how users fetch the initial state of groups. Previously, users would have to make a separate request to fetch groups, meaning they'd have to keep track of the status of that request separately. While this wouldn't introduce much complexity on its own, clients would also need to keep track of an updates stream. To help simplify this, Group Sync now uses the Group Initial State Service class to fetch the latest group info from Group Service with the help of the new Group State Service class.
This new service relies on the state pattern for managing the initial state of groups. The initial state is built only once if successful, transitioning the service into the
READY
state. Groups are kept up-to-date using the same event stream that users subscribe to (groups.updates.all
) using concurrency-safe Java utilities.Group State Service
Provides utilities for initializing the current state of groups as well as handling event updates for groups and their members.
RSocket Endpoints
groups.updates.all
Previously returned a stream of group updates to users. Now it returns a concatenated stream of events in the following order:
This provides users with the initial state of groups when they initially connect. They can use the same event handling logic used for handling group updates to also handle building the initial state.
Also note the empty event. Currently, RSocketJS used by the GroupHQ client does not provide a way to hook into an 'on connected' event to a stream, meaning it's difficult to know when a stream is active and to trigger any changes as a result. One way to solve this is to set the state once an item is emitted from the stream. However, if the current state of groups is empty, and there are no updates from the stream, this emission will never occur. To solve this edge case, an empty event is emitted which contains no group updates. It is sent after the initial state of events since that stream will always be finite, while the stream of group updates never ends.
groups.user.member
Previously returned a user's member as a normal
MemberModel
. Now returns it as aPublicMember
model. This change lessens the burden of clients having to keep track of two separate models. TheMemberModel
contains a user's unique identifying info, which isn't needed by the user in this context.groups.ping
Added for the purposes of checking the stability of an RSocket connection. Currently, when a user tries to establish an RSocket connection with Group Sync, they first need to go through GroupHQ's API Gateway. This gateway is not set up to authenticate against RSocket connections for the /rsocket endpoint. Instead, any request to this endpoint is forwarded to Group Sync which does the authenticating. However, it seems like the API Gateway causes the connection to appear accepted client-side. If Group Sync is unavailable, or if it rejects the connection request, the client experiences a quick disconnection after connecting.
This can make it complicated for the client to know if their RSocket connection is ready, so this endpoint allows them to test their connection--which would only work if their connection has been accepted by Group Sync.
Event ID Handling
Previously we employed a zero-trust policy when it came to user-provided event ids. That is, we would always overwrite the event id of a received request event. The issue here is it makes it difficult for the user to keep track of their request on a separate event stream. Two solutions were considered:
Solution two was chosen, mainly because of the simplicity of not having to return to the client anything (and the client not having to keep track of the returned event id). The implications of this is that a user could send multiple requests with the same event id. That's fine, since Group Service is designed to reject any requests if there exists a request event with the same event id. And with version 4 UUIDs, there's no practical risk of id collision, whether it's generated by the client or the server.
Additional Info / Concerns
Group Initial State Service
This service still requires more work for added robustness. What happens if the update stream for groups errors out? What if the state of groups somehow go out of sync? A separate issue has been created to address this.