Caso Real: Podcastvery.com -> Migración y scrapear datos
El contenido central es resolver las típicas dudas que pueda tener alguien que tiene o quiere tener una web en Drupal.
Aparte de resolver dudas de "clientes", también se habla de tips, recomendaciones y buenas prácticas para el Developer que recién empiezan en este mundo.
Hoy vengo a contarte los problemas que estoy teniendo para obtener datos de 1.5 millones de podcasts.
Problemas en disco, bloqueos en la base de datos, motivos para no usar el módulo migrate y formas de usar comandos Drush y Cron.
Hola, bienvenido o bienvenida otra semana más aquí a Drupalízate, el podcast donde te hablo de mis proyectos Drupal o de cómo hago cosas con Drupal. Este... Estaba pensando si sería el último episodio, creo que no va a ser el último de lo que es Podcast Verde, tranquilos, tranquilos, de lo que es el tema de hablar del proyecto Podcast Verde. Hoy toca hablar de lo que es el tema de migración o indexación de datos y problemas que estoy teniendo con espacio en disco, ¿vale? Con tal cantidad de datos. Dicho esto, quizás la semana que viene publique otro episodio haciendo un repaso de cosas que han cambiado. Más que nada porque este es el último episodio que estoy grabando en julio, aunque seguramente se va a publicar a finales de agosto, así que con un mes de margen puede que hayan cambiado cosas. Así que esto lo hago porque no tengo vacaciones porque soy freelance, pero tengo un poco más de margen de descanso durante agosto. Así que cuando se publique este episodio seguramente estaré grabando ya el siguiente y ya comentaré si se han cambiado cosas o no. Dicho todo esto, yo estoy haciendo un repaso para la gente que no ha escuchado los dos episodios anteriores. Estoy hablando del proyecto Podcastvery.com, que es un buscador e indexador de podcast, con lo cual estoy indexando datos de un millón y medio de podcast con todos sus episodios, lo cual implica que tengo una base de datos, al día de hoy, ya veremos agosto como acaba, pero antes de que acabe julio tengo 200 y pico gigas en MySQL. O sea, no estoy contando las imágenes que están en Site Default Files, o sea, no cuento las imágenes de la portada de los podcast. Solo en texto, en títulos, urls y descripciones tengo 200 gigas o más de 200 gigas. Es una burrada, ¿vale? Empezamos por aquí, si un caso, y criticando a Drupal. Y esto no me vais a escuchar muchas veces criticando a Drupal. ¿Cuál es el problema principal y por qué tengo tantos gigas en base de datos? El problema principal son las revisiones de Drupal. Al final, todos los datos que estoy guardando los creo, o los guardo, como nodos. Al final tengo lo que son los podcasts, que son, pues cojo la url y sus datos y lo creo como un podcast. Después, parte de esos datos, que son títulos y descripciones y urls al fichero de audio de cada episodio, lo creo como otro tipo de nodo, que es episodio, con un entity de referencia al podcast, con lo cual ya tengo dos tipos de contenido, tengo podcast y episodios. Estos contenidos son siempre automáticos, o sea, son migraciones automáticas. Y después tengo otro tipo de contenido que solo se crea manualmente por usuarios, que son las listas de podcast, donde básicamente los usuarios añaden podcast manualmente y yo qué sé. Mi recomendación de los mejores podcasts de terror, o de aprender inglés, o de marketing, pues añaden los podcasts manualmente. Es una forma de hacer recomendaciones, de hacer listas de recomendaciones de tus preferencias. Pero bueno, en el caso de las migraciones, este último del tipo de contenido de listas no afecta porque, como digo, es una cosa que se crea manualmente y hay apenas, no llega a 30 listas actualmente en podcast video, o sea, no es una cosa... El problema son los 20 millones de episodios y el 1 millón y pico de podcast. Sobre todo, como digo, el problema es los episodios. Tengo muchísimos nodos que son un título, descripción y URL de cada episodio. En algunos casos son, digamos, de tamaño pequeño porque la descripción son cuatro líneas, como es el caso de Endu Pariseret, de que yo no me mato mucho haciendo descripciones, pero en algunos podcasts son la Biblia y media, o sea, meten una descripción del episodio larguísima. Así que lo primero que he hecho para intentar limitar esto, aunque actualmente aún se está indexando y tengo descripciones indexadas antiguas muy largas, pues la idea es limitar el número de caracteres. O sea, a partir de cierto número de caracteres, limito y ya lo corto para que solo se guarde en base de datos un límite de caracteres ya establecido. Por cierto, antes de eso también hago una limpieza de HTML. Elimino todo el HTML que está en las descripciones porque como las descripciones de los episodios no se tienen que mostrar completas en mi web, me es igual si los corto o si elimino el HTML. Y digo que elimino el HTML parcialmente, no lo elimino todo, porque por el tema de ser JAPI, que esto creo que no lo comenté la semana pasada, de tu poder especificar que detecte dentro de la HTML pues h1, h2 o negritas, por ejemplo, y que a estas palabras que están en un h1, h2 o negritas les dé mayor peso. O sea, que si alguien busca marketing, y marketing es una palabra que en tu podcast está marcada con negrita o como un h1 o un h2, le va a dar mayor peso. Esto realmente en los podcasts la gente no acostumbra poner HTML en las descripciones, pero sí que me he encontrado en algún caso que están, con lo cual es, mira, ya que está pues lo hago, lo hago bien. Elimino todo HTML que no sea h1, h2 o negritas y los que lo son les doy mayor peso, ya que han intentado poner títulos sin negritas pues mira, les doy un poco más de posicionamiento SEO entre comillas en mi buscador. Dicho todo esto, igualmente sigue pensando una burrada la base de datos. ¿Por qué? Por las revisiones. Drupal, para quien no sepa, por defecto, cuando guardas un nodo te guarda una tabla, o sea, tienes una tabla para cada campo. Si tengo un título, una descripción, perdón, el título no es un campo bien bien, el título ya está incluido dentro de la tabla del nodo, pero si tienes un campo descripción, un campo URL y un campo fecha de publicación o frecuencia, en el caso de los podcasts calculo la frecuencia, si es un podcast semanal o mensual o anual o lo que sea. La frecuencia queda cuando se publica un episodio nuevo. Si tengo esos tres campos, que en verdad yo tengo más de tres, pero simplificando, tengo esos tres, pues el campo descripción tiene una tabla en base de datos que es el campo descripción y otra tabla que es la revisión de la descripción. Con lo cual en verdad tengo dos tablas que son el mismo campo, pero una es la revisión de la otra. Lo mismo para un campo tipo link, lo mismo para un campo tipo enlace, un campo tipo numérico, un campo tipo lo que sea. Siempre tenemos otra tabla, una copia de la tabla original, que es la revisión. En verdad no es una copia exacta, o no siempre es una copia exacta, porque las revisiones de Drupal sirven para cuando las tienes activas. Si un editor, un usuario, edita un contenido y, ¡ay! la he liado, he eliminado ese enlace, quiero recuperar la copia de este texto de cómo estaba hace una semana, pues las revisiones sirven para esto. Ves las últimas revisiones y recupera el contenido viejo que has eliminado o has modificado sin querer o queriendo. O sea que depende del caso de uso del proyecto, es muy útil tenerlo activado. En mi caso, no. No lo quiero tener activado y no me sirve para nada tenerlo activado. Juraría que en Drupal 7, por clorido de memoria, las revisiones eran un módulo que podías desactivar. No estaban dentro de los nodos. O sea, no estaban dentro del core como tal de Drupal. Estaban en el core, pero se podían desactivar. O juraría que se podían desactivar. En Drupal 8 o Drupal 9 no se pueden desactivar. A lo sumo, le puedo especificar que este tipo de contenido no quieres que tenga revisiones, pero internamente te va a seguir duplicando las tablas. Seguirás teniendo dos tablas de descripción y en este caso sí que sean exactamente una copia una de la otra. Porque no tiene revisiones activadas, con lo cual realmente se guarda siempre la última revisión. Que coincidencia, es el mismo texto que el contenido publicado, porque es la última revisión. Así que estoy teniendo tablas duplicadas. Tablas que tienen más de 30 GB en algunos casos. Así que, como se puede imaginar, tengo muchos GB que realmente son contenido duplicado. Y los que pesan más es el tipo de contenido que tenga más cantidad, que son los episodios. Y aquí vengo con la puya de Drupal es, si no quiero revisiones, no me crees tablas duplicadas. Estuve buscando issues en Drupal VRG y hay gente que se queja de lo mismo. Si yo activo tablas que no las quiero, para qué coño me las duplicas. No te las puedes eliminar, no puedes hacer un trunque y dar tablas para eliminar y recuperar espacio. Porque en algunos casos te puedes romper la web. Porque en algunos módulos se hacen queries a estas tablas de revisiones y después pides contenido. Así que no es lo más recomendable estar eliminando tablas que te crea automáticamente Drupal. Si Drupal las crea, es que las usa para algo. El problema es que desde mi punto de vista, conceptualmente esto está mal. Si yo activo tablas que no quiero revisiones, es por algún motivo, no me quede tablas duplicadas. Pero bueno, hasta aquí la puya de Drupal. Quizá para el tema de proyectos donde la edición, o la mayoría de la edición, no la hace un usuario final. Sino que es cosas automatizadas, que hay un script que está constantemente creando y creando contenidos. Con 20 millones de nodos o de páginas, no sé hasta qué punto le recomendaría Drupal para qué tipo de proyectos. Este proyecto me ha dado cuenta de esto. Si tienes muchos tipos de contenido, muchas páginas, puedes ser útil. Pero si tienes muchas páginas, empiezas a ver las limitaciones a PHP, MySQL y CMS como Drupal. Y eso que no me escuche mucha gente, ¿vale? Pero es que es verdad, al final, una cosa que no me pensaba que tenía este problema, que tablas duplicadas, que pensaba justamente que Drupal me elimina, me soluciona estos problemas, en verdad no, me está dando problemas nuevos. Pero bueno, dicho todo esto, el problema también se puede atribuir a mi culpa. Fue mi decisión meter los episodios de los podcasts como nodos, o sea, como un tipo de contenido separado a lo que es el nodo original. Lo hice básicamente por simplicidad, porque en el script que tengo de la migración, es muy cómodo estar creando nodos nuevos de episodios o actualizando episodios viejos. Pero bueno, como digo, fue por comodidad. En este proyecto en concreto, los episodios no tienen URL, no son nodos visibles como tal, o sea, uso el rabbit hole para evitar que esos nodos sean indexables y visibles para la gente. Solo se ven dentro de la página del podcast cuando hay una views que muestra los episodios, pero como digo, no hay una página para cada episodio, con lo cual realmente, si no hay una página, no hay una URL, no me hace falta como tal que sean un nodo. Lo que estoy pensando que intentaré hacer durante este mes de agosto, entre comillas de vacaciones, es reconvertir todo esto y que en vez de que sean nodos, pues hacer que los episodios se miran directamente como datos en el Elasticsearch en un índice solo de episodios. Con lo cual, me ahorraría las consultas a Maya SQL y me ahorraría el tema de tablas duplicadas de Maya SQL de Drupal. El problema es que tengo que ser mucho más código custom y la implementación va a ser más lenta, sobre todo ahora que ya tengo datos en base de datos. Pero bueno, es para que lo tengas en cuenta en tu caso de uso, en tu proyecto, que si realmente no te hace falta que sean nodos, piénsatelo muy bien, qué implicaciones puede tener guardar los contenidos en nodos cuando realmente no hace falta que sean nodos. Los podcasts, en mi caso, han de ser nodos sí o sí, porque cada podcast tiene que tener su URL, quiero que se gestione con Serjapi, quiero que se gestione con Pathauto, han de ser nodos, pero los episodios fue cajada mía decidir que fueran nodos. Basicamente, como digo, es por simplicidad, creía que no había ningún problema. Pero bueno, vi que el cuello de botella fue justamente el tema de los episodios. Dicho todo eso, también, en el momento de la indexación, claro, por ejemplo, pueden haber podcasts que tengan 100 episodios. En el momento de indexar ese podcast, por primera vez, cuando indexo el podcast y sus episodios, creo un nodo tipo podcast con los datos correspondientes y para cada episodio creo un nodo nuevo, con lo cual estoy quedando en nada, en un momento, 100 episodios, 100 nodos y un podcast, un nodo. O sea, siento un nodos de golpe. El problema es que me he encontrado con esto, al crear tantos nodos de golpe, me revienta, me da error de conexión con base de datos del dialogue, hay bloqueo en base de datos, se están quedando demasiados nodos al mismo tiempo. Y lo de 100 nodos de golpe es un ejemplo, pero en verdad estoy podiendo quedar perfectamente 2000, 3000, 5000 nodos de golpe, porque como, bueno, creo que no lo he comentado aún, ahora lo comentaré como va al tema de importación, pero estoy quedando muchos nodos de golpe. Y me he encontrado con esto, de que estoy teniendo bloqueos de base de datos en el momento de la escritura. Así que mi suposición es de, si lo muevo esto, la creación de episodios, a Elasticsearch, voy a solucionar este tema, o eso espero. Así que os lo comentaré en el próximo episodio, que para mí será de aquí un mes. Vale, dicho esto, ¿cómo estoy haciendo yo la importación? Decidí, viendo lo bien y lo mal que me fue con Babiso, que en Babiso fue una migración hecha con el módulo Migrate y con Codio Custom, pero la base era usando el módulo Migrate en Drupal. Viendo las ventajas y desventajas que tuve en ese proyecto, decidí en este hacer toda la migración en Codio Custom. Hice un script en Drash, o sea, al final es Drupal, es PHP, es un comando Drash que creé yo nuevo, que me permite, le puse varios parámetros a ese comando, y dependiendo de qué parámetros, pues me permite usar el mismo script para varias cosas. Al final, de forma simplista, me obtiene un número limitado de nodos que tiene la URL ya puesta. Porque, a ver, perdón, dos temas. Primero, hay dos scripts. Un script que me coge el Postgres, la base de datos original, donde están todas las URL, y me convierte cada URL en un nodo. Y ya está, no hace nada más. Es un comando que he ejecutado dos o tres veces, para ser probado en local y una vez en producción, y ya está. Después, tengo otro script en Drash, que es el que comentaba antes, que coge una lista, creo que por defecto eran 30 o 50 nodos, que tienen URL, que son los nodos que se han quedado en el primer paso que he comentado antes, y después va URL a URL, obtiene los datos del feed del podcast, como título, descripción, autor, categoría, datos de iTunes, lo que sea, y los guarda en campos dentro del nodo. Y después, también obtiene los datos de los episodios que están dentro del mismo feed, y crea nodos nuevos para cada uno de los episodios, con la referencia al nodo que se ha guardado previamente. Dicho esto, ¿qué parámetros, o algunos de los parámetros que tengo yo en ese comando Drash? Uno sería, pues, sólo actualizar los nodos que no tienen, o sea, que están vacíos, que sólo tienen la URL. O sea, nodos nuevos, o sea, podcasts nuevos. De esta forma puedo priorizar que se ejecute un comando, o varios comandos Drash, que me están actualizando sólo los podcasts que aún no han sido indexados ni una sola vez. Otro parámetro que hay es el tema de la frecuencia. De esta forma, con el mismo comando Drash puedo especificar de que me está actualizando sólo los podcasts que una vez ya se han importado, tengan en el campo frecuencia, pues, yo que sé, que sean semanales, o diarios, o mensuales. Y jugando con la fecha, puedo decirle de que me esté ejecutando, o mejor dicho, actualizando los nodos, que la frecuencia sea semanal y que hace más de una semana que no se han actualizado. Al final es para evitar estar constantemente mirando si los podcasts semanales, mensuales, o semestrales se han actualizado, los actualizo una vez cada, pues, igual a su frecuencia. Si es semanal, pues una vez a la semana. Si es mensual, una vez al mes. Si es semestral, o trimestral, pues una vez al trimestre o semestre. Y si es diario, en ese caso sí, una vez al día o cada dos días. Es una forma simple de intentar quitar peso en la CPU del servidor. O sea, intentar optimizar lo máximo posible que no se esté malgastando llamadas a servicios externos cuando realmente no hay apenas cambios en un mes. Así que, digamos que esto es un comando dash custom que me obtiene el nodo, del nodo me lee el campo URL, hace una llamada curr a un fit, obtiene los campos, digo que al final el fit es un XML, me procesa los valores, a unos casos me los limpio un poco, y me guarda el nodo actual y me quedan nodos nuevos. Vale, pero esto no lo ejecuto yo manualmente, siempre, ¿no? No estoy cada día ejecutando el comando dash. ¿Por qué lo hice como comando dash y no como el migrate y como lo hice con Babiso? Uno de los principios problemas que me encontré yo con Babiso y con migrate es el tema de ejecutar importaciones periódicas. En este caso, más que periódicas, serían constantes, porque no es una vez al día, sino que estoy constantemente ejecutando ese tipo de migraciones. Mi punto de vista es que el migrate se queda corto, y por rendimiento, sobre todo, se queda corto. O sea, leer datos y procesarlos es más lento. Sí que es verdad que te facilita la vida como programador, y es mucho más rápido de implementar ese tipo de funcionalidad. Y si es una migración que se ejecuta una vez, pues mira, que se tarden un par de horas más en ejecutarse, vale, es igual. Si me ahorra esas dos horas de trabajo, pues vale. Pero viendo lo que me llevó en Babiso y que valores de cabeza que he tenido, y cómo ejecutarlo desde Chrome o estas cosas, dije, voy a probarlo en hacerlo directamente todo custom. O sea, un comando rash y lo ejecuto todo por aquí. ¿Y por qué como comando rash? Porque no lo meto como un cron. O sea, no se ejecuta con el cron del propio Drupal, sino que tengo una talla cron a nivel de servidor que me ejecuta ese comando rash. Y no me ejecuta el comando rash una vez, sino que tengo una ejecución del cron para cada uno de los valores de esos parámetros que he recomendado. Con lo cual, en verdad, al mismo tiempo estoy ejecutando el mismo comando con distintos valores en los parámetros, pues uno o varios para los podcasts diarios, cuatro o cinco para los que son podcasts nuevos para que me los indexe cuanto antes mejor, un par para los que son podcasts mensuales, otro par para los que son podcasts semestrales, ya así, ¿vale? Y con otros parámetros. Es una forma de tener un único comando y que por cron se esté ejecutando simultáneamente más de una vez al mismo tiempo. Ah, y por cierto, aquí me he olvidado comentar, algunos de esos parámetros, por ejemplo, son un parámetro limit, que básicamente siempre tengo el mismo, que creo que hay unos 30, 40 o 50, no mucho más, y después un parámetro offset, porque de esta forma, en la llamada al cron, le estoy dando un offset en plan de, por decir algo, importame del 0 al límite 50, si es que lo digo de memoria, no me acuerdo de 150, pero del 0 al 50, el siguiente que me importe del 100 al 150, el siguiente del 300 al 350, o sea, al final le doy un offset muy, o algo distante entre ellos, para que si uno acabe, cuando empiece el otro, que no se pisen, ¿vale? Y si que, al menos, aunque se pisen, como es una cuedia de datos que te ordena por fecha, no se van a acabar de pisar nunca. Pero es una forma, como digo, de tener un único comando que me está ejecutando al mismo tiempo, varias cosas, y en mi caso ha sido una forma más óptima que no hacerlo por Migrate, porque por Migrate acababa teniendo muchas migraciones, y acaba siendo con distintas llamadas, y todas se tenían que ejecutar desde concorde o custom, pero se ejecutaban con un comando, de, a ver como digo, usando el cron propio de Rupal, se ejecutaban todos al mismo tiempo, y el problema es que cuando alguna daba fallos, me bloqueaba, por ejemplo, la indexación, porque no se ejecutaba el cron de la indexación en search API, y en PodcastBerry esto no me pasa. Como el cron de Rupal va aparte de la creación de nodos, si peta uno, no me peta el otro, ¿vale? Lo estoy diciendo de forma muy simplista, pero digamos que en mi caso de uso en este proyecto en concreto, me sirve mucho más no usar Migrate. En otros proyectos, porque lo he usado en varios, sobre todo si son migraciones que se ejecutan una o dos veces manualmente y ya está, recomiendo mucho más Migrate. Pero esto va, es que depende del caso, depende del tipo de migración, depende si es una migración, yo que sé, si es tipo CCV o un poco más estándar, que Migrate ya te da muchas sospechas, pero en mi caso que es un XML, y es un XML un poco raro porque es uno de los feeds de los podcast, y que tenía que hacer cosas custom, al final he acabado, creo que ha sido mejor idea, y hasta aquí creo, defiendo mi opinión, de que hacerlo custom en mi caso ha sido mejor para este proyecto en concreto. Vale, ¿qué más? Ah, como antes también, aparte de leer una base de datos y obtener las URLs de la base de datos, también creé un modo custom que te crea un formulario, o sea hay un formulario en la web que pones la URL, hace una pequeña validación que es una URL de on-feed, y si esa misma URL no está indexada ya, crea un nodo nuevo y le añade, crea un nodo nuevo vacío, solo con el campo URL ya lleno, para que en el cron, en el siguiente, se indexe y de alta los valores del podcast. Pero como digo, es un módulo pequeño muy custom que valida si esa URL ya ha sido migrada o no, y te crea un nodo en base a eso, para que después el script de migración lo actualice. ¿Qué más tengo por aquí apuntado? Problemas de actividad, como ya he comentado, comandos dash también, y problemas de disco y espacio, como lo comentaba antes, aunque consiga mover todo lo que tengo de episodios a un LASICsearch, y mi opinión es moverlo a LASICsearch porque ya que tengo todo el tema montado de las búsquedas, pues me es cómodo moverlo allí, quizás se podría mover directamente a otra base de datos, o a un Postgres, o a un MySQL, pero aparte, al final es evitar que me dupliquen tablas, que es lo que me hace Drupal, aunque arregle todo esto, o aunque por dicho de otra forma, aunque eliminase todo el contenido de los episodios, se quedaría teniendo un millón y pico de podcast. Igualmente, se hacía una tabla en MySQL más grande de 10 GB, estoy haciendo una estimación un poco así a lo tonto, pero en mi caso, por mi conocimiento, los proyectos tener tablas de 1 GB, 2 GB, ya es una burrada en MySQL en casos de Drupal. Se hace igualmente porque no he trabajado en proyectos, o al menos no, cuando hay proyectos iniciales, como al final había poco contenido, no se llegaba a estos límites. Como digo, aún así, sean tablas muy grandes que pesan varios GB. Tengo que ver si realmente fue buena decisión del todo o no que los podcasts fueran nodos, sobre todo sabiendo que puedo llegar a 4 millones de nodos. Pero bueno, son cosas a tener en cuenta en proyectos Drupal de esta envergadura, pensar si realmente hace falta que sean nodos y realmente si no queremos tener ni revisiones ni nada de esto, si nos merece la pena tener un MySQL tan grande, tan hinchado. Por ejemplo, en la página de administración de contenidos, lo que vemos ya en la URL es admin.content, el listado de nodos tardaba la vida en cargar, hasta en algún caso me daba fallo de timeout, de conexión. Y es porque es una BIOS que tiene un paginador por defecto, el paginador completo. Tiene un join con la tabla del autor del nodo. En mi caso, como los nodos son creados automáticamente, el autor siempre es el admin. Total, que yo entre en la configuración de la BIOS, por suerte en Drupal es todo configurable, y desde la BIOS configuré de, mira, el autor no quiero que se muestre en ninguna columna, el join con la tabla de usuarios para ver el autor te lo cargas, no quiero que haya un join aquí en medio, y la paginación, en vez de que sea paginación completa, que sea la paginación simple, de página siguiente a página anterior, que no haya enumertos, que no te cuente la cantidad de páginas disponibles. Porque eso por rendimiento es una patada. Tener joins y tener paginaciones completas es una patada, no funciona bien por rendimiento. Fue al cambiar eso y la página de contenido a mí como administrador me carga muchísimo más rápido. Ahora es usable, pero claro, es que tengo 20 millones de páginas de nodos dentro. Son cosas a tener en cuenta que al final, con tanto contenido, toda la web se acaba resintiendo de una o de otra forma. Y nada, que esto, que es un proyecto que me ha servido a mí para ver hasta dónde puedo exprimir el Drupal, hasta ver dónde llego con los límites de la cantidad de datos, qué problemas me puedo encontrar de rendimiento. Cualquier cosa que he visto que por código funcionaba un poco mal, me acababa provocando muchos problemas en el servidor. Porque cuando venía Google y me estaba indexando de golpe, o Google o AlgomBot, porque no sé si era Google, cuando algo estaba navegando por las URLs de mi web, un pequeño error me estaba provocando caídas de rendimiento y lo notaba porque el servidor estaba un poco al límite, porque como estaba constantemente escapando feeds, a la que el servidor subía 80 de CPU, se notaba. Es a tener en cuenta de esto, cuando tienes muchas páginas y vos que estás indexando esas páginas, cualquier cosa la notas. Por ejemplo, una de las tonterías, yo uso href para temas de SEO, me di cuenta, porque mala configuración mía de href, que te está intentando indexar los enlaces de los facets, los filtros facetados de las páginas de búsquedas, href, si no le marcas lo contrario, va a detectar que eso es un enlace normal y ya da click y te lo va a intentar indexar. Con lo cual, para cada página donde hay facetados, el href, que es para temas de SEO e indexación, va a detectar que hay URL, que son distintas porque es la misma URL con un parámetro detrás, y de una URL de una página te va a generar, yo qué sé, 2000 páginas, porque son las 2000 posibilidades que tienes de combinación de filtros. Eso es una putada, básicamente porque me fundí el... no es el presupuesto porque tengo la versión gratuita de href, pero el límite que tengo mensual me lo fundí en un día y eso provocó también que al mismo tiempo, ese día que se estuvo indexando, la CPU del servidor estuviera a 1000, porque se estaban generando las 1000 páginas posibles para todas las combinaciones de filtros, y la solución fue configurar bien href y modificar el robot.xt para decirle a los robots o incentivar a los robots que no indexen ese tipo de páginas, o sea que indexen pero que cuando no hayan parámetros, para que no esté generando aquí contenido duplicado. Como digo, eso también fue más culpa mía que no de Drupal, o sea, era el problema mía de configuración, pero que te das cuenta con tantos contenidos a la que haces alguna tontería mal te repercute a nivel de servidor muy simple. Por cierto, hablando de servidores, ¿cuánto estoy pagando y qué tengo yo en ese servidor? Y voy a pasar esto un momento porque no lo sé y lo tengo que mirar, así que ahora vuelvo. Vale, ya estoy aquí. Primero de todo, están en Hezner, igual que otros proyectos que ya he comentado, básicamente porque por precio-rendimiento creo que es lo mejor que hay en Europa actualmente. Y por tema de backups y tal, a mí me va perfecto. Estoy contentísimo con ellos, lo comenté creo que en el episodio con Babiso, si es un caso también os puedo dejar otra vez el link al artículo del blog donde lo comenté yo y también hay códigos de… es afiliado, si lo usáis, creo que tenéis un 20 euros o 10 euros de descuento para hacer pruebas, y yo también recibo algo si al final acabáis renovando con ellos. Pero lo mismo, que si también usáis Digital Ocean o Linode, que yo los usé y también tengo afiliados con ellos, yo recomiendo mucho más Hezner, aunque me pagan menos afiliación, pero básicamente porque los encuentro que son mejores. Y que apruebes cosas que no todo es Amazon Web Service, que yo para mí lo encuentro carísimo lo que es Amazon Web Service. Pero bueno, aquí hay cada uno que haga lo que quiera. De hecho, todo esto. Yo tengo Hezner Potencia, tengo el de mayor potencia del plan estándar, del cloud de Hezner, son 16 CPUs y la verdad es que me sobran, ¿vale? O sea, voy a tirar perfectamente con la mirada, con 8 CPUs, sobre todo porque ahora mismo, bueno, ahora mismo voy a tirar con 2, porque lo que son las migraciones, justamente hoy las he pausado porque estoy a tope de disco, ¿vale? Ahora vamos con ello, pero estoy a punto de llegar a 100% de disco, he pausado las migraciones para que no siga indexando porque tengo que arreglar el problema que comentaba antes de las revisiones y de mover los datos, tengo tablas duplicadas y tengo muchos gigas que realmente no hacen nada. Así que bueno, eso, que ahora mismo los tengo parados y que podría tirar perfectamente con nada, con 2 CPUs, pero bueno. Lo tenía con el 1016 y lo sigo teniendo con el 1016. Yo creo que con 8 podía tirar de normal, con 8 CPUs, porque los skips de indexación consumen CPU, pero yo creo que con 8 tiraría perfectamente. De RAM, tengo 32 gigas y me sobran, pero me sobran muchísimo, o sea, la RAM apalada, o sea, podría tirar con muchísima menos. El problema es que aquí en Hezner va todo junto, o sea, no puedes redimensionar solo 2 CPUs o 2 RAM, es que CPU y RAM van de la mano. Si quiero tener 16 CPUs, voy con 32 gigas y el problema es que, aunque no me hagan falta ninguno de esos dos, si quiero tener más disco duro, he de ir con más RAM y con más CPU. Y el problema yo lo tengo con el disco duro. Actualmente tengo 360 gigas de disco duro y como digo estoy llegando casi al 100%. Claro, tengo 200 y pico solo de base de datos, más lo que son imágenes, más lo que ella hace por sí, aparte de lo que es el código tu pal, que es nada, pero lo que es el sistema operativo, que también suma un poco. Pero a lo que voy es que lo que me pesa más como tal es la base de datos. Así que tengo que arreglar esto. Bueno, total, 300 gigas de base de datos, perdón, de disco, espacio en disco, y 20 teras, que tampoco me los consumo, de transferencia. Aquí también se incluye la transferencia que uso yo para ir a escreper contenido externo. O sea, no solo la transferencia de usuarios que navegan por mi web, sino mi web cuando va a obtener datos externos, también se consume esa transferencia. Y total, ¿qué pago por todo esto? Un maquinón de 16 CPUs, 32 de RAM y 360 de disco. ¿Qué estoy pagando? 49 euros. Bueno, en verdad es más porque se tienen que sumar el término de los backups, pero son 50 y algo. 50 y algo euros es lo que estoy pagando. A ver si me suena bien. Es que no me lo aguanta con el total del backup. Bueno, normal son 49.40, si se suma el término de los backups, no llega a 60 euros. Es que no me sale el precio aquí total, tendría que haber la última factura que pagué. Que al final es un servidor entre comillas caro. Son 50 y algo euros al mes. Para hacer un side project es el más caro que tengo yo actualmente. O sea, el que mayor recurso me está pidiendo de ese servidor, tengo que optimizar el tema del consumo en disco, sobre todo ver cómo lo hago. Pero tampoco lo encuentro tan caro. Para la potencia que tiene la máquina, realmente lo encuentro hasta barato y todo. Ya lo comenté en episodios pasados, eso es porque yo me lo administro. Esto es un servidor no administrado, te hace falta alguien que sepa de sistemas. O un conocimiento mínimo al menos. Y yo me lo gestiono yo solo, con lo cual no he de pagarle a nadie más. Es uno de los motivos por los que para mí es tan barato tener un VPS. Y creo que nada más. Y creo que no me dejo nada. Si la semana que viene, depende de si he solucionado en este último mes el problema del disco o no, es lo que voy a comentar el siguiente episodio. Y si no, pues nada. Os comentaré ese raro servidor porque es una mierda, porque estoy esto a huevos, no sé, ya veremos. A ver, que yo creo que sí, que moviendo todo a la Sixth Search o a otras opciones si la Sixth Search no me funciona como tal. Pero a ver, a mí este proyecto me sirvió para aprender muchas cosas. Sobre todo el funcionamiento de la Sixth Search y los procesadores para crear campos falsos y optimizar el tema de indexaciones. Y el tema de búsquedas de texto y optimizarla y el tema de búsquedas similares y recomendaciones por palabras clave y tal. No había hecho, es que ni para clientes reales, o sea para clientes de agencias, no había hecho nada que me obligase a aprender tanto de Setjapi. Normalmente instas el javi, configuras cuatro cosas y es un, ah, ya está, lo que pienso no se puede. No, sí que se puede, hace falta un poco más de trabajo. Pero para eso justamente es por lo que hago Side Projects. Pero también salí un poco de mi zona de confort, forzándome a mí mismo a hacerlo. Y voy con la calma de que si, como no es de un cliente, si realmente no consigo hacerlo o hacer lo que yo quiero, tampoco pasa nada. Es un proyecto mío personal, no le he prometido nada al cliente porque cliente soy yo mismo, ¿vale? Es una forma de saber hasta dónde puedo llegar y a futuros clientes qué les puedo prometer porque sé que se puede o que no se puede hacer. Y nada más. Así que hasta la semana que viene. Chao.
¿Tienes algún proyecto en mente?
Si quieres hacer algo en Drupal tal vez puedas contratarme.
Ya sea para consultoría, desarrollo o mantenimiento de sitios web Drupal.