Programación

Packager + Composer = repositorios privados – Parte 2

0

PHP Composer Packager

Siguiendo con la serie de posts referentes a packager. En esta segunda parte vamos a integrar packager y composer para poder crear un repositorio que tenga nuestros propios paquetes, pero además que contengan las dependencias de estos y otros paquetes que utilizamos en nuestros proyectos.

Recordamos que tenemos un repositorio con la siguiente estructura

.
├── packager.json
├── packages
│   └── packager-1.0.0.zip
└── packages.json

Ahora bien, supongamos que nuestros proyectos tienen dependencia con los siguientes componentes de symfony

  • symfony/console 2.1
  • symfony/finder 2.1
  • symfony/process 2.1
  • symfony/yaml 2.1
  • symfony/filesystem 2.1

Lo que vamos a necesitar ahora es crear un file llamado “composer.json” al nivel de “packages.json” donde declararemos nuestras dependencias y configuraremos a composer para que guarde los files que baja en el directorio donde nosotros alojamos nuestros paquetes (cache-files-dir=./packages)

{
    "name": "rgnu.com.ar/repository",
    "description": "Download repository dependencies",
    "type": "repository",
    "license": "GPL-3.0",
    "version": "0.1.1",
    "keywords": [ "repository" ],

    "require": {
        "symfony/console": "2.1.*@stable",
        "symfony/finder": "2.1.*@stable",
        "symfony/process": "2.1.*@stable",
        "symfony/filesystem": "2.1.*@stable",
        "symfony/yaml": "2.1.*@stable"
    },

    "config": {
        "cache-files-dir": "./packages"
    }
}

Una ves realizado esto ejecutamos un composer update, para que este baje las dependencias

$ ../composer.phar update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing symfony/console (v2.1.8)
    Downloading: 100%         

  - Installing symfony/finder (v2.1.8)
    Downloading: 100%         

  - Installing symfony/process (v2.1.8)
    Downloading: 100%         

  - Installing symfony/filesystem (v2.1.8)
    Downloading: 100%         

  - Installing symfony/yaml (v2.1.8)
    Downloading: 100%         

Writing lock file
Generating autoload files

Una vez realizado el update, podemos borrar tanto el directorio vendor que se creo, como el file composer.lock

$ rm -rf vendor composer.lock

Ahora nuestro repositorio debería tener el siguiente contenido

.
├── composer.json
├── packager.json
├── packages
│   ├── packager-1.0.0.zip
│   └── symfony
│       ├── console
│       │   └── 2.1.8.0-v2.1.8.zip
│       ├── filesystem
│       │   └── 2.1.8.0-v2.1.8.zip
│       ├── finder
│       │   └── 2.1.8.0-v2.1.8.zip
│       ├── process
│       │   └── 2.1.8.0-v2.1.8.zip
│       └── yaml
│           └── 2.1.8.0-v2.1.8.zip
└── packages.json

Ahora lo único que nos queda es volver a realizar el build del repositorio para que incluya los paquetes que composer acaba de bajar

$ ../packager.phar build:repository
Loading Config ./packager.json
Process Repository ./
Add package rgnu.com.ar/packager (1.0.0)
Add package symfony/yaml (v2.1.8)
Add package symfony/console (v2.1.8)
Add package symfony/filesystem (v2.1.8)
Add package symfony/process (v2.1.8)
Add package symfony/finder (v2.1.8)

En la próxima entrega veremos como automatizar todo el proceso con Jenkins, de esta forma solo nos queda mantener el file “composer.json” con las dependencias y agregar nuestros paquetes al repositorio.

Packager + Composer = repositorios privados

1


Después de casi dos años de no postear nada, voy a tratar de armar una serie de posts relacionados con packager, una herramienta que se creó con el objetivo de mitigar algunas limitaciones y aspectos negativos del uso de composer y el repositorio que este usa por defecto packagist.org.

