Charlas de GNOME Hispano


CouchDB


Bienvenidos a la Charla IRC del Mes de Octubre

Hoy el tema sera CouchDB

y quien mejor para hablar del tema que Rodrigo Moya

aqui algunos datos sobre el  http://es.gnome.org/RodrigoMoya

no se olviden que cualquier pregunta durante la charla, me la envian y yo en el momento adecuado la planteare
 

bueno sin mas preambulo, con ustedes Rodrigo

hola! :)

en cuanto a las preguntas, si no le importa a neosergio, yo no tengo problema en que me interrumpais cuando queráis hacer una

bueno, pues primero, vamos a ver qué es CouchDB

perfecto

http://couchdb.apache.org/

couchdb es un proyecto Apache, lo cual quiere decir, no que necesite de Apache para funcionar, sino que está apoyado por la fundación apache
es una BBDD orientada a documentos, en formato JSON

aunque se llama BBDD, es algo distinta de lo que todos conocemos como BBDD, o sea las relacionales
en un punto muy importante, que es que una BBDD couchdb puede tener registros con distintos campos
es decir, está libre de todo esquema

por ejemplo, yo puedo tener una bbdd con un documento -> { "name": "rodrigo", "hobbies": "couchdb" }
 y otro -> { "descripcion": "hola", "date": "23-01-1985" }
todo ello, en la misma BBDD

por cierto, si estáis en ubuntu y queréis seguir lo que haga -> apt-get install couchdb
en otras distros no sé si está empaquetado

couchdb, de cara al exterior, es un servidor web (sin apache) que ofrece tanto un interfaz web
como un API REST, para que las aplicaciones puedan acceder a la BBDD

si instalais couchdb en ubuntu, podéis arrancarlo con  -> sudo /etc/init.d/couchdb start
eso arranca una instancia de couchdb para todo el sistema, accesible por todos los usuarios del sistema, en http://localhost:5984/

vamos a ver primero el interfaz web
http://localhost:5984/_utils/ permite acceder a un interfaz HTML para gestionar las BBDD y la configuración

no necesita mucha explicación, pero por encima:

1. puedes tener todas las BBDDs que quieras
2. cada BBDD se compone de documentos JSON

como decía antes, los documentos pueden tener la estructura que querais
pero hay un tipo especial de documentos, que os voy a explicar por encima, de momento
son las vistas

son documentos que contienen mini-scripts en javascript que permiten hacer consultas a la BBDD

lo bueno de estas vistas es que, una vez creadas, se cachean sus resultados, y así, el acceso a los documentos es mucho más rápido
que si accedemos a todos los documentos uno por uno

alguna pregunta hasta ahora?
no? ok

todo claro al parecer

bueno, pues pasamos a la 2ª, y más interesante, funcionalidad de couchdb
que es la sincronización

esto funciona de una manera muy sencilla
tú tienes una instancia de couchdb corriendo en tu máquina (en local normalmente)
y puedes decirle que se sincronice con otra u otras instancias de couchdb en máquinas remotas

así, por ejemplo, una de las cosas en las que estoy trabajando, es el almacenamiento de contactos de evolution en una instancia por usuario             (luego comento más de esto) que corre en local
que se sincroniza con el servidor de Ubuntu One (https://one.ubuntu.com)

qué permite esto? pues sencillo, replicar tus datos en varios sitios
y sincronizar los cambios entre las distintas instancias de couchdb

así, por ejemplo, yo puedo almacenar mis contactos en local, luego irme a un cibercafé, añadir o editar un contacto a través de un interfaz web
y luego, por arte de magia, tener mi contacto automáticamente en evolution cuando vuelvo a mi PC

couchdb está preparado para lidiar con conflictos, y para sincronizar los datos entre BBDD sin ningún problema
cada documento tiene como un pequeño control de revisiones
que hace que couchdb sepa sin problemas cuáles han sido los cambios

es importante destacar que la sincronización es en 2 (o más sentidos)
vamos, que puedo hacer cambios en todas las BBDD por separado, y todos esos cambios se sincronizan/replican en todas las BBDD

por defecto, como habéis visto, couchdb arranca una instancia por ssitema, sin autenticación de ningún tipo
lo cual no es útil es sistemas multiusuario

pregunta

donde no quieres que tu jefe vea tus contactos con el mundo del porno, por ejemplo :)
neosergio: si, dime

