Criar política personalizada de resolução de conflitos

Concluído

Pode haver momentos em que você deseja escrever sua própria lógica para resolver conflitos entre itens. Isso pode ser feito usando uma política de resolução de conflitos personalizada.

Uma política de resolução personalizada usará um procedimento armazenado para resolver conflitos entre itens em regiões diferentes. Todos os procedimentos armazenados personalizados devem ser implementados com a seguinte assinatura de função JavaScript.

function <function-name>(incomingItem, existingItem, isTombstone, conflictingItems)

Cada um destes quatro parâmetros é necessário na função:

Parâmetro Descrição
existenteItem O item que já está comprometido
incomingItem O item que está sendo inserido ou atualizado que gerou o conflito
isLápide Booleano indicando se o item recebido foi excluído anteriormente
conflitantesItens Matriz de todos os itens confirmados no contêiner que entram em conflito com incomingItem

Um exemplo de implementação de um procedimento armazenado para resolver conflitos usando o /metadata/sortableTimestamp incluiria o código a seguir.

function resolveConflicts(incomingItem, existingItem, isTombstone, conflictingItems) {
  if (!incomingItem) {
    if (existingItem) {
      __.deleteDocument(existingItem._self, {});
    }
  } else if (isTombstone) {
  } else {
    if (existingItem) {
      if (incomingItem.metadata.sortableTimestamp > existingItem.metadata.sortableTimestamp) {
        return;
      }
    }
    var i;
    for (i = 0; i < conflictingItems.length; i++) {
      if (incomingItem.metadata.sortableTimestamp > conflictingItems[i].metadata.sortableTimestamp) {
        return;
      }
    }
    delete (conflictingItems, incomingItem, existingItem);
  }

  function delete (documents, incoming, existing) {
    if (documents.length > 0) {
      __.deleteDocument(documents[0]._self, {}, function (err, responseOptions) {
        documents.shift();
        delete (documents, incoming, existing);
      });
    } else if (existing) {
      __.replaceDocument(existing._self, incoming);
    } else {
      __.createDocument(collection.getSelfLink(), incoming);
    }
  }
}

Você pode usar o SDK do .NET para Azure Cosmos DB para NoSQL para configurar a política de resolução de conflitos personalizada. Para iniciar este exemplo, um contêiner chamado produtos será criado com uma política de resolução de conflitos personalizada.

string databaseName = "cosmicworks";
string containerName = "products";
string partitionKey = "/categoryId";
string sprocName = "resolveConflicts";

Database database = client.GetDatabase(databaseName);

ContainerProperties properties = new(containerName, partitionKey)
{
    ConflictResolutionPolicy = new ConflictResolutionPolicy()
    {
        Mode = ConflictResolutionMode.Custom,
        ResolutionProcedure = $"dbs/{databaseName}/colls/{containerName}/sprocs/{sprocName}",
    }
};

Container container = database.CreateContainerIfNotExistsAsync(properties);

Finalmente, um procedimento armazenado chamado resolveConflicts é criado para dar suporte à política de resolução de conflitos .

StoredProcedureProperties properties = new (sprocName, File.ReadAllText(@"code.js"))

await container.Scripts.CreateStoredProcedureAsync(properties);

Como alternativa, uma política de resolução de conflitos personalizada pode ser configurada sem um procedimento armazenado. Nesse cenário, os conflitos são gravados em um feed de conflitos. O código do aplicativo pode resolver manualmente conflitos no feed.

Usando o .NET, você pode configurar um contêiner para resolução manual de conflitos usando este exemplo de código.

Database database = client.GetDatabase("cosmicworks");

ContainerProperties properties = new("products", "/categoryId")
{
    ConflictResolutionPolicy = new ConflictResolutionPolicy()
    {
        Mode = ConflictResolutionMode.Custom
    }
};

Container container = database.CreateContainerIfNotExistsAsync(properties);