Hay dos aspectos que tratamos de solucionar con esta herramienta, el primero es poder generar un repositorio para composer que pudiera contener paquetes desarrollados internamente en la empresa, y el segundo es el problema de performance que actualmente tiene composer al realizar operaciones de update, install, search, etc, teniendo habilitado su repositorio por defecto. Este último lo logramos resolver al crear un repositorios que solo tiene aquellos paquetes que nos interesan, de esta forma reducimos considerablemente el tamaño del mismo.

Basta de tanto parloteo y pasemos a la acción. (más…)

space-tweet: Buenos tweets vs. Malos tweets en Node, Socket.IO, MooTools

0

Reportado en el blog de Twitter, Jacob Thornton a creado una demostración divertida sobre el sentimiento de los tweet con el clásico Space Invaders.

Jacob buscaba aprender más sobre Node y desarrollo este proyecto utilizando Node.js, Socket.IO, MooTools, y el API de streaming de Twitter.

Node.js – NVM (Node Version Manager)

1

Después de algunos post que tenían como objetivo llamar la atención de Google, volvemos a los temas interesantes. Dando vueltas por algunos sitios sobre Node.js me encuentro con esta utilidad NVM (Node Version Manager) que me resulto muy práctica a la hora de compilar e instalar diferentes versiones de Node.js

Instalación

Para instalarlo debemos estar seguro que disponemos de un compilador de c++ en nuestro sistema. Para OSX, XCode debería funcionar, para Ubuntu, el paquete build-essential es suficiente. También necesitaremos git si vamos a realizar un seguimiento del HEAD del proyecto.

$ git clone git://github.com/creationix/nvm.git ~/.nvm

Luego agregamos las siguientes lineas en nuestro profile de bash:

$ NVM_DIR=$HOME/.nvm
$ . $NVM_DIR/nvm.sh
$ nvm use

La primera linea carga la función nvm en nuestro shell, dejandola disponible como un comando. La segunda linea configura nuestra versión por defecto de node a la última release.

Uso

Para bajar, compilar, instalar y usar la release v0.1.94 release de node, debemos hacer los siguiente:

$ nvm install v0.1.94
$ nvm use v0.1.94

Si deseamos realizar un seguimiento del HEAD, utilizamos el comando clone:

$ nvm clone
$ nvm use HEAD

Cuando deseamos realizar una actualización del código desde el repositorio de node:

$ nvm update

Para ver las diferentes versiones de node que tenemos instaladas vamos a utilizar el comando list:

$ nvm list

Con estos sencillos pasos, estaremos en unos minutos experimentando con está nueva plataforma de desarrollo.

Node.js – Express vs Sinatra Benchmarks

2

Siguiendo con una serie de post referidos a Node.js, vamos a ver a continuación una serie frameworks para Node.js y su performance respecto a sus contrapartes para Ruby.

Comenzamos realizando un benchmark para Express, con resultados realmente sorprendentes! Los números indicados deben tomarse a la ligera, sin embargo, coinciden en afirmar que Express es bastante rápido.

Si estás interesado en realizar un benchmark de tus propias aplicaciones web puedes leer el artículo ApacheBench Gnuplot Graphing Benchmarks.

Todos los benchmark que verás a continuación fueron realizado con ApacheBench, una concurrencia de 50 y realizando 2000 requests. Tené en cuenta que se utilizó Thin para servir Sinatra requests.

Express vs Sinatra

Para los que no conocen Express, es un NodeJS framework inspirado en Sinatra para Ruby. Debajo pueden encontrar los resultados de un benchmark para un típico “Hello World” response, que incluye NodeJS benchmarks sin el overhead de las características provistas por Express:

Express vs Sinatra Benchmark

Express vs Sinatra
(más…)

Node.js – Server-Side JavaScript

5

Si, ya no solamente para los navegadores web. Aunque existan varias implementaciones de javascript, entre ellas Rhino, Flusspferd, Narwhal (el equivalente de JRuby, IronRuby, MRI, etc) la que está tomando mayor tracción es Node.js.

