> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pocketsync.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Conflict Resolution

> Custom Conflict Resolution for PocketSync

For applications with specific requirements, PocketSync allows implementing custom conflict resolution logic:

* Set the conflict strategy to ConflictResolutionStrategy.custom
* Provide a custom resolver function that implements the ConflictResolver type
* The resolver receives both conflicting changes and must return the winning change

To use a custom conflict resolver, you must:

* Set the conflictResolutionStrategy to ConflictResolutionStrategy.custom in PocketSyncOptions
* Provide your custom resolver function in the customResolver parameter

Example configuration:

```dart theme={null}
final pocketSync = await PocketSync.initialize(
  options: PocketSyncOptions(
    conflictStrategy: ConflictResolutionStrategy.custom,
    conflictResolver: (localChange, remoteChange) async {
      // Custom logic to determine the winning change
      if (localChange.tableName == 'priorities') {
        return localChange; // Local changes always win for the 'priorities' table
      } else {
        return remoteChange; // Server changes win for other tables
      }
    },
  ),
  // ... other configuration options
);
```

## Custom Conflict Resolver

The custom conflict resolver function receives two parameters:

| Parameter | Description |
| - | - |
| `localChange` | The local change that conflicts with the remote change |
| `remoteChange` | The remote change that conflicts with the local change |

The resolver must return the winning change.

### Example

```dart theme={null}
final pocketSync = await PocketSync.initialize(
  options: PocketSyncOptions(
    conflictStrategy: ConflictResolutionStrategy.custom,
    conflictResolver: (localChange, remoteChange) async {
      // Custom logic to determine the winning change
      if (localChange.tableName == 'priorities') {
        return localChange; // Local changes always win for the 'priorities' table
      } else {
        return remoteChange; // Server changes win for other tables
      }
    },
  ),
  // ... other configuration options
);
```

The change object has the following properties:

| Property | Type | Description |
| - | - | - |
| `id` | `String` | Unique identifier for the change |
| `tableName` | `String` | Name of the table being modified |
| `recordId` | `String` | ID of the record being modified |
| `operation` | `ChangeType` | Type of operation (insert, update, delete) |
| `timestamp` | `int` | When the change occurred (milliseconds since epoch) |
| `version` | `int` | Version number of the change |
| `synced` | `bool` | Whether the change has been synced to the server |
| `data` | `Map<String, dynamic>` | The actual data changes for the record |

> Import note: The data property should always contain a "old" and "new" key. This is needed to maintain consistency with the default conflict resolution strategy.

### Conflict Resolution Process

```mermaid theme={null}
sequenceDiagram
    participant App as "Client Application"
    participant PS as "PocketSync"
    participant ME as "MergeEngine"
    participant CR as "Custom Resolver"

    App->>PS: initialize(options with customResolver)
    PS->>ME: create with customResolver
    
    Note over ME: Store resolver for later use
    
    Note over App,CR: During synchronization...
    
    ME->>ME: Detect conflict
    ME->>CR: Call customResolver(localChange, remoteChange)
    CR-->>ME: Return winningChange
    ME->>ME: Apply winning change
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.