Devo armazenar datas ou regras de recorrência no meu banco de dados ao criar um aplicativo de calendário?

StackOverflow https://stackoverflow.com/questions/4239871

Pergunta

Estou construindo um site de calendário (ASP.NET MVC) Aplicação (pense na versão simples do Outlook) e quero começar a apoiar eventos de calendário que são recorrentes (mensalmente, anualmente etc.)

No momento, estou armazenando datas reais nas minhas, mas queria descobrir se, com recorrência, faz sentido continuar armazenando datas (com algum corte óbvio), ou devo armazenar as opções de recorrência e gerar as datas em tempo real .

Isso me fez pensar em como o Outlook, o Google Mail etc. faz este ou qualquer outro serviço que suporta itens recorrentes do calendário.

Existem sugestões sobre isso?

Foi útil?

Solução

Separe seus dados em duas partes: os dados "canônicos" (a regra de recorrência) e "servir" (datas geradas; somente leitura além da regeneração). Se os dados canônicos mudarem, regenere os dados de "serviço" nesse ponto. Para recorrências infinitas, mantenha algumas instâncias e gerar mais se você acabar (por exemplo, se o usuário olhar para o calendário para 2020).

Se você tivesse velocidade infinita do processador, precisaria apenas dos dados canônicos - mas, na realidade, fazendo todo o processamento de data/hora para todas as regras de recorrência sobre todo É provável que a visualização da página consuma muito tempo ... para trocar algum armazenamento (e complexidade) para salvar esse cálculo repetido. O armazenamento geralmente é bastante barato, em comparação com o cálculo necessário para um grande número de eventos. Se você Precisa armazenar as datas dos eventos, isso é realmente muito barato - você pode facilmente usar um número inteiro de 4 bytes para representar uma data e, em seguida, gerar uma data/hora completa a partir disso, assumindo que suas recorrências sejam todas baseadas na data. Para recorrências baseadas no tempo (por exemplo, "a cada três horas"), você pode completar os instantes da UTC - 8 bytes representarão isso até uma resolução muito boa pelo tempo que você precisará.

Você precisa ter cuidado para manter a validade - se uma reunião recorrente mudar hoje, isso não muda quando isso tem aconteceu no passado ... então você provavelmente quer também têm dados canônicos somente leitura sobre quando as recorrências realmente ocorreram. Obviamente, você não vai querer que isso mantenha o passado para sempre, então provavelmente deseja "colecionar lixo" mais de alguns anos, dependendo das suas limitações de armazenamento.

Você também pode precisar da capacidade de adicionar notas e exceções (por exemplo, "a reunião não ocorre hoje devido a um feriado público" ou "mudou para as 16h") com base por ocorrência. Isso se torna verdade Diversão quando você muda a recorrência - se você mudar "toda segunda -feira" para "toda terça -feira", você mantém as exceções ou não? Como você combina as exceções quando muda de "todos os dias" para "toda semana"? Essas não são perguntas diretamente sobre o armazenamento - mas as decisões de armazenamento afetarão a facilidade de implementar qualquer política que você decidir.

Outras dicas

Você precisará lidar com eventos e ocorrências separadamente.

Em termos de eventos: para eventos, você precisará armazenar regras de recursão (que podem ser uma rrule como especificada pelo RFC5545, mas também um conjunto explícito de datas como o RDATE no RFC5545), mas também exceções (consulte Exdate de RFC5545 e possivelmente extraculento em RFC244) . Você também precisará acompanhar as alterações nessas regras: alterações no RDATE, Exdate não são problemas quando elas ocorrem no futuro e para serem ignoradas para as datas anteriores. As mudanças no RRULE são mais complicadas como impactar ocorrências anteriores. Minha preferência pessoal é adicionar uma propriedade específica para o antigo e o novo rrule especificar seu respectivo data de início e término da validade.

Se o evento tiver um período de tempo limitado (por exemplo, contagem ou até a propriedade estar presente), você deve armazenar o início e o fim na sua mesa para permitir uma consulta mais fácil de eventos (especialmente ao procurar ocorrências fora da janela de tempo pré -calculada (veja abaixo), ele pode ajudar a reduzir o número de eventos para os quais o cálculo deve ser refeito).

Ocorrências em termos de ocorrência: Para ocorrências, você deve armazenar instâncias em uma janela predefinida em torno do presente (digamos +/- 6 meses ou 12 meses e calculada regularmente) e manter registros disso para permitir o recalculação, se seus usuários desejam ver mais adiante no futuro (para questões de performances). Você também deve considerar a computação do índice (ID-ID de recorrência) para ajudar a encontrar mais fácil a descoberta da próxima ocorrência.