Node.js es un framework en javascript para el desarrollo de aplicaciones web en el lado del servidor. A partir de todas las implementaciones mencionadas, en enero del 2009 Kevin Dangoor se creo el proyecto de CommonJS, con el fin de crear una especificación que cada implementación pueda cumplir y así tener un API I/O en común.

Node.js es un tanto diferente de otras soluciones, porque está orientado al evento en lugar de ser basado en threads. Web servers como Apache están diseñados en base al modelos de thread, porque utilizan un thread/process para cada request entrante. Mientras esto funciona correctamente para muchas aplicaciones, el módelo de threads no escala muy bien con demasiadas conexiones, como las que se necesitan para servir aplicaciones de tiempo real como Friendfeed o Google Wave.

Node.js, usa un modelo de event loop en lugar de threads, de esta forma puede escalar para manejar ciento de miles de conexiones concurrentes. Node.js toma ventaja del hecho de que los servidores pasan la mayoría del tiempo esperando por operaciones de I/O, como leer un file desde el disco, acceder a servicios web externos o esperar para que el upload de un file termine, porque estas operaciones son mucho más lentas que las realizadas en memoria. Todas las operaciones de I/O en Node.js son asincrónicas, de esta forma el server puede continuar procesando request entrantes mientras espera que las operaciones de I/O finalicen. JavaScript esta muy bien preparado para la programación orientada a eventos, porque tiene funciones anónimas y closures que permiten definir callbacks inline, además que los desarrolladores en JavaScript ya conocen como programar de esta forma. Este modelo event-based hace de Node.js muy rápido, y hace que escalar aplicaciones de tiempo real sea muy sencillo.

Paso 1. Instalación
Node.js corre en sistemas tipo Unix, como Mac OS X, Linux, y FreeBSD. Desafortunadamente o no ;) , Windows no está soportado. Vas a necesitar utilizar la terminal para instalar y correr Node.js.

Abre una terminal y corre los siguientes comandos.

$ wget http://github.com/ry/node/tarball/v0.1.99
$ tar -zxvf ry-node-v0.1.99-0-ga620b72.tar.gzls
$ cd ry-node-87230e6
$ ./configure
$ make

(más…)

Ejecutando procesos en paralelo con Javascript

0

El sistema usado en el ejemplo que croczilla.com publica, está desarrollado usando Stratified Javascript (SJS), una implemenetación de Javascript con Javascript O.o. Se trata de una librería multinavegador que nos permite añadir concurrencia a Javascript fácilmente.
La clave está en el uso de tags <script/> de un tipo diferente al que conocemos como text/javascript, usando uno propio se encarga de evaluar el código contenido en él añadiendo una serie de funcionalidades como hold(),resume(), suspend() y la posibilidad de usar concurrencia en Javascript.

Ejemplo

<script type="text/javascript" src="sjs-loader.js"></script>
<script type="text/sjs">
….
function animate(elemname, duration_ms, step_ms) {
 var elem = document.getElementById(elemname);
 var start_time = new Date();
 var x = 0;
 do {
 elem.style.left = x;
 x = (x + 10) % 200;
 hold(step_ms); // Parando la ejecución
 } while (duration_ms > new Date() - start_time);
 }

 function par(a, b) {
 alert("all done");
 }
 // Procesos paralelos
 par(animate("animated_element_1", 10000, 100),
 animate("animated_element_2", 7000, 80));
…
</script>

Como podemos ver, en esta porción de código sacada de una demo de crockzilla.com, usamos hold() para detender la ejecución y usamos el paso de parámetros para comenzar la concurrencia de procesos.
Con los Web Workers a la vuelta de la esquina, estas técnicas nos puedes empezar a mostrar el camino a seguir en unos meses (años). Por el momento, recomendaría usarla con precaución ya que no debemos olvidar que la librería basa su funcionamiento en la evaluación del código, con el coste que esta operación conlleva.

Remote Tail sobre HTTP con Shell Script

