WIP
h3. High level targets
Enable framework for effective conflict resolution on client and server. Enable full traceability for conflict resolution Allow developers to define what conflict means and how it's detected Build sample application that (integrate with current sample application
h3. Non target
- Provide comprehensive query mechanism working with conflict resolution. - Provide data focused conflict resolution (data from different sources)
h3. Technical information h4. Enablement
Server side is dictatic conflict resolution policies. Users can provide default state provider in the configuration:
{code} { conflictProvider?: new VersionedObjectState() } {code}
By default conflict provider is `VersionedObjectState` which implements `version` field conflict detection.
Outdated: -Conflict resolution can be enabled on server by providing configuration options for both JavaScript SDK and server side:-
{code} conflict: { enabled: boolean conflictStrategy?: (currentRecord: ConflictResolutionData, client: ConflictResolutionData) => ConflictResolutionData } {code}
-When conflict on server side is enabled it will by default defer resolution to server wins. Different strategies can be employed on both client and server but server side strategies have bigger priority over client (kinda obvious) call that out). Conflict resolution must be enabled on the client and by default it will process server side strategies. Users will be able to change conflict strategy on client but not disable it (as server really controls it)-
h4. Top level overview
Users interact with the conflict interface by calling hasConflict and next methods. They can import one of their predefined strategies or write their own. Conflict resolution is applied per resolver basis which gives great customization options.
h4. Communication between server and client
Server side will always return GraphQL error when conflict is detected thru interface. Error will contain information about: - Client and server state - If conflict was resolved on server or deferred to client.
h4. Operating on Object State on server
To effectively manage conflict resolution we need to have:
- effective way to iterate on object state (hashing, changing version) - effective way to detect difference between version (collision aka conflict)
This can be achieved by following interface. {code} export interface ObjectState { /** * * @param serverData the data currently on the server * @param clientData the data the client wishes to perform some mutation with */ hasConflict detectConflict (serverData: ConflictResolutionData, clientData: ConflictResolutionData): boolean ConflictInfo
/** * * @param currentObjectState the object wish you would like to progress to its next state */ next (currentObjectState: ConflictResolutionData): ConflictResolutionData } {code} h4. Conflict resolution
Conflict resolution will use following interface:
{code} (currentRecord: ConflictResolutionData, client: ConflictResolutionData) => ConflictResolutionData {code}
h4. Communication between server and client
Server side will always return GraphQL error when conflict is detected thru interface. Error will contain information about: - Client and server state - If conflict was resolved on server or deferred to client.
h4. Conflict resolution listeners on client
Client UI should be notified about the conflict being resolved.
h4. Conflict resolution and error strategy
Mutations error strategy needs to be specified in docs. Strategies like `none` cannot be employed since users will not be able to see results coming back from server. Alternatively we should map server side error to different GraphQL error but this will mean that we will lose ability to notify users about conflict error for specific object.
h4. Conflict resolution and orphaned objects
Retrying policies should be employed on the ConflictLink to prevent from endless loop. We should track conflicted data so there is no objects left in cache
h4. Special cases conflicts
Delete operations trigger conflicts that are not easily solvable using predefined strategies (due to fact that delete actually removes data). We need to apply strategy to clear the cache inside the link if delete happens.
h4. Subscription support
Conflicted data should not trigger subscriptions until data will be actually saved to the database. Implementation details for this matter rely strictly on users performing publish subscribe operations, however we need to clearly document that as subscriptions can happen only when conflict is being resolved.
h4. Implementation details
Versioning is already done UI !Screen Shot 2018-12-19 at 4.38.01 PM.png|thumbnail!
Data access methods are already defined and working. Basic conflict resolution link is currently added to SDK: https://github.com/aerogear/aerogear-js-sdk/tree/master/packages/sync/src/conflicts
Implementation ported from spike repo to server: https://github.com/aerogear/apollo-voyager-server/pull/15
h4. Packaging and deployment
Both client side and server will have different config and internal processing embedded into them. If we identify some common or shared interface we may consider reusing server side package in client
|
|