Maneiras de versão documentos gerados pelo usuário

8

Eu tenho um documento online que basicamente é armazenado no banco de dados como uma string XML.

Estou pensando em uma maneira de implementar a versão do documento para o usuário. Para que o usuário possa voltar às versões anteriores do documento.

update No meu caso, é um aplicativo da web com centenas de milhares de usuários. Um usuário pode armazenar uma quantidade ilimitada de documentos. O XML do documento é armazenado no campo blob do MySQL, portanto, não é pequeno. Eventualmente, preciso limitar os limites de alguma forma, mas esse é um tópico diferente.

Existe uma maneira padrão de abordar isso? Devo armazenar apenas as diferenças entre as versões? Quais são as outras coisas que eu preciso considerar?

desenvolvedor
fonte
1
A questão interessante aqui é: você possui um infraestrutura de banco de dados MYSQL existente em que os dados precisam ser integrados (especialmente um sistema dimensionado para muitos usuários)? A sugestão de Crazy Eddie da RCS não parece fácil de ser integrada a esse sistema.
Doc Brown
Qual é o modelo de segurança - presumo que os documentos de cada usuário sejam privados?
Michael
@ Michael Sim cada usuários documentos são privados
dev.e.loper
@DocBrown Sim, eu tenho uma tabela Mysql db existente onde esses documentos xml estão armazenados agora.
dev.e.loper
@ dev.e.loper: Eu acho que a privacidade não é imposta pelo servidor DB, certo? O número de usuários mencionados indica que você está falando sobre uma solução de servidor da Web em escala. A questão aqui colocada é: você deseja / deve manter os dados XML no banco de dados ou está livre para escolher uma tecnologia diferente para essa parte dos dados?
Doc Brown

Respostas:

13

Por que não usar um repositório de controle de origem? Isso exigirá menos espaço de armazenamento, fará tudo o que você deseja no momento e permitiria que você ampliasse o conceito com mais facilidade em ramificações, tags, etc ... tudo o que você obtém de um RCS. Por que reinventar a roda?

Edward Strange
fonte
Como exatamente você quer dizer? Você está dizendo para instalar o SVN no meu servidor e usar a API para armazenar esses arquivos?
dev.e.loper
Existe um gargalo em algum lugar nessa abordagem? Por exemplo, se eu tiver 50.000 usuários salvando / versionando seu trabalho. O repositório de controle de origem precisa lidar com o controle de versão para os 50.000 corretos?
dev.e.loper
O OP está falando de um banco de dados (eu acho, um existente). Não conheço nenhum sistema de controle de origem que se integre facilmente a um esquema de banco de dados existente.
Doc Brown
@ dev.e.loper - um RCS decente, incluindo o SVN, deve ser capaz de lidar com muitos usuários.
Edward Strange
5

Como você está fazendo isso em um banco de dados, a maneira mais fácil de versionar sua cadeia XML seria criar uma nova tabela Histórico com as seguintes colunas:

  • ID do histórico
  • Nova sequência XML (coluna opcional)
  • String XML antiga
  • Inserir carimbo de data e hora

Insira uma linha nesta tabela Histórico antes de atualizar a linha na tabela de cadeias XML.

