All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.cosmos.models.ConflictResolutionPolicy Maven / Gradle / Ivy

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.cosmos.models;


import com.azure.cosmos.implementation.Constants;
import com.azure.cosmos.implementation.JsonSerializable;
import com.azure.cosmos.implementation.Paths;
import com.azure.cosmos.implementation.Resource;
import com.azure.cosmos.implementation.StoredProcedure;
import com.azure.cosmos.implementation.Strings;
import com.fasterxml.jackson.databind.node.ObjectNode;


/**
 * Represents the conflict resolution policy configuration for specifying how to resolve conflicts
 * in case writes from different regions result in conflicts on items in the container in the Azure Cosmos DB
 * service.
 *
 * Refer to: https://docs.microsoft.com/en-us/azure/cosmos-db/conflict-resolution-policies
 *
 * 

* A container with custom conflict resolution with no user-registered stored procedure. *

{@code
 *
 * CosmosContainerProperties containerProperties =
 *      new CosmosContainerProperties("Multi-master container", "Multi-master container partition key");
 * containerProperties.setConflictResolutionPolicy(ConflictResolutionPolicy.createCustomPolicy());
 *
 * CosmosAsyncDatabase database = client.createDatabase(databaseProperties).block().getDatabase();
 * CosmosAsyncContainer container = database.createContainer(containerProperties).block().getContainer();
 *
 * }
 * 
*

* A container with custom conflict resolution with a user-registered stored procedure. *

{@code
 *
 * CosmosContainerProperties containerProperties =
 *      new CosmosContainerProperties("Multi-master container", "Multi-master container partition key");
 *
 * ConflictResolutionPolicy policy = ConflictResolutionPolicy.createCustomPolicy(conflictResolutionSprocName);
 * containerProperties.setConflictResolutionPolicy(policy);
 *
 * CosmosAsyncDatabase database = client.createDatabase(databaseProperties).block().getDatabase();
 * CosmosAsyncContainer container = database.createContainer(containerProperties).block().getContainer();
 *
 * }
 * 
*

* A container with last writer wins conflict resolution, based on a path in the conflicting items. * A container with custom conflict resolution with a user-registered stored procedure. *

{@code
 *
 * CosmosContainerProperties containerProperties =
 *      new CosmosContainerProperties("Multi-master container", "Multi-master container partition key");
 *
 * ConflictResolutionPolicy policy = ConflictResolutionPolicy.createLastWriterWinsPolicy("/path/for/conflict/resolution");
 * containerProperties.setConflictResolutionPolicy(policy);
 *
 * CosmosAsyncDatabase database = client.createDatabase(databaseProperties).block().getDatabase();
 * CosmosAsyncContainer container = database.createContainer(containerProperties).block().getContainer();
 *
 * }
 * 
*/ public final class ConflictResolutionPolicy { private JsonSerializable jsonSerializable; /** * Creates a LAST_WRITER_WINS {@link ConflictResolutionPolicy} with "/_ts" as the resolution path. *

* In case of a conflict occurring on an item, the item with the higher integer value in the default path * {@link Resource#getTimestamp()} ()}, i.e., "/_ts" will be used. * {@link Resource#getTimestamp()}, i.e., "/_ts" will be used. * * @return ConflictResolutionPolicy. */ public static ConflictResolutionPolicy createLastWriterWinsPolicy() { ConflictResolutionPolicy policy = new ConflictResolutionPolicy(); policy.setMode(ConflictResolutionMode.LAST_WRITER_WINS); return policy; } /** * Creates a LAST_WRITER_WINS {@link ConflictResolutionPolicy} with path as the resolution path. *

* The specified path must be present in each item and must be an integer value. * In case of a conflict occurring on an item, the item with the higher integer value in the specified path * will be picked. * * @param conflictResolutionPath The path to check values for last-writer wins conflict resolution. * That path is a rooted path of the property in the item, such as "/name/first". * @return ConflictResolutionPolicy. */ public static ConflictResolutionPolicy createLastWriterWinsPolicy(String conflictResolutionPath) { ConflictResolutionPolicy policy = new ConflictResolutionPolicy(); policy.setMode(ConflictResolutionMode.LAST_WRITER_WINS); if (conflictResolutionPath != null) { policy.setConflictResolutionPath(conflictResolutionPath); } return policy; } /** * Creates a CUSTOM {@link ConflictResolutionPolicy} which uses the specified stored procedure * to perform conflict resolution *

* This stored procedure may be created after the {@link CosmosContainerProperties} is created and can be changed as * required. * *

    *
  • This method requires conflictResolutionStoredProcFullPath in format * dbs/%s/colls/%s/sprocs/%s. User can also use equivalent method {@link #createCustomPolicy(String, String, String)}
  • *
  • In case the stored procedure fails or throws an exception, * the conflict resolution will default to registering conflicts in the conflicts feed
  • *
  • The user can provide the stored procedure @see {@link Resource#getId()}
  • *
* * @param conflictResolutionStoredProcFullPath stored procedure full path to perform conflict resolution. * @return ConflictResolutionPolicy. */ public static ConflictResolutionPolicy createCustomPolicy(String conflictResolutionStoredProcFullPath) { ConflictResolutionPolicy policy = new ConflictResolutionPolicy(); policy.setMode(ConflictResolutionMode.CUSTOM); if (conflictResolutionStoredProcFullPath != null) { policy.setConflictResolutionProcedure(conflictResolutionStoredProcFullPath); } return policy; } /** * Creates a CUSTOM {@link ConflictResolutionPolicy} which uses the specified stored procedure * to perform conflict resolution *

* This stored procedure may be created after the {@link CosmosContainerProperties} is created and can be changed as * required. * *

    *
  • In case the stored procedure fails or throws an exception, * the conflict resolution will default to registering conflicts in the conflicts feed
  • *
  • The user can provide the stored procedure @see {@link Resource#getId()}
  • *
* * @param dbName database name. * @param containerName container name. * @param sprocName stored procedure name to perform conflict resolution. * @return ConflictResolutionPolicy. */ public static ConflictResolutionPolicy createCustomPolicy(String dbName, String containerName, String sprocName) { return createCustomPolicy(getFullPath(dbName, containerName, sprocName)); } /** * Creates a CUSTOM {@link ConflictResolutionPolicy} without any {@link StoredProcedure}. User manually * should resolve conflicts. *

* The conflicts will be registered in the conflicts feed and the user should manually resolve them. * * @return ConflictResolutionPolicy. */ public static ConflictResolutionPolicy createCustomPolicy() { ConflictResolutionPolicy policy = new ConflictResolutionPolicy(); policy.setMode(ConflictResolutionMode.CUSTOM); return policy; } /** * Initializes a new instance of the {@link ConflictResolutionPolicy} class for the Azure Cosmos DB service. */ ConflictResolutionPolicy() { this.jsonSerializable = new JsonSerializable(); } /** * Instantiates a new Conflict resolution policy. * * @param jsonString the json string */ ConflictResolutionPolicy(String jsonString) { this.jsonSerializable = new JsonSerializable(jsonString); } /** * Instantiates a new Conflict resolution policy. * * @param objectNode the object node. */ ConflictResolutionPolicy(ObjectNode objectNode) { this.jsonSerializable = new JsonSerializable(objectNode); } /** * Gets the {@link ConflictResolutionMode} in the Azure Cosmos DB service. * By default it is {@link ConflictResolutionMode#LAST_WRITER_WINS}. * * @return ConflictResolutionMode. */ public ConflictResolutionMode getMode() { String strValue = this.jsonSerializable.getString(Constants.Properties.MODE); if (!Strings.isNullOrEmpty(strValue)) { try { return ConflictResolutionMode .valueOf(Strings.fromCamelCaseToUpperCase(this.jsonSerializable.getString(Constants.Properties.MODE))); } catch (IllegalArgumentException e) { this.jsonSerializable.getLogger().warn("INVALID ConflictResolutionMode getValue {}.", this.jsonSerializable.getString(Constants.Properties.MODE)); return ConflictResolutionMode.INVALID; } } return ConflictResolutionMode.INVALID; } /** * Sets the {@link ConflictResolutionMode} in the Azure Cosmos DB service. * By default it is {@link ConflictResolutionMode#LAST_WRITER_WINS}. * * @param mode One of the values of the {@link ConflictResolutionMode} enum. */ ConflictResolutionPolicy setMode(ConflictResolutionMode mode) { this.jsonSerializable.set(Constants.Properties.MODE, mode.toString()); return this; } /** * Gets the path which is present in each item in the Azure Cosmos DB service for last writer wins * conflict-resolution. * This path must be present in each item and must be an integer value. * In case of a conflict occurring on an item, the item with the higher integer value in the specified * path will be picked. * If the path is unspecified, by default the {@link Resource#getTimestamp()} ()} path will be used. *

* This value should only be set when using {@link ConflictResolutionMode#LAST_WRITER_WINS} * * @return The path to check values for last-writer wins conflict resolution. * That path is a rooted path of the property in the item, such as "/name/first". */ public String getConflictResolutionPath() { return this.jsonSerializable.getString(Constants.Properties.CONFLICT_RESOLUTION_PATH); } /** * Sets the path which is present in each item in the Azure Cosmos DB service for last writer wins * conflict-resolution. * This path must be present in each item and must be an integer value. * In case of a conflict occurring on an item, the item with the higher integer value in the specified * path will be picked. * If the path is unspecified, by default the {@link Resource#getTimestamp()} ()} path will be used. *

* This value should only be set when using {@link ConflictResolutionMode#LAST_WRITER_WINS} * * @param value The path to check values for last-writer wins conflict resolution. * That path is a rooted path of the property in the item, such as "/name/first". */ ConflictResolutionPolicy setConflictResolutionPath(String value) { this.jsonSerializable.set(Constants.Properties.CONFLICT_RESOLUTION_PATH, value); return this; } /** * Gets the {@link StoredProcedure} which is used for conflict resolution in the Azure Cosmos DB service. * This stored procedure may be created after the {@link CosmosContainerProperties} is created and can be changed as * required. * *

    *
  • This value should only be set when using {@link ConflictResolutionMode#CUSTOM}
  • *
  • In case the stored procedure fails or throws an exception, * the conflict resolution will default to registering conflicts in the conflicts feed
  • *
  • The user can provide the stored procedure @see {@link Resource#getId()} ()}
  • *
* * * * @return the stored procedure to perform conflict resolution.] */ public String getConflictResolutionProcedure() { return this.jsonSerializable.getString(Constants.Properties.CONFLICT_RESOLUTION_PROCEDURE); } ConflictResolutionPolicy setConflictResolutionProcedure(String value) { this.jsonSerializable.set(Constants.Properties.CONFLICT_RESOLUTION_PROCEDURE, value); return this; } void populatePropertyBag() { this.jsonSerializable.populatePropertyBag(); } JsonSerializable getJsonSerializable() { return this.jsonSerializable; } private static String getFullPath(String dbName, String containerName, String sprocName) { if (dbName == null) { throw new IllegalArgumentException("dbName cannot be null"); } if (containerName == null) { throw new IllegalArgumentException("containerName cannot be null"); } if (sprocName == null) { throw new IllegalArgumentException("sprocName cannot be null"); } StringBuilder builder = new StringBuilder(); builder.append(Paths.DATABASES_PATH_SEGMENT); builder.append("/"); builder.append(dbName); builder.append("/"); builder.append(Paths.COLLECTIONS_PATH_SEGMENT); builder.append("/"); builder.append(containerName); builder.append("/"); builder.append(Paths.STORED_PROCEDURES_PATH_SEGMENT); builder.append("/"); builder.append(sprocName); return builder.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy