como implementar chamadas de serviço da web idempotentes


8

Estou desenvolvendo uma solução baseada em wcf para uma camada de serviço da web que dispositivos móveis "conectados ocasionalmente" usarão. O serviço não usará filas (neste estágio) devido às complexidades adicionais e, portanto, estará operando uma abordagem simples de Solicitação / Resposta.

Obviamente, sendo um dispositivo móvel, é possível que os dispositivos fiquem sem sinal no meio da inserção / atualização. O próprio serviço da web pode ter concluído a transação, mas o cliente nunca receberá esta mensagem. Por isso, ele reenviará a solicitação, quando o servidor precisará reconhecê-la como uma solicitação duplicada e retornará a mesma resposta que tentou na primeira instância.

Por isso, estou tentando tornar os serviços idempotentes. Para conseguir isso, estou implementando objetos DTO do Request Paramter, que consistem no RequestID, além dos parâmetros necessários para concluir a chamada.

No entanto, minha dificuldade está em implementar uma maneira de monitorar os IDs de solicitação. Desde que o serviço esteja atualmente sem estado, a única maneira que eu posso imaginar atualmente é ter uma tabela ServiceRequest no banco de dados, que tomará o RequestID como primário. Obviamente, consultar isso indicará se a solicitação já foi acionada, pois o cliente enviará o mesmo RequestID. Mas o serviço também precisa saber qual mensagem enviar. No caso de uma inserção / atualização, o ID raiz agregado afetado também precisará ser armazenado em algum lugar, diretamente na tabela de solicitação ou em uma tabela RequestToObjectLookup

Então, eu estou querendo saber se existe uma maneira de práticas recomendadas de implementar isso? Meu pensamento é ter uma tabela ServiceRequest (específica para o serviço), que armazena solicitações, informações adicionais e também uma pesquisa no ID do objeto de resultado (em um salvar / inserir / atualizar). Portanto, quando uma nova solicitação entra, essa tabela pode ser consultada antes de prosseguir com o restante da solicitação, seja para executar o salvamento ou apenas retornar o objeto atualizado anteriormente (que foi acionado na primeira tentativa de solicitação).

Também estou pensando (como declarado) que só preciso manter o ID agregado raiz referenciado com a solicitação, pois só devo usar os relacionamentos para obter o restante das informações.

Respostas:


2

A exclusão pode ser tornada idempotente, permitindo apenas a exclusão com base nos IDs. Você precisará ter alguma maneira de os IDs permanecerem "em uso" e talvez expirarem.

Com esse sistema de reservas; a criação de um objeto pode ser feita primeiro reservando um ID e, em seguida, uma segunda chamada para criar o objeto com esse ID (essencialmente uma atualização no novo objeto vazio). Quando um ID é solicitado, o servidor pega qualquer ID gratuito e cria um objeto não inicializado com esse ID, a segunda chamada para inicializar incluirá o ID retornado anteriormente (mais todos os dados necessários). Isso significa que a segunda chamada é, em essência, uma atualização chamada idem potente em si (chamá-lo com os mesmos dados várias vezes resultará no mesmo resultado).

Se a reserva ocorrer várias vezes, vários IDs serão retornados e o objeto inicializado permanecerá. Esses objetos não inicializados podem ser limpos por um rhoomba após algum tempo automaticamente.

Isso coloca o ônus no cliente para garantir que, se eles obtiverem um ID, eles sejam responsáveis ​​por chamar a inicialização. Se o cliente cai no meio da transação, ele deve manter seu próprio log para as operações, para saber, por exemplo, que ele obteve um ID e estava ocupado com a inicialização do objeto.

A atualização é mais difícil de tornar idempotente, mas uma operação de comparação e configuração (com resultado verdadeiro / falso) ajudará.


Você poderia explicar um pouco mais sobre o sistema de reservas? Você quer dizer que o cliente precisaria primeiro solicitar um ID do serviço, antes de fazer uma segunda chamada na qual o objeto havia dito o conjunto de IDs?
Milambardo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.