1

Surgió un problemática en el trabajo, debíamos debuguear lo que estaba sucediendo en unos Solr que se encontraban en el datacenter y la única via de acceso a los logs era por medio de un webserver.

Seguramente alguien desarrollo alguna herramienta para hacer los mismo que hacemos con nuestro querido tail, pero con files que se encontraban accesible via HTTP. Pero lamentablemente o no, yo no encontre ninguna, y lo primero que se me vino a la mente es el resume, que tienen algunas utilidades de download.

Así que hechando mano a algunas herramientas disponible en la mayoría de los UNIX (bash, curl, awk, wc, cat), y después de un rato de darle vuelta salió este engendro, que si bien no tiene mucho diseño, ni patrones, ni nada por el estilo, increiblemente funciona :) . Por si alguno tiene la misma problemática acá les dejo esta pequeña porción de código, espero les sirva

URL='http://example.com/access.log'; \
SIZE=$(curl -I "$URL" 2> /dev/null | awk '/Content-Length:/ {printf("%d", $2)}'); \
while [ 1 ]; do \
curl -r$SIZE- "$URL" > /dev/null > out; cat out; \
LEN=$(cat out | wc -c); \
SIZE=$(expr $SIZE + $LEN ); \
sleep 1; \
done

La salida se puede combinar con otro comando (siguiendo la filosofía UNIX)

URL='http://example.com/access.log'; \
SIZE=$(curl -I "$URL" 2> /dev/null | awk '/Content-Length:/ {printf("%d", $2)}'); \
while [ 1 ]; do \
curl -r$SIZE- "$URL" 2> /dev/null > out; \
cat out; \
LEN=$(cat out | wc -c); \
SIZE=$(expr $SIZE + $LEN ); \
sleep 1; \
done | grep foo

Apache CouchDB: una base de datos NoSQL (Relax)

1

Apache CouchDB

CouchDB, oficalmente Apache CouchDB, es una base de datos orientada a documentos (document-oriented database), también conocido como ‘NoSQL’, que puede ser consultada e indexada usando JavaScript como función MapReduce.

CouchDB ofrece una API (Application Programming Interface) RESTful (Representational State Transfer) en JSON que puede ser accedida vía peticiones HTTP. Hay muchas librerías para casi cualquier lenguaje de programación que facilitan el acceso.

CouchDB está escrito en Erlang, un lenguaje de programación funcional robusto ideal para construir sistemas distribuidos simultáneos, lo que permite un diseño flexible y fácilmente escalable y extensible.

Base de datos documental sin schema

Estamos acostumbrados a que cuando hablamos de base de datos pensemos en el modelo relacional (columna, filas, tablas, relaciones…)  En cambio CouchDB nos ofrece guardar nuestros datos de otra forma. En pocas palabras, para CouchDB solo hay documentos. Todo lo que almacenamos es un documento sin schema, lo cual nos permite guardar juntos documentos con distintos campos dentro de la misma BD.

Estos documentos se almacenan en JSON, un formato ligero, sencillo y cómodo de usar desde cualquier lenguaje. Vamos a ver un típico documento de CouchDB:

{
    "_id" : "234a41170621c326ec63382f846d5764",
    "_rev" : "1-480277b989ff06c4fa87dfd0366677b6",
    "tipo" : "articulo",
    "titulo" : "Esto es una prueba",
    "cuerpo" : "Soy el contenido de un artículo de prueba",
    "tags" : ["cine", "comedia"]
}

El _id sirve para que CouchDB lo distinga de otros documentos y a nosotros nos vale para poder recuperarlo posteriormente. Es un string que puede contener lo que queramos aunque si no ponemos nada CouchDB generará un UUID. ¿Y por que no genera los ids con un autoincremental? Bueno, el uso del UUID nos permite tener un id único UNIVERSALMENTE, lo cual nos será muy útil cuando entremos en el tema de la replicación, pero no adelantemos acontecimientos…