Gilbert Le Blanc
fonte
Se você atualizar a linha na tabela de cadeias XML, não há como obter a versão anterior. Tudo o que você pode fazer é ver um histórico das datas de alteração. Você precisaria fazer inserções em vez de atualizações ... de preferência de diferenças.
Edward Strange
@CrazyEddie: A versão anterior (versão antiga) está na tabela Histórico. As diferenças não são necessárias para um documento.
Gilbert Le Blanc
"Diferenças não são necessárias" - você não sabe o tamanho do documento, a frequência com que ele é alterado e se o OP talvez não significasse "um documento por usuário". Portanto, "nenhuma diferença necessária" é apenas um palpite. No entanto, dei +1 a você, pois acho que sua resposta aponta para a direção certa. Mas você pode melhorá-lo, explicando melhor o que essas colunas "nova versão" e "versão antiga" deve conter (cordas XML, a referência a IDs de história anteriores, ou algo mais?)
Doc Brown
@ Doc Brown: E você não sabe quantas vezes a versão antiga da string XML é necessária, para não mencionar o tempo e o esforço para escrever um mecanismo diff, que também precisa ser modificado. Você nem sabe se o banco de dados compacta as strings de texto. Corrigi as referências da coluna.
Gilbert Le Blanc
@ GilbertLeBlanc: Nós dois não sabíamos disso (quando o OP escreveu sua primeira versão da pergunta) - e por isso eu não teria escrito "diferenças são necessárias" ou "diferenças não são necessárias" aqui. Eu sugeriria apenas não começar com uma solução diff mais complicada, se uma solução simples não diff puder ser suficiente. Eu acho que é isso que você quis dizer.
Doc Brown
3

Existe uma maneira padrão de abordar isso?

Para uma abordagem baseada em padrões, dê uma olhada na extensão Delta-V para WebDAV (ela própria uma extensão amplamente suportada para HTTP). O Delta-V adiciona versão ao WebDAV e é descrito na RFC 3253 .

Caleb
fonte
1

Uma maneira relativamente simples é incrementar um ID de revisão a cada salvamento e salvar o novo documento xml sob esse novo ID de revisão.

tabela: docs

doc_id | name          | current_revision
   1   | Shopping List |       5         

tabela: doc_revisions

doc_id | revision | timestamp | xml_blob
  1    |    1     | 2012...   |
  1    |    2     | 2012...   |
  1    |    3     | 2012...   |
  1    |    4     | 2012...   |
  1    |    5     | 2012...   |

Você também pode considerar armazenar os arquivos xml separadamente no sistema de arquivos. Você pode alterar a tabela doc_revisions com uma URL / caminho para o arquivo em vez de um blob. Isso permitirá que o seu banco de dados lide com volumes muito mais altos em um único servidor, porque o banco de dados não será fisicamente tão grande (você pode mover os documentos para um servidor diferente) e levaria a carga de recuperação de documentos do servidor de banco de dados.

Pessoalmente, eu não armazenaria as diferenças de arquivo. Em vez disso, eu armazenaria a nova revisão completa do arquivo a cada vez. O armazenamento é barato e não há necessidade de complicar as coisas. A funcionalidade 'diff' poderá ser implementada mais tarde se, eventualmente, você realmente precisar dela. Se você armazenar diferenças, lembre-se de que isso pode apresentar um monte de complexidades inesperadas, por exemplo, se você precisar pesquisar o texto dos documentos.

GrandmasterB
fonte
Tanto quanto armazenar as diferenças de arquivo, eu estou olhando para armazenar diffs com ajuda de diff-match-patch biblioteca code.google.com/p/google-diff-match-patch
dev.e.loper
1

Por que não imitar um log de banco de dados?

Basicamente, as alterações são marcadas cronologicamente como transações. Para um banco de dados de documentos, uma transação consistiria em um diffs blob + timestamp em vez de uma entrada de linha da tabela, mas o conceito funciona da mesma maneira. Praticamente da mesma maneira que os sistemas de controle de versão funcionam.

Para manter as coisas rápidas, mantenha uma cópia em cache da versão atual. Se alguém precisar voltar no tempo, poderá reverter (ou seja, reverter) as transações até atingir o histórico solicitado de que precisa. A ideia é que a cópia em cache não seja alterada até que uma operação de salvamento seja executada.

Para manter a consistência, você também precisa levar em consideração as reversões. Seguindo o que já descrevi, digamos que o usuário volte 5 versões. 5 transações seriam aplicadas inversamente em ordem cronológica reversa para a versão atual, mas quando esse estado é salvo, a transação é armazenada como um diff desse estado em comparação com a versão atual.

Basicamente, a história nunca é reescrita, apenas reutilizada para criar novas versões.

Evan Plaice
fonte