en cuanto al consumo de recursos, como capacidad de memoria y procesamiento, que tan eficiente es CouchDB en estas sincronizaciones?

no tengo datos científicos para enseñarte, pero con mis pruebas, la velocidad de respuesta es prácticamente la misma que acceder a ficheros locales, eso para instancias locales de couchdb
para la sincronización, el consumo es mínimo en memoria y procesamiento

ya os digo que incluye algoritmos que permiten saber qué cambios ha habido, sin necesidad de comparar documentos, ni nada de eso
en cuanto a la velocidad de red, depende de la red, claro :)

        :)

couchdb está escrito en erlang, que hace que mucha gente piense que es muy pesado
 pero es todo lo contrario
 erlang es un lenguaje hecho para sistemas concurrentes, como couchdb

responde esto a la pregunta?

bueno, pues sigo

si, todo claro

estaba con los sistemas multiusuario
couchdb puede arrancarse desde la línea de comandos
pasándole los argumentos adecuados, se puede hacer que arranque una instancia de couchdb por usuario
que es lo más interesante

además, es muy útil el activar la autenticación
que puede ser o bien por usuario/contraseña o bien por OAuth

todo esto se puede hacer a mano, pero para facilitar las cosas, en el equipo en el que trabajo ha desarrollado desktopcouch -> https://launchpad.net/desktopcouch
que no es más que un servicio dbus que, cuando se activa, arranca couchdb con los argumentos y configuración precisos para que sólo pueda ser accedido por el usuario que lo arranca

además, incluye todo lo necesario para replicar/sincronizar las BBDD automáticamente con ubuntu one o con cualquier otro couchdb que corra en la red en la que estás
esto último es especialmente interesante, ya que, en una conferencia, por ejemplo, puedes arrancar la herramienta de sincronización, buscar en la red otros servidores couchdb, y sincronizar la BBDD local con otra remota

con esto acabamos la parte de teoría de couchdb

así que hagan sus preguntas ahora, si teneis alguna :)

todo muy claro rodrigo :)

a los asistentes pueden participar de manera libre e interrumpir con sus preguntas en el momento que deseen

ok, o que nadie está escuchando, aparte de neosergio :)

:) son timidos

bueno, pues ahora vamos a centrarnos en cómo usar esto en las aplicaciones de GNOME

existen a día de hoy 2 APIs, una en python (python-oauth) y otra en C (couchdb-glib)
como esto es un canal de GNOME, vamos a centrarnos en couchdb-glib
ya que python-oauth es genérico, aunque, evidentemente, muy útil para aplicaciones ya escritas en python

que tanta diferencia puede haber entre ambas?

python-oauth sólo implementa el acceso al interfaz REST de couchdb
mientras que couchdb-glib hace lo mismo + varias cosas más:

* incluye GObject's con señales para recibir notificaciones de cambios
 python-oauth permite acceder a las notificaciones, que se opbtienen por medio del interfaz REST, pero hay que hacerlo a mano
es decir, hay que conocer el protocolo

* couchdb-glib incluye también objetos de alto nivel para acceder a los distintos tipos de documentos estandarizados -> http://www.freedesktop.org/wiki/Specifications/desktopcouch
por ejemplo, para contactos, se puede usar el objeto CouchDBDocumentContact
que permite acceder/modificar un documento de tipo 'contact' con un API típica de libs GTK/GNOME
además, esto permite abstraer la app de cualquier cambio que pudiera realizarse en el formato de los documentos
ya que las apps usan el API, si quieren, en vez de modificar el documento JSON  a mano