El campo _rev también es especial y sirve para que CouchDB controle la versión del documento. Cada vez que guardamos un cambio en el documento cambia el número de revisión (se incrementa el 1 de antes del – y el resto del número cambia). Esto es útil porque cada vez que intentamos guardar un documento pasamos el numero de la versión que vamos a modificar, de forma que si CouchDB ve que estamos guardando un cambio sobre una revisión antigua da error y no permite continuar.

Después, el resto de campos  podemos poner lo que queramos, siempre que usemos expresiones JSON válidas, como en el ejemplo donde tenemos el atributo tags que es un array de strings. Podría ser un diccionario ({“clave1″: “valor1″, “clave2″:”valor2″}),un número (2), etc…

La parte buena de estar trabajando sin schema es que este sistema se adapta a los cambios en la estructura de los documentos que es necesario almacenar. De esta forma nos podemos despreocupar de lo que vamos metiendo en la base de datos, ya nos preocuparemos cuando tengamos que recuperarlos.

Consultable al estilo MapReduce

CouchDB no nos ofrece un lenguaje tipo SQL para realizar consultas sino que nos ofrece un sistema basado en MapReduce para poder obtener los datos que queramos. ¿Y como funciona esto?  Pues es mas sencillo de lo que parece, se compone de una parte Map una parte Reduce.

Map: Es una función que se ejecuta para cada documento. Esta función recibe como parámetro el propio documento y puede devolver pares de clave-valor. Un función puede devolver 0, 1 ó varios de estos pares para un único documento de entrada. A primera vista esto puede parece muy ineficiente, pero la función sólo se ejecuta una vez para cada documento y va almacenando los resultados en un índice que relaciona claves y valores de forma que en posteriores consultas se ataque sobre este índice. Por supuesto, si alguno de los documentos de nuestra BD se modifica, se vuelve a rehacer el índice (pero sólo para los documentos modificados)

Un ejemplo rápido:

function(doc) {
  for (var i in doc.tags)
   emit(doc.tags[i], doc);
}

Como podemos ver las funciones Map (y las Reduce) se definen en Javascript. CouchDB ofrece una arquitectura pluggable mediante la cual podemos crear estas en nuestro lenguaje favorito (Python, Ruby…).

Esta función devuelve como clave cada uno de los tags y como valor el propio documento. De esta forma ejecutada sobre nuestro doc de ejemplo daría 2 filas: una para “cine”  y otra para “comedia” ambas teniendo como valor el propio documento.

Después sobre este conjunto de resultados podemos  filtrar por clave o bien por un par de claves inicio y fin. De esta forma si queremos sabe todos los artículos que son de cine filtraríamos aquellos que tienen la clave “cine”. Es fácil, ¿no?

Lo bueno es que las claves pueden ser cualquier tipo de datos soportado por JSON como arrays, números, diccionarios… lo cual puede ser útil para realizar consultas más avanzadas.

Reduce: A grandes rasgos esta agrupa los resultados del Map para obtener un número. De esta forma si la parte Map anterior fuera asi:

function(doc) {
  for (var i in doc.tags)
    emit(doc.tags[i], 1);
}

Podemos definir una funcion reduce tal que asi:

function(keys, values)
{
  return sum(values);
}

La función Reduce recibe como entrada todas las claves y todos los valores. Con la funcion sum, proporcionada por CouchDB, vamos acumulando los 1 que devuelve la función map de forma que como resultado de esta obtenemos varias filas con cada uno de los tags como clave y el número de documentos que tienen este tag como valor.

En la nomenclatura de CouchDB un par de funciones MapReduce se llama view (no siendo obligatorio definir la parte reduce).

Accesible por REST

REST nos permite acceder a nuestro datos de una forma muy sencilla a través de URLs. Por ejemplo para recuperar nuestro documento con id  6e1295ed6c29495e54cc05947f18c8af de nuestra BD albums accederíamos a esta URL que nos devuelve el documento JSON correspondiente:

