Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Zup Tech Hour - Race Conditions em Microsserviços: um problema comum em arquiteturas distribuidas

Jordi Henrique Silva
April 14, 2023
49

Zup Tech Hour - Race Conditions em Microsserviços: um problema comum em arquiteturas distribuidas

Talk apresentada no Zup Tech Hours no dia 13 de abril de 2023. Discutimos o que é Race Conditions, e heurística para la identifica e exploramos 3 soluções, sendo elas @Syncronized da JVM, Pessimistic Locking e Optimistic Locking.

Ficou interessado?
Assista nesse endereço: https://www.youtube.com/live/80I5zv1sDHo?feature=share

Jordi Henrique Silva

April 14, 2023
Tweet

Transcript

  1. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  2. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  3. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  4. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  5. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  6. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  7. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  8. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  9. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  10. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  11. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  12. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  13. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  14. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  15. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  16. João Maria select p.* from poltrona p where id =

    1 select p.* from poltrona p where id = 1
  17. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  18. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara:
  19. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara:
  20. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1
  21. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1
  22. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1 1 linha atualizada
  23. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1 1 linha atualizada
  24. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }
  25. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }
  26. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }
  27. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }
  28. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }
  29. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  30. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  31. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }
  32. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }
  33. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }
  34. João Maria select p.* from poltrona p where id =

    1 for update select p.* from poltrona p where id = 1 for update
  35. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  36. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  37. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  38. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  39. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João

    Maria COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  40. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  41. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update
  42. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  43. @Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable

    = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false @field:Version var version: Long ) { @Id @GeneratedValue var id: Long? = null; }
  44. @Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable

    = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false, var version: Long ) { @Id @GeneratedValue var id: Long? = null; }
  45. @Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable

    = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false, @field:Version var version: Long ) { @Id @GeneratedValue var id: Long? = null; }
  46. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  47. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  48. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun

    reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }
  49. update poltrona set version = 1, reservado = true, reservadoPara

    = :user where id = :poltronaId and version = 0
  50. João Maria select p.* from poltrona p where id =

    1 select p.* from poltrona p where id = 1
  51. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version:

    0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  52. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version:

    0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  53. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version:

    0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  54. Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version:

    0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  55. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  56. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  57. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  58. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  59. 1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado:

    false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria OptimisticLockException select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1
  60. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0
  61. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0
  62. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1
  63. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0
  64. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 OptimisticLockException
  65. João POST /poltronas/1/reservas select p.* from poltrona p where id

    = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 OptimisticLockException HTTP 500
  66. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }
  67. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }
  68. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }
  69. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }
  70. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }
  71. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status<Any>(CONFLICT, ex.message) } }
  72. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status<Any>(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }
  73. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status<Any>(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }
  74. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status<Any>(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }
  75. @Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable

    id: Long, @QueryValue usuario: String): HttpResponse<Void> {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status<Any>(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }
  76. Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de

    conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações
  77. Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de

    conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações
  78. Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de

    conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações
  79. Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de

    conflitos, ambientes altamente concorrentes Vantagem: Não exige mudanças no codigo Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações
  80. Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de

    conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações
  81. Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de

    conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações
  82. Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de

    conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações
  83. Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de

    conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações
  84. Se você usa o Banco de dados ... ... apenas

    como repositório. VOCÊ ESTA SUB-UTILIZANDO!