Menos no back-end, mas mais no front-end, você também deve acompanhar as alterações da TZID para perguntar ao usuário se um evento que foi agendado em um determinado TZID se ele deve permanecer no fuso horário atual, precisa ser Atualizado (pense em alguém na ilha de Samoa, que fez uma reunião na sexta -feira, 30 de dezembro de 2011 antes que o país decidisse acontecer "ou" acontecer duas vezes "(mais sobre este tópico aqui)

Nota: Você pode considerar o apoio além do que é definido no RFC5545 em termos de regras de recursão e também adicionar apoio a regras religiosas religiosas ( Veja USNO Introdução aos calendários ou em "cálculos calendários" impressos (terceira edição) de E. reingol e N. Dershowitz).

Como você pergunta sobre a implementação existente, você pode verificar facilmente o esquema de banco de dados do Sunbird (sqlite) ou do Apple Open Source Calendar and Contacts Server, uma lista mais completa de projetos de código aberto existentes para servidores Caldav (que provavelmente é um subconjunto do que você está procurando) está disponível aqui)

Eu tive que construir um sistema que trabalhava com a programação e fizemos as duas coisas. Aqui está o que tivemos

  • Um conjunto de tabelas que acompanharam o cronograma.
  • Uma tabela que acompanhou as instâncias anteriores do cronograma (quando elas realmente ocorreram)
  • Uma tabela que acompanhou a última e a próxima instância (quando o próximo item deve ocorrer com base na última vez), você não precisa desta tabela, mas nós o usamos, porque, caso contrário, você estaria constantemente calculando se um item deve estar ocorrendo agora

Com a programação, as coisas podem ficar realmente complicadas, porque você deve se lembrar de que, a qualquer momento, o cronograma pode mudar. Além disso, um item pode ser devido quando seu aplicativo não estiver em execução e, quando ele inicia novamente, você precisa saber como identificar itens vencidos.

Além disso, garantimos que as tabelas que acompanhassem a programação real estavam sozinhas. A razão para isso é que esses eram o conjunto mais complexo de tabelas do sistema e queríamos poder reutilizá -las para que pudessem ser usadas para coisas diferentes que precisavam de programação. Como enviar e -mails de administrador, enviar notificações e manutenção do servidor, como limpar arquivos de log.

Eu definitivamente usaria sua segunda opção. Use diferentes opções de recorrência, armazene -o separadamente e calcule em tempo real. O armazenamento de todas essas datas seria um monte de dados que não é necessário.

Aqui está uma boa resposta para elogiar sua pergunta.
Estrutura de dados para armazenar eventos recorrentes?

Além disso, como uma nota lateral. Comecei a armazenar tudo como hora da UTC, para que você tenha uma linha de base comum se precisar usar vários fusos horários.

Eu tive um problema semelhante em uma aplicação na web que fiz há alguns anos (pode haver uma maneira melhor agora :)). Eu queria incluir um agendador que tivesse toda a funcionalidade de eventos recorrentes, tempo de manuseio, dias, semanas, meses, anos e exceções, para que eu pudesse ter regras como:

1) Todos os dias às 10h, exceto quartas -feiras

2) A cada 2 horas com no máximo 4 iterações por dia

3) Toda primeira segunda -feira do mês

etc ..

O armazenamento das datas/tempos recorrentes foi possível, mas inflexível. Cada iteração do seu evento muda quando o "máximo" seria. E quão à frente você está?

No final, escrevi uma aula de agendamento personalizada que poderia ler e escrever em uma string. Essa foi a string que foi armazenada no banco de dados e, em seguida, uma função simples pode ser chamada para descobrir quando a próxima ocorrência é.

Você precisa armazenar alguns deles com certeza. O usuário pode editar um dos eventos, deixando os outros intocados (você provavelmente fez a pergunta: "Deseja editar todos os eventos recorrentes ou apenas este?" Em alguns calendários, ou seja, Windows Mobile).

Você também pode querer armazenar eventos anteriores e não removê -los quando o usuário excluir o evento recorrente.

Se você armazenar todos os outros ou gerá -los, é um detalhe de implementação. Eu preferiria gerá -los, se possível.

De qualquer forma, você desejará ter algum ID do evento recorrente armazenado a cada evento, além de algum sinalizador informando se o evento foi modificado posteriormente. Ou em uma abordagem mais complicada, um sinalizador para cada propriedade de evento informando, se for o valor padrão (do evento recorrente) ou se foi modificado para essa instância específica. Você precisará disso quando o usuário decidir editar o evento recorrente.

Observe que a maioria das respostas se inclina para salvar dados gerados. Mas certifique -se de considerar seu caso de uso.

Nos dias em que meus servidores eram limitados por IO, com muita CPU não fazendo nada. Atualmente, você tem SSD (se você pode pagar, caso contrário, sua esquerda com um HD giratório antigo), mas observe que a contagem de núcleos também aumentou.

O bom desse tipo de cálculo é que você pode dividi -los com facilidade e entregá -los aos seus muitos núcleos ou até alguns servidores baratos em uma rede local. Muitas vezes, mais barato do que configurar um cluster NoSQL ou seguir o cluster completo do banco de dados.

E a alternativa também pode ser um cache, basta cache sua visualização do calendário, sem necessidade de fazer todos os cálculos toda vez que nada mudou.

Mas, como dito, depende do seu caso de uso. Não siga as respostas acima, mas faça seus próprios cálculos, se você tiver tempo e tomar uma decisão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top