Reserva em sistema de bilheteria

5 respostas
spranta

Pessoal, estou desenvolvendo um sistema de bilheteria para teatros, no qual quando o bilheteiro (vendedor) seleciona na tela de venda uma apresentação de um dado espetaculo e informa o numero de ingressos, o sistema já deve reservar automaticamente aquele numero de ingressos para aquela suposta venda, no entanto, somente na confirmação da venda é que os ingressos devem ser definitivamente marcados como vendidos.
Meu problema é que esta aplicação é web, dai que pode acontecer eventualmente da maquina do vendedor dar um pau qualquer e ele sair do sistema enquanto ainda montava a venda, ou seja, ele selecionou alguns ingressos para a compra mas como nao confirmou a venda, tais ingressos ficaram presos no sistema como reservados, quando na realidade deveriam ser liberados, já que o vendedor nao confirmou a venda por um incidente qualquer, fora do controle do sistema.
Enfim, gostaria de saber de voces sobre alguma ideia para resolver este problema.
Por enquanto o que pensei foi o seguinte: Quando o o vendedor seleciona o espetaculo e o numero de ingressos que vai comprar, o sistema guarda aquele valor em atributo statico de uma classe que possui uma lista de ingressos reservados para aquele espetaculo, dai se a venda é confirmada eu tiro aquele valor da lista de ingressos reservados daquele espetaculo, e tudo continua ok, ou seja, quando o vendedor vai conferir a disponibilidade de ingressos ele vai conferir no banco de dados os ingressos vendidos e nesta lista de ingressos reservados que está em memoria. Dai para o caso em que o vendedor sair da venda sem confirma-la, eu pensei no seguinte: haverá no sistema uma thread que vai ficar executando a cada 1 minuto varrendo essa lista de ingressos reservados que estão em memoria e verificando se algum ingresso ali reservado tiver mais de 5 minutos de vida, então ele é expurgado automaticamente, considerando-se nesta situação que tenha acontecido alguma exceção que impediu o vendedor de cancelar aquela reserva ou de concluir a venda. O que vocês acham? Tô achando ruim essa solução porque eu tenho um intervalo de 5 minutos ai do ingresso reservado ficar em memoria até ele ser expurgado.

5 Respostas

mvargens

Não precisa ficar lendo um lugar com registros em memória para saber se está reservado ou não.
Se der pau no computador do cara e ele ficar sem contato com o servidor, o próprio servidor vai matar todos os objetos da sessão dele.
Basta vc incluir os ingressos na memória e no final gravar tudo no banco. Caso não seja executado a gravação os objetos morrem e pronto.

Para que consultar no banco e nessa variavel?
Se vc precisa que outros atendentes vejam que denominado ingresso está sendo reservado, vc vai precisar tratar isso no banco de dados usando flags. Criar Classes para compartilhar informaçòes de negócio entre sessões de browser é uma péssima idéia amigo.

spranta

Mas dai vai demorar um tempão (o tempo configurado no servidor de aplicação) para que a sessao do usuario seja finalizada por time-out, eu queria que ela fosse eliminada mais rapido, além disso, colocando em variavel de sessao do usuario os outros bilheteiros nao vao enxergar o ingresso reservado.

Se eu colocar isso no banco piora as situações; primeiro que todo ingresso no banco precisa estar associado a uma venda, portanto se eu for fazer isso eu precisaria criar a venda no banco antes mesmo de confirma-la, o que na minha opiniao nao é o ideal.
E pior, se der o pau na maquina do cara entao como eu iria limpar no banco os ingressos e a venda nao realizada?

mvargens

Se que isso não ajuda, mas seu servidor está mal configurado. Todo mundo faz assim.

Se eu colocar isso no banco piora as situações; primeiro que todo ingresso no banco precisa estar associado a uma venda, portanto se eu for fazer isso eu precisaria criar a venda no banco antes mesmo de confirma-la, o que na minha opiniao nao é o ideal.
E pior, se der o pau na maquina do cara entao como eu iria limpar no banco os ingressos e a venda nao realizada?

Se seu modelo de dados exige que o ingresso esteja associado a uma venda. você deveria fazer dessa forma, afinal é assim que funciona a regra de negócio. Caso contrario o banco de dados foi mal modelado.
Quanto a limpar os dados se a venda não for concluida, um rollback usando JTA resolveria o problema até certo ponto.

Compartilhar informações que estão no banco de dados, jogando na memória vai exigir um absurdo de controle manual.
Primeiro que esse pool de informações não vai poder estar associado a sessão nenhuma. E vai ter que ser carregado junto com a aplicação e nunca com a sessão de um usuário.
Imagine quando um vendedor efetuar a venda. Você vai ter que ficar atualizando essa fonte central de dados e o banco de dados tambem. Se por algum motivo (sistema externo) atualizar o banco e não esse local na sua memória, seu BD vai virar uma zona, ou erros de violaçào de chave no BD vão pipocar a rodo.

O ideal seria vc gravar uma espécie de pré venda no banco de dados. Ja que precisa amarrar o bilhete a uma venda para saber que ele está sendo utilizado. Ou usar um flag dizendo que o bilhete está sendo usado na própria tabela de bilhete.
Enfim, vc precisa guardar a informação que te diz que o bilhete está sendo usado em algum lugar comum a toda a aplicação.
Nada mais natural que o BD. Em memória eu não faria. Usaria até uma tabela temporaria se fosse o caso, mas na memória eu não faria. Se por acauso der um StackOverFlow em alguma parte da VM vc está fud…
Fora o controle de threads.

Acho mais facil lidar com inserts e deletes.

Outra solução seria usar uma tabela associando um id (da sessão por exemplo), data da criação e bilhete.
Para consultar os bilhetes vc pode ir nessa tabela e pesquisar pela data. Se tiver passado um tempo consideravel de criação vc ignora o bilhete nessa tabela e usa ele.
Claro que vc vai precisar controlar a deleção desses registros perdidos. Mas é mais seguro que guardar em memória.

spranta

mvargens, voce me convenceu de que é melhor gerenciar via BD do que em memoria, no entanto, meu maior problema será como excluir as reservas do BD caso o vendedor não conclua a venda.
Voce disse:

MInha gerencia de transações é feita pelo Spring, como funcionaria esse roolback usando a JTA, não enxerguei muito bem a sua solução. E porque até certo ponto, o que ficaria pendente nesta solução?

mvargens

O Spring consegue usar JTA sem problemas. Basta ver na documentação como se faz isso.

Quanto ao rollback até certo ponto é o seguinte:
Para que todas as sessões consigam ver que o bilhete está sendo usado vc vai precisar comitar isso no banco. Senão só a sua sessão do banco é que vai ver os inserts ou updates.
Sendo assim após o commit no banco, não tem mais como dar rollback entendeu?
Dai só deletando mesmo.
Mas se usar uma solução como a da tabela com data e id do bilhete, vc pode deletar todos os registros absoletos a cada verificação.
É só uma ídéia precisa ser trabalhada.

Outra solução seria usar cascade no banco.

Criado 28 de maio de 2008
Ultima resposta 29 de mai. de 2008
Respostas 5
Participantes 2