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

Race Conditions em Microsserviços: Desmistifica...

Race Conditions em Microsserviços: Desmistificando um Problema Comum em Arquiteturas Distribuídas

Os microsserviços são uma realidade na arquitetura de sistemas distribuídos, porém, o aumento da complexidade desses sistemas trouxe novos desafios, em especial na garantia da integridade e consistência dos dados de negócio. Com a crescente adoção de microsserviços, problemas de concorrência, como Race Conditions e Lost Update, se tornaram mais frequentes e podem comprometer a eficiência dos seus sistemas. Nesta talk, vamos explorar as causas que levam a problemas de Race Conditions em microsserviços, assim como heurísticas para identificar e controlar situações de concorrência.

Talk apresentada na trilha de Microsserviços II no TDC CONNECTIONS 2023.
Talk apresentada na Weekly II no TDC CONNECTIONS 2023.

Jordi Henrique Silva

March 24, 2023
Tweet

More Decks by Jordi Henrique Silva

Other Decks in Technology

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!