como podéis ver en http://www.freedesktop.org/wiki/Specifications/desktopcouch, hemos creado esa página para intentar estandarizar los tipos de documento más comunes

como no hay estructura fija en el formato de los documentos
se ha hecho eso para que no acabemos con documentos tipo "contact" que unos usan "first_name" y otros "FirstName"
que haría completamente inviable el compartir datos entre aplicaciones

como veis, tenemos, de momento, 3 tipos de documentos:
        * notas (para tomboy)
        * marcadores (https://launchpad.net/bindwood, una extensión de firefox que almacena todos los marcadores que creas en Firefox en tu couchdb local
        con el tiempo iremos creando más tipos de documentos, a saber, en breve, 'events' (calendario), 'tasks', etc
        y, a medio plazo, quizás configuraciones (que te permitiría grabar toda la conf de las apps en couchdb, replicarlo a un servidor, y al reinstalar/instalar tu distro en otra máquina, sincronizarla desde el servidor a la bbdd local, y así obtener toda la conf automáticamente)
        y otras cosas, que ya se irán viendo según surja la necesidad

bueno, pues vamos a ver cómo usar couchdb-glib en las apps
es un API muy sencilla

para empezar, hay que crear un objeto CouchDB:
couchdb = couchdb_new (url) -> url puede ser NULL, en cuyo caso se conecta a localhost:5984, o sea la instancia del sistema, o un URL cualquiera en el que haya una instancia de couchdb corriendo

para crear este objeto, es necesaria alguna interfaz en especial, o cual es la forma mas recomendable para crear un objeto CouchDB?

para listar las BBDD que hay -> GSList              *couchdb_list_databases (CouchDB *couchdb, GError **error);

neosergio: la interfaz es el API del objeto CouchDB
couchdb_new lo crea
estamos pensando en renombrarlo a CouchDBConnection, que quizás sea más claro

una vez que sabes el nombre de la BBDD a la que quieres acceder:
        GSList          *couchdb_list_documents (CouchDB *couchdb, const char *dbname, GError **error);
        lista los documentos
        
pero cierto, antes de listar bbdd y documentos, hay otros métodos muy útiles:
        gboolean             couchdb_create_database (CouchDB *couchdb, const char *dbname, GError **error); -> para crear BBDD
        gboolean             couchdb_delete_database (CouchDB *couchdb, const char *dbname, GError **error); -> para borrar BBDD
        
o, para activar autenticación por OAuth -> gboolean             couchdb_enable_oauth (CouchDB *couchdb,

                                                   const char *consumer_key,
                                                   const char *consumer_secret,
                                                   const char *token_key,
                                                   const char *token_secret);

en ubuntu OAuth se activa por defecto, y todos los datos para acceder se almacenan en el gnome-keyring
 así que si no se llama a la función couchdb_enable_oauth antes de cualquier otra petición, couchdb devolverá "401 unauthorized" para todas las peticiones quele hagamos

bueno, se almacena en gnome-keyring y en un fichero .ini -> ~/.config/desktop-couch/desktop-couchdb.ini

bueno, pues una vez que ya sabes a qué BBDD vas a acceder, se usa couchdb_list_documents, que devuelve una lista de todos los documentos (sus nombres y datos, como la revisión actual, su ID único, etc)

y, muy útil -> void                 couchdb_listen_for_changes (CouchDB *couchdb, const char *dbname);

esta última función activa la escucha de cambios en la BBDD que indiques
esto es muy importante, ya que si tienes configurado tu CouchDB para que sincronice con otro servidor, si no monitorizas los cambios, tu app no recibirá ninguna notificación

el objeto CouchDB incluye las señales:
                void (* database_created) (CouchDB *couchdb, const char *dbname);
                void (* database_deleted) (CouchDB *couchdb, const char *dbname);
                void (* document_created) (CouchDB *couchdb, const char *dbname, CouchDBDocument *document);
                void (* document_updated) (CouchDB *couchdb, const char *dbname, CouchDBDocument *document);
                void (* document_deleted) (CouchDB *couchdb, const char *dbname, const char *docid);

pero para realmente monitorizar los cambios en los documentos es necesaria la función couchdb_listen_for_changes
 si no la llamas, sólo recibirás notificaciones de los cambios hechos por tu app

una vez que se tiene la lista de documentos, se puede obtener cada documento con:
        
CouchDBDocument *couchdb_document_get (CouchDB *couchdb,
                                               const char *dbname,
                                               const char *docid,
                                               GError **error);

así mismo, se puede crear un documento vacío con -> CouchDBDocument *couchdb_document_new (CouchDB *couchdb);
el objeto CouchDBDocument permite manejar un documento desde tu app, de forma muy sencilla
un documento en CouchDB se compone de distintos campos, que pueden ser de estos tipos:
        * entero
        * booleano
        * cadena
        * objeto, que no es más que el equivalente a una struct en C
        * arrays

estos campos se acceden de forma muy sencilla:

        gint             couchdb_document_get_int_field (CouchDBDocument *document, const char *field);
        gboolean         couchdb_document_get_boolean_field (CouchDBDocument *document, const char *field);
        const char      *couchdb_document_get_string_field (CouchDBDocument *document, const char *field);
        gdouble          couchdb_document_get_double_field (CouchDBDocument *document, const char *field);
        CouchDBStructField *couchdb_document_get_struct_field (CouchDBDocument *document, const char *field);

los arrays no están soportados aún en couchdb-glib, más que nada porque no los he necesitado de momento
        
pero añadirlos es cuestión de minutos, así que imaginaros que ya existe esta función: :)

        GArray *couchdb_document_get_array_field (CouchDBDocument *document, const char *field);

