Colección de citas famosas - Consulta de diccionarios - Escribe una vez y almacena en cualquier lugar: el sistema de archivos escalable de Go

Escribe una vez y almacena en cualquier lugar: el sistema de archivos escalable de Go

Foto de Caroline Selfors en Unsplash

Estoy haciendo la maleta para un viaje en avión y me acabo de dar cuenta de que no tengo suficiente espacio para toda mi ropa. Mi maleta solía funcionar bien; aparentemente mis necesidades han cambiado.

Puedo meter todo allí y atarlo con una cuerda. ¿O podría meter la ropa extra en tres bolsas de compras y llevar las cuatro por el aeropuerto? Esto no tiene buena pinta. Recomponer o cambiar por completo la forma en que guardo mi ropa es una forma terrible de planificar un viaje: necesito algo mejor. Algo más sencillo. Por supuesto, todo lo que realmente necesitaba era una maleta más grande. Las maletas son intercambiables, simplemente cambia tu ropa de una a otra.

Mi dilema ahora es un poco tonto y obvio, pero resulta que el almacenamiento intercambiable también es muy adecuado para el almacenamiento de software. El sueño del software portátil es "escribir una vez y ejecutar en cualquier lugar". El software también debe tener datos de portabilidad. Ya sea que almacene sus datos en un depósito, disco o navegador web de S3, deben ser fácilmente intercambiables.

Desafortunadamente, a menudo no es tan simple: cada nueva "maleta" de datos no se puede colocar de la misma manera, se utiliza un embalaje poco convencional o, si te parece gracioso, se desmoronará. Sin estándares acordados o procesos de revisión, puede resultar difícil determinar un sistema de almacenamiento para su programa. No es necesario cambiar su programa para adaptarlo al sistema de almacenamiento exclusivo y adaptarse a cambios futuros no debería ser difícil. Necesitamos interfaces comunes para diferentes tipos de almacenamiento y un conjunto de pruebas compartido para revisarlas.

Los estándares de almacenamiento comunes pueden ayudar a resolver estos problemas, pero necesitan una adopción generalizada en la comunidad para que sean efectivos. El primer paso para adoptar una norma es introducirla en un diseño conocido y procedente de una fuente conocida. Por ejemplo, Go introdujo una interfaz de sistema de archivos en la biblioteca estándar, sentando las bases para que los desarrolladores puedan desarrollarse. Utiliza el humilde archivo, un paquete familiar de datos, organizado en carpetas para formar un sistema de archivos. El patrón de sistema de archivos "en capas" de Go es una buena opción porque ya se usa ampliamente en otros campos. Desde álbumes de fotos en teléfonos inteligentes hasta marcadores en navegadores web, los patrones de sistemas de archivos están en todas partes en el software actual. Los sistemas de archivos parecen ser una excelente opción para una interfaz de almacenamiento universal.

Durante el desarrollo de Hackpad, comenzaron a aparecer grietas en nuestro sistema de almacenamiento, pero carecíamos de herramientas para repararlas. La mayoría de nuestros componentes requieren el uso de varios sistemas de almacenamiento diferentes para leer y escribir datos. Con cada nuevo sistema de almacenamiento, escribíamos y reescribíamos el código del adaptador cada vez, lo que generaba mucha rotación. Comenzó como un simple almacén en memoria, luego progresó a un lector de archivos .tar.gz en streaming y luego a un sistema de archivos superpuesto. Cuando necesitábamos agregar también almacenamiento basado en navegador, quedó claro: se necesitaba una abstracción nueva y flexible.

En este artículo, analizaremos un modo de sistema de archivos nuevo y escalable para programas Go y cómo funciona. La interfaz del sistema de archivos de Go, io/fs.FS, abre la puerta a nuevas posibilidades. Abramos esta puerta con HackpadFS.

Abrimos nuestra biblioteca HackpadFS para definir una interfaz de sistema de archivos común y compartir un conjunto de pruebas rigurosas para que todos puedan crear sistemas de archivos personalizados y portátiles. Lleva el sistema de archivos básico de Go a un nivel completamente nuevo:

A continuación, exploremos nuevas posibilidades con el sistema de archivos integrado, la interfaz común y el conjunto de pruebas maduro de HackpadFS.

Un sistema de archivos o FS es una colección de archivos ubicados por una "ruta". Si ha utilizado paquetes de Goos antes, ya ha utilizado FS. Sin embargo, es importante tener en cuenta que las funciones estáticas del paquete del sistema operativo no se pueden utilizar como objetos que implementan interfaces comunes.

No se puede intercambiar con otras implementaciones y sus datos solo están en un almacenamiento. La interfaz io/fs.FS de Go nos da una idea de las posibilidades de un sistema de archivos intercambiable. Usando HackpadFS, podemos probar una variedad de nuevos sistemas de almacenamiento sin tener que reescribir nuestro código.

Coloca los mismos datos en el nuevo almacenamiento. Foto de Aleksei Ieshkin en Unsplash

