Número 78
3 de xaneiro de 2024

Modificacións simultáneas

Tiven que refacer todo o código dos comentarios por culpa do fallo do meu ordenador vello, pero foi para ben porque a nova versión ten mellor cara que a anterior. Comecei a subilo a GitHub a semana pasada e hoxe vouvos falar de varias maneiras nas que teño que ter coidado ao actualizar a base de datos.

Dous homes queren bater no mesmo cravo cos seus martelos ao mesmo tempo.

Vou gardar os comentarios nunha base de datos que vai ter dúas táboas. Unha é a evidente, chamada “Comentarios”, que vai conter a información de cada comentario. A outra, chamada “Artigos”, vai conter información sobre os distintos artigos que hai na Folla.

En teoría podería ter un sistema de comentarios funcional só coa táboa “Comentarios”, pero na práctica preciso da outra para controlar o spam.

(O meu programa está todo escrito en inglés, pero nesta Folla hei poñer os nomes das táboas e das columnas da base de datos en galego, que se non toleo indo dun idioma ao outro).


Cando deseñedes algo que vai estar en Internet, lembrade sempre que hai xente que quere publicar cousas sen pagar, e se non lles poñedes obstáculos van arruinar os vosos proxectos.

O meu principal medo é que, mentres vos divertides nos comentarios loitando sobre Vi e Emacs, veñan eses ruíns a poñer anuncios de pílulas para a pirola, me enchan o disco duro, me estraguen o ranking en Google, vós vos fartedes e marchedes, e para rematalo os xornais publiquen algo así como “un boletín sobre programación de nombre malsonante se financia vendiendo aumentos de pecho y bitcoins falsos procedentes de Venezuela”.

Polo tanto, para poder facer un control mínimo do spam, preciso de ter a posibilidade de abrir, pechar e inhabilitar completamente os comentarios para un artigo ou para o sitio completo. Iso é o que podo acadar coa táboa “Artigos”.

Hai dúas maneiras nas que quero configurar os comentarios. A primeira é no encabezamento de cada artigo: onda o título, número de episodio e data de publicación vai haber tamén un campo para o estado dos comentarios. Cada vez que execute o meu programa para actualizar a páxina web da Folla, este programa tamén vai actualizar cada rexistro da táboa “Artigos” de acordo co contido dese campo.

A segunda maneira na que podo configurar os comentarios é mediante unha interface web. No medio dun ataque de spam, os segundos contan e ninguén pode agardar a que eu chegue á casa, abra o meu ordenador, actualice o ficheiro, faga git commit e git push. Hai que facelo rápido!

Para iso é a interface web: estea onde estea, podo conectarme desde o móbil e pechar os comentarios con dous clics. E, por suposto, esa interface web tamén actualiza a correspondente fila da táboa “Artigos”.

Como hai dúas maneiras de configurar os comentarios dun artigo teño que ter coidado porque, se non, poden pisarse unha á outra e producir efectos non desexados.

A porta dun cuarto de aseo, con alguén dentro queixándose de que a xente non tira da cadea despois de facer spam.

Por exemplo, imaxinade que hai un ataque de spam no martes pola noite e eu desactivo os comentarios na web e marcho para a cama. Mentres durmo, sae unha nova Folla (ás dez da mañá en España pero ás catro onde eu vivo), o meu programa ve que os comentarios estaban abertos no encabezamento do artigo e volve abrilos, e cando esperto atopo dous millóns de mensaxes de príncipes nixerianos. Obviamente, eu non quero que iso ocorra.

Pola outra banda, se despois de pechar os comentarios na web decido modificar o encabezamento do artigo para eliminalos completamente, quero que o programa de actualización da Folla garde a nova configuración.

Estes dous obxectivos que aparentan ser incompatibles son moi doados de acadar ao mesmo tempo usando dúas columnas na táboa “Artigos” para gardar a configuración dos comentarios: unha que chamei “Configuracion” (non souben pensar nun nome mellor) e outra chamada “ConfigWeb” que pode conter un valor NULL.