como veis, couchdb_document_get_struct_field devuelve un objeto CouchDBStructField, que no es más que una capa para implementar una struct en JSON:

        gboolean            couchdb_struct_field_get_boolean_field (CouchDBStructField *sf, const char *field);
        gdouble             couchdb_struct_field_get_double_field (CouchDBStructField *sf, const char *field);
        gint                couchdb_struct_field_get_int_field (CouchDBStructField *sf, const char *field);
        const char         *couchdb_struct_field_get_string_field (CouchDBStructField *sf, const char *field);
        CouchDBStructField *couchdb_struct_field_get_struct_field (CouchDBStructField *sf, const char *field);

como veis con  couchdb_struct_field_get_struct_field se puede tener struct's dentro de struct's, etc, etc
todos los niveles que querais
así mismo, todas estas funciones *_get_*field tienen su correspondiente *_set_*_field

así, por ejemplo:
        CouchDBDocument *doc = couchdb_document_new ();
        couchdb_document_set_string_field (doc, "last_name", "Moya");
        couchdb_document_set_boolean_field (doc, "is_dumb", TRU);
        TRUE :)

alguna pregunta? que no quiero saturaros de información :)
aunque creo que el API es bien sencillo, no necesita mucha explicación

bueno, pues sigo, que ya estamos acabando

una vez que tenéis un objeto CouchDBDocument, almacenarlo en la BBDD es muy sencillo:

        gboolean         couchdb_document_put (CouchDBDocument *document,
                                               const char *dbname,
                                               GError **error);

esa función se usa tanto para crear nuevos documentos como para actualizar documentos ya existentes
el truco está en que, si el CouchDBDocument fue leido de la BBDD, incluye una serie de campos internos que CouchDB crea:
        * _id -> identificador único del documento
        * _rev -> revisión actual del documento

asímismo, para borrar un documento -> gboolean  couchdb_document_delete (CouchDBDocument *document, GError **error);

y bueno, para terminar, os comento un poco sobre CouchDBDocumentContact

