Utilizo un patrón en mis servicios donde tengo métodos que siempre devuelven una Entidad, pero depende de ese método recuperarla de la base de datos o crearla de nuevo. Llamo a estos métodos métodos. getOrCreate* Un ejemplo. Los usuarios pueden agregar un a un . Cuando un usuario ingresa una etiqueta "JavaScript", tengo un método en el llamó . En ese método, pongo el nombre en minúsculas y trato de obtener etiquetas de la base de datos con ese nombre homogeneizado. En caso de que lo encuentre, lo recupera; de lo contrario, creará una nueva entidad de etiqueta y la recuperará. Tag Post TagService getOrCreateTag(name: string) Esto puede conducir a un problema. Cuando se producen dos solicitudes al backend exactamente al mismo tiempo, con exactamente la misma cadena, se insertan dos etiquetas con el mismo nombre. (¿Crees que es poco probable? ¡Lee la nota debajo del artículo!) Lo que sucede en cámara lenta: Solicitud A: pregunta si existe esa etiqueta no lo encuentra Decide crearlo Mientras tanto, la solicitud B pregunta si existe esa etiqueta. no lo encuentra Decide crearlo La solicitud A lo crea La solicitud B lo crea Puede evitarlo fácilmente mediante una restricción de clave única. Pero solo cambias el tema. Porque entonces el paso 8 simplemente fallará con una excepción que dejará la aplicación fallando. Una forma de solucionarlo, la describiré aquí implementada con TypeOrm. bloqueo pesimista Siempre se crea un bloqueo de la base de datos durante la escritura en la base de datos. Por ejemplo, los pasos 7 y 8 crean un bloqueo de escritura de muy corta duración. Sin embargo, el problema fue que en los pasos 2 y 5, respectivamente, ambas solicitudes no pudieron encontrarlo y decidieron que lo escribirían en la base de datos. ya Un bloqueo de lectura pesimista es algo que se crea . En TypeOrm necesitas la conexión a la base de datos para eso. manualmente Repositorio: getOrCreateTag(name: string): <Tag> { .manager.transaction( (entityManager: EntityManager): <Tag> => { entityManager .createQueryBuilder(Tag, ) .setLock( ) .where({ name}) .getOne() .then( (result) => { tag = result; ( === tag) { tag = Tag(); tag.name = name; entityManager.save(tag); } tag; }); } ); } async Promise return this Promise return "tag" "pessimistic_read" async let if undefined new return await return Entonces, lo que hace es establecer una transacción (requerida para bloqueos) e intenta obtener la etiqueta. Si no es posible (la etiqueta no está definida), creará una. Hasta aquí todo bien. Si se encontraba con el problema de dos solicitudes que intentaban crear la misma entidad simultáneamente, ahora está mejor. Pero, cuando tenga solicitudes simultáneas, ahora se encontrará con el problema de los . interbloqueos "Se encontró un punto muerto al intentar obtener el bloqueo; intente reiniciar la transacción". interbloqueos Lo que sucede ahora en cámara lenta: Solicitud A: crea un candado Solicitud A: pregunta si existe esa etiqueta no lo encuentra Decide crearlo Mientras tanto, la solicitud B intenta crear un bloqueo encontrará el candado de la solicitud A fallará con el mensaje de arriba La solicitud A lo crea El mensaje significa que reiniciar la transacción. Al igual que los bloqueos son manuales, la captura de errores y el reinicio es manual. debe El servicio getOrCreateTag(name: string): <Tag> { maxTries = ; currentTry = , tryTransaction = ; tag = ; (tryTransaction) { currentTry++; { tag = .tagRepository.getOrCreateTag( name, .createTagService ); } (e) {} ( !== tag) { tryTransaction = ; } (currentTry >= maxTries) { ( ); } } tag; } async Promise const 10 let 0 true let null while try await this this catch if null false // proceed, because everything is fine if throw new Error "Deadlock on getOrCreateTag found." return Esa es mi solución. Si tienes uno mejor, ¡avísame! Aunque es muy poco probable que dos usuarios tengan la misma etiqueta ingresando al mismo tiempo, todavía puede ser. Imagine que un usuario crea una etiqueta, pero usted activa dos solicitudes de backend en el frontend cuando lo hace. Uno para almacenar la etiqueta, otro para enviar una notificación automática a las personas que se han suscrito a esa etiqueta. También hay otras formas con bloqueos optimistas, pero me gusta la idea de dejar que el servicio simplemente "espere" una fracción de segundo. Tengo una aplicación monolítica, así que funciona bien para mí. Dime qué piensas de esto.