A columna “Configuracion” é modificada polo programa que fai as actualizacións da Folla, e recibe o valor establecido no encabezamento do correspondente artigo. En cambio, a columna “ConfigWeb” é modificada pola interface web da que vos falei enriba.

Cando chega o momento de saber se os comentarios dun artigo están abertos, pechados ou desactivados, o programa olla o contido das dúas columnas, usando a “ConfigWeb” preferentemente a menos que conteña un NULL.

Cando chega a hora de facer as actualizacións da Folla, o programa compara o contido da columna “Configuracion” co valor establecido en cada encabezamento. Se é o mesmo, o programa non fai nada con ese rexistro, pero se son diferentes, o programa actualiza a columna “Configuracion” e tamén pon un NULL en “ConfigWeb”.


Outra razón pola que teño que ter coidado ao modificar o contido da base de datos é que é posible facer cambios no mesmo rexistro da mesma táboa a un mesmo tempo, e se non os fago ben podo acabar cun resultado impredicible.

Por exemplo, se os papamerdas (a suxestión que me fixo o corrector ortográfico cando atopou a palabra spammers, e que vou adoptar con efecto inmediato) están a facer as súas trangalladas no mércores pola mañá e eu estou a pechar comentarios, e xusto nese momento se activa o programa para publicar unha nova Folla, que ocorre se mudo a configuración dun artigo mentres o programa actualiza a base de datos?

Na programación de sistemas, á que estou afeito, a solución sería simple: usaría exclusión mutua para que só unha das funcións que modifican eses datos puidera funcionar ao mesmo tempo. Porén, isto é programación web sobre bases de datos SQL, así que teño que usar outras técnicas.

Hai moito tempo faleivos dunha desas técnicas: antes de gravar o novo valor na base de datos teño que comprobar que ninguén fixo un cambio no mesmo rexistro. Polo tanto, cando eu lle dou ao botón de “modificar configuración dos comentarios”, o meu programa le a configuración orixinal; despois eu fago os meus cambios nun formulario e, cando lle dou a “enviar”, o frontend non envía só a nova configuración, senón que tamén envía a configuración orixinal.

Cando o backend recibe a petición, compara a configuración existente na base de datos coa configuración orixinal que o frontend lle mandou. Se os valores son idénticos, todo está ben e é posible facer a modificación. En cambio, se son diferentes, iso indica que alguén fixo un cambio mentres eu facía o meu; o programa, daquela, vai rexeitar o cambio e amosar unha mensaxe que avisa da circunstancia.

Dous disquetes están a correr; un casete está detrás deles pero desesperada porque a súa fita magnética está a enlearse.Carreira de datos.

Esta técnica, porén, é vulnerable a unha carreira de datos (“data race”). De pouca axuda vai ser se, no medio de todas esas comprobacións, alguén consegue meter un cambio entre o momento no que o backend le a “configuración existente na base de datos” e o momento no que a compara coa que lle forneceu o frontend.

As bases de datos SQL teñen un mecanismo para evitar que isto ocorra: as transaccións. As operacións realizadas en distintas transaccións están illadas unhas das outras, e existen varios niveis de illamento, desde “só se ven os resultados finais das outras transaccións, non os resultados das operacións intermedias” ata “se outra transacción fixo cambios nos rexistros que eu quero modificar, esta transacción fracasa”.

O meu programa vai usar unha combinación destes dous niveis de illamento. Para as operacións de lectura e consulta vou usar o primeiro (chamado “Read Committed”) e para as de modificación vou usar o nivel máis estrito (“Serializable”).

Con isto e cun pouco código para volver executar algunhas transaccións falladas, debería abondar para que o meu código funcione correctamente. Dito isto, teño que confesar que hai moitísimos anos que non traballo cunha base de datos SQL, así que igual hai cousas que non sei ou non lembro. Mentres o sistema de comentarios non estea listo, tirádeme unhas poucas liñas a a@folla.gal coas vosas puntualizacións e eu publicareinas aquí abaixo e tereinas en conta para o programa.