CouchDBDocumentContact no es más que uno de los múltiples objetos de alto nivel que se van a añadir a la lib, para facilitar la gestión de documentos estandarizados (ya sabéis -> http://www.freedesktop.org/wiki/Specifications/desktopcouch)

es una capa que permite gestionar documentos de tipo "contact" -> http://www.freedesktop.org/wiki/Specifications/desktopcouch/contact

se me había olvidado hablar del campo "record_type", que es el que especifica qué tipo de documento es
 por ejemplo, para contactos -> "record_type": "http://www.freedesktop.org/wiki/Specifications/desktopcouch/contact",
y bueno, este CouchDBDocumentContact incluye un API para acceder a todos los campos definidos en http://www.freedesktop.org/wiki/Specifications/desktopcouch/contact

por ejemplo:
        const char *couchdb_document_contact_get_first_name (CouchDBDocument *document);
        void        couchdb_document_contact_set_first_name (CouchDBDocument *document, const char *first_name);
        const char *couchdb_document_contact_get_last_name (CouchDBDocument *document);
        void        couchdb_document_contact_set_last_name (CouchDBDocument *document, const char *last_name);
        ...

esto permite que no tengas que acordarte de los nombres de los campos
y que tu app sea transparente a cualquier cambio que se haga en el formato del documento

y bueno, dle API creo que no os voy a contar más, si alguien quiere saber más, que me pregunte, ahora o por email, cuando quiera

el código está en el GIT de GNOME, en el modulo couchdb-glib, y ha sido propuesto para ser incluido en GNOME 2.30/3.0
junto con evolution-couchdb

lo que si os voy a contar es un poco qué permite todo esto

el plan de dominación mundial es que, por ejemplo, yo tenga mi móvil (o celular) con todos mis contactos, me vaya de viaje, haga amigos, sincronice los contactos con mi servidor de couchdb, y luego esos contactos aparezcan todos en evolution sin tener que sincronizar a mano

esto, imaginaroslo con cualquier tipo de datos
las notas de tomboy (conboy en los nokia, tomdroid en los android), etc
además, permite que apps totalmente diferentes compartan datos
por ejemplo, akonadi, el equivalente a evolution en KDE, usa el formato http://www.freedesktop.org/wiki/Specifications/desktopcouch/contact

así que, por fin, los usuarios podrían cambiarse de app sin tener que hacer migraciones masivas de datos
incluso sólo para eso, sin sincronización ni replicación, couchdb tiene muchísimo sentido

umm una pregunta, que relacion tiene couchdb-gnome con lo que se llamaba gnome-base o gnome-db en gnome 1.x  Recuerdo que querian hacer gnome-db como una especie de estructura de datos utopica para las apps de gnome. Esto suena algo similar solo que mas en la red.

imaginad que tanto evolution como akonadi almacenan el correo, contactos, calendaro, etc en couchdb, eso permitiría cambia r de una a otra app sin problemas para los usuarios

jza: gnome-db es un API para acceder a bbd relacionales

se parece, pero no es lo mismo

couchdb es, por decirlo de alguna manera, un almacen de datos

por cierto, que se me ha olvidado comentar que los documents de couchdb pueden tener ficheros adjuntos

no todo tiene que ser JSON

lo otro que me suena muy similar es sobre google-gears de tener un banco de datos para las apps en web. 

perdón, almacen de datos no, sino almacen de documentos
jza: si, en eso si tienes razón, es algo parecido

lo que pasa es que esto, couchdb, es 100% libre
y cualquiera se puede instalar su propio servidor
cosa que no se si es posible con google-gears

alguna pregunta más?

la tercera es sobre akonadi pero es lo que estas ya explicando.

continua :)

no, ya he acabado, ahora preguntad :)

erlang no es muy complejo? Por que eso si suena a una lata aprender un nuevo leenguaje. 

erlang no es complejo, es "diferente"
así que cuesta un poco aprenderlo
pero vamos, no necesitas aprenderlo

erlang es el lenguaje en el que está implementado internamente couchdb
así que no es necesario aprenderlo para usar couchdb

y para su uso lo puedes manipular desde? JSON?

ok javascript .... ok 