http://localhost:5984/albums/6e1295ed6c29495e54cc05947f18c8af

De forma similar si queremos acceder a una view como la que comentábamos cuando explicábamos el Map y recuperar algún resultado iremos a la URL:

http://localhost:5984/blog/_design/doc/_view/tag?key="cine"

Esta URL quiere decir que estamos accediendo a la BD llama blog, para recuperar un design document (donde se guardan las views dentro de la BD) llamado doc y dentro de este a la view llamada tag. Después como comentábamos antes, dentro de la view queremos recuperar el resultado identificado por la clave cine (es interesante ver como hay que pasarla entre ” ” ya que la clave es un string, uno de los tipos válidos de JSON).

En esta URL obtendríamos un resultado similar a este:

{"total_rows":4,"offset":0,"rows":[
 {
   "id":"9280b03239ca11af9cfedf66b021ae88",
   "key":"cine",
   "value":{"_id":"9280b03239ca11af9cfedf66b021ae88",
                "_rev":"1-0289d70fe05850345fd4e9118934a99b",
                "tags":["cine","comedia"]}
 },
{
   "id":"a92d03ff82289c259c9012f5bfeb639c",
   "key":"cine",
   "value":{"_id":"a92d03ff82289c259c9012f5bfeb639c",
                "_rev":"2-97377eef95764a4dbf107d8142187f53",
                "tags":["cine","drama"]}}
]}

Como podemos ver en key y value tenemos los resultado esperados: el tag y el documento que lo contiene. Aparte CouchDB incluye el id del documento que ha dado lugar a ese resultado (el que entra como parámetro en la función Map). Además se devuelve el numero total de filas devueltas y el offset del resultado.

En vez del parámetro key se le puede pasar a nuestra vista un par de parámetros startkey y endkey para obtener un rango de los resultados que nos interese (p.ej. en una view que devolviera como clave un string representando una fecha).

Replicación integrada

Una funcionalidad relativamente exótica que nos permite que nuestra BD de datos sincronice sus datos de una forma muy sencilla (una simple llama REST la activa) con otra BD remota o local. De este modo podemos tener de una forma sencillísima una o mas réplicas de nuestra BD para implementar arquitecturas de alta disponibilidad o de balanceo de carga.

Si os acordáis de cuando comentábamos  que CouchDB usaba por defecto UUIDs como identificadores de los documentos veréis que al tener varias BD de datos intercambiándose filas esto es indispensable. Pensad que pasaría si tuviéramos 2 o más bases de datos cada una con su autoincremental como id y empezaran a pasarse datos entre ellas ;)

Futon Apache CouchDB

Futon Apache CouchDB

De forma similar, el atributo _rev anteriormente comentado nos permite que CouchDB detecte casos en los que un mismo documento ha sido modificado en varias bases de datos a la vez (cada documento tendria un _rev diferente) .

Si os ha parecido interesante este post podéis probar a seguir la introducción práctica ofrecida en el libro gratuito de CouchDB aquí.

Symfony Components – Librerias PHP

0

La gente detrás de Symfony, uno de los Frameworks más usados por la comunidad PHP ha publicado una serie de librerias independientes, que prometen ayudar con el proceso de desarrollo de aplicaciones Web, en su web reza la siguiente frase:

The Symfony Components are standalone and reusable PHP classes. With no pre-requisite, except for PHP, you can install them today, and start using them right away. Currently, there are three components available at the moment.

Los componentes publicados hasta el momento son:

YAML – Una librería que habla YAML
Symfony YAML es una libreria PHP que convierte cadenas YAML a arreglos PHP y viceversa.

Event Dispatcher – Facilitando la comunicación entre clases
Symfony Event Dispatcher es una librería que provee de una implementación ligera del patrón de diseño Observer.

Dependency Injection – Reinventando el manejo de clases
Symfony Dependency Injection es una librería que provee un robusto contenedor de inyección de dependencias (Dependency Injection).

Go to Top