HackpadFS viene con varios sistemas de archivos potentes. Cada uno de estos encaja con la nueva interfaz de HackpadFS y el poderoso golpe de io/fs.FS:

La combinación de algunos de estos puede crear programas verdaderamente innovadores sin tener que codificar un solo sistema de almacenamiento.

Como ejemplo de la vida real, Hackpad ahora usa la mayoría de estos para construir el IDE de Go en el navegador. Vea el código fuente en GitHub.

¿Buscas inspiración para crear tu propio FS? Aquí hay algunas ideas:

Go 1.16 presenta el nuevo paquete io/fs, que presenta una interfaz estándar para implementar sistemas de archivos de solo lectura. También demuestra HTTP desde cualquier sistema de archivos compatible a través de net/http.FS. El proyecto HackpadFS se inspiró en este enfoque para crear una interfaz común para todos los programas Go. La inspiración inicial también provino de spf13/afero y go-git/go-billy, aunque HackpadFS adopta un enfoque diferente, proporcionando una interfaz modular para sistemas de archivos personalizados y agrupando un conjunto de pruebas rigurosas para una coherencia estricta.

Las interfaces conocidas ayudan a los desarrolladores a crear combinaciones creativas, pero lo único que definen es cómo interactúan los diferentes sistemas. HackpadFS permite a los desarrolladores compartir muchas interfaces pequeñas y componibles que imitan a Go y sus paquetes. Para implementar un FS personalizado, solo necesita escribir un código mínimo. osio/fs

Por ejemplo, para crear un nuevo Lstat() de foo.FS que solo agregue, podemos escribir una estructura FS completa con solo 2 métodos:

Manejo de tipos de interfaz Puede que sea complicado, por lo que HackpadFS también incluye funciones auxiliares para simplificar el código. Ahora cualquiera puede usar foo.FShelpershackpadfs.Lstat(fooFS, "bar") para evitar la verificación de tipos en hackpadfs.FS en busca de genéricos. Si resulta que FS no admite la interfaz correspondiente o una interfaz compatible, se devuelve un error "no implementado".

Entonces, ¿qué incluye HackpadFS que Go no incluye? Aquí hay un desglose rápido de todas las interfaces antiguas y nuevas, y cómo las ampliamos.

Las interfaces integradas de Go incluyen FS, File, FileInfo y DirEntry, por otro lado, define interfaces equivalentes para compatibilidad y luego define 27 más:

Todas. Las interfaces se pueden utilizar para componer su propio FS con cualquier funcionalidad que necesite.

Go también implementa varias funciones auxiliares para facilitar el manejo de FS. HackpadFS implementa la mayoría de los mismos asistentes y luego 23 más:

Una fuente común de problemas para nosotros es el manejo de errores. Idealmente podríamos usar errores.Is() o errores.As() para detectar ciertos tipos de errores, pero los valores que debemos verificar son muy inconsistentes. A veces podemos buscar errores de biblioteca estándar como fs.ErrExist., pero a veces nos vemos obligados a incorporar el paquete syscall para detectar correctamente errores como "no es un directorio".

HackpadFS resuelve este problema al incluir un conjunto unificado de errores que se comportan de manera correcta y consistente:

Por último, pero no menos importante: si el sistema de archivos no funciona, entonces simplemente está mal. Para garantizar una coherencia estricta, HackpadFS proporciona un conjunto de pruebas compartido, fstest, para comprobar que cada sistema de archivos se comporta igual que el paquete os.

Está diseñado para ser fácil de usar en sistemas de archivos personalizados y solo ejecutará pruebas para una interfaz específica en el sistema de archivos que las implementa. Por ejemplo, probemos foo.FS:

Tanto fstest.FS() como fstest.File() anteriores inician una gran cantidad de subpruebas. Cada subprueba llama a TestFS() para crear una nueva instancia de foo.FS y luego las ejecuta en paralelo. Dado que foo.FS solo implementa FS y LstatFS, solo se ejecutarán esas pruebas; se omitirán todas las demás pruebas. Lo mismo ocurre con los archivos: si el archivo devuelto por Open() solo admite operaciones de lectura, solo se ejecuta la prueba de lectura de archivos.

El conjunto de pruebas es riguroso para garantizar un cumplimiento estricto y coherencia con el comportamiento del paquete del sistema operativo. No hay nada peor que un sistema de archivos que no lo parece. Hoy, fstest ejecutó 90 pruebas en el sistema de archivos y 50 pruebas en el archivo, para un total de 556 afirmaciones. Está integrado en las pruebas de CI para los 6 sistemas de archivos integrados.

Creemos que compartir una interfaz común y un conjunto de pruebas rigurosos ayudará a crear un ecosistema de sistema de archivos sólido para la comunidad Go. La componibilidad de la interfaz HackpadFS y su sistema de archivos integrado puede empoderar a todos a la hora de escribir su próxima aplicación.

¡Esperamos que pruebes HackpadFS! Fue muy divertido armar esto y nos encantaría saber si tienes algún comentario.