si lo aprendes, nos das una charla aquí, que yo me he medio leido el libro, pero como te digo, cuesta, es un lenguaje totalmente distinto :)

jza: javascript es para escribir las vistas
para acceder al interfaz REST HTTP, cualquier lenguaje que te guste

muy bien.

las vistas son muy sencillas
por ejemplo:
        {
           "get_records_and_type": {
               "map": "function(doc) { emit(doc.record_type, doc) }"
           }
        }

o algo más complejo: function(doc) { if (doc.record_type == "http://www.freedesktop.org/wiki/Specifications/desktopcouch/contact") emit (NULL, doc); }

para devolver todos los documentos de tipo "contact"

una pregunta mas, hay algunos sitios usando couchdb, o como se puede ver una implementacion de couchdb en accion?

el caso es que creo que van a soportar vistas en más lenguajes aparte de JS, pero no sé decirte a día de hoy cómo va la cosa

jza: https://one.ubuntu.com es uno

en http://couchdb.apache.org/ hay una lista, a ver si la encuentro

http://wiki.apache.org/couchdb/CouchDB_in_the_wild

como ves, hay hasta apps de facebook que lo usan :D

gracias

excelente recurso

bueno, alguna pregunta más?

ah, por cierto, hay un libro sobre couchdb en construcción -> http://couchdb.apache.org/docs/books.html

http://books.couchdb.org/relax/

que requisitos minimo debe tener una persona para que empiece a colaborar con couchDB?

no sabia que ubuntu one estaba implementado de esa manera!!!
EGCdigital

bueno, con couchdb es complicado, ya que esa persona tiene que saber erlang, que es complicado

:)

pero para colaborar con couchdb-glib, evolution-couchdb, o en integrar couchdb-glib en apps ya existentes

cualquier persona que sepa algo de programar en GTK/GNOME, debería poder ponerse en marcha rápidamente

EGCdigital: la parte de los ficheros no usa couchdb, pero la de contactos, notas, etc, si

Con respecto al plan de dominacion mundial, ya se puede ver algun intento de aplicacion en moviles??

ah, por cierto, que Roberto Majadas ha escrito bindings de Vala para couchdb-glib, así que al que le guste Vala más que C, puede usar esos bindings

:)

neosergio: el sincronización de notas desde tomboy usa un protocolo definido por la gente de tomboy, que en breve implementarán (si no lo hacen ya) tomdroid (para android) y conboy (para los tablets nokia)

el tema de contactos estará probablemente en breve, para ubuntu one

y en cuanto reciba mi n900, pienso ponerme a integrar couchdb-glib ahí :)

genial :)

es una tecnología joven, en el sentido que hace muy poco que se ha empezado a mostrar interés en proyectos fuera de la web, sobre esta tecnología
vamos, que hay un camino muy bonito por hacer aún
 :)

pero si, poco a poco van surgiendo cosas muy interesantes
en la web couchdb es popular, incluso hasta el punto que mucha gente está reemplazando sus BBDD relacionales con couchdb
pero en el tema de escritorios y móviles, queda muchísimo, y muy interesante por hacer
así que es un proyecto muy interesante en el que embarcarse, de verdad :)

y bueno, si no hay más preguntas, lo dejamos aquí, ok?

me parece que ya no quedan preguntas

ok

el tema ha sido muy interesante
y la charla muy clara

pues muchas gracias a todos, espero que os haya gustado

muchas gracias rodrigo por tu tiempo

clap clap clap clap clap

gracias por la charla rodrigo 

aplausos por el excelente expositor

si quereis hablar conmigo, suelo estar en este canal, si no -> rodrigo@gnome-db.org
así que espero recibir parches, ideas,etc en breve :D

:D mas ideas de dominacion mundial

:D

muchas gracias rodrigo nuevamente

Eventos/CharlasIRC/CharlaOctubre2009/Log_CharlaIRCOctubre2009 (última edición 2009-11-25 03:36:24 efectuada por JuanjoAmor)