Créer un éditeur de texte plein écran avec MacRuby

Capture vidéo avec MacRuby

PeriodicTimer de EventMachine, le cron simplifié

EventMachine est une des meilleures librairies Ruby, tout en étant une des plus sous-estimées et mal connues.

J'ai donc commencé à regarder un peu dans quels cas utiliser EventMachine. La première application que j'en ai trouvé c'est tout simplement le PeriodicTimer.

Son utilisation la plus simple est le remplacement d'une cronjob.

Je m'explique : une cronjob est vraiment une très bonne chose. On peut définir très précisément l'heure à laquelle on souhaite qu'une tâche s'exécute. Celle-ci s'exécute alors à ce moment précis. Cron est vraiment un outil magnifique. Cependant, dans le cas d'une tâche récurrente qui doit être effectuée régulièrement, l'utilisation d'un cronjob peut avoir un gros inconvénient.

Cron n'a aucune gestion de queue. Ainsi on peut se retrouver très simplement avec une quantité astronomique de tâches essayant de s'exécuter en même temps. Votre « load » explose et il faut redémarrer votre serveur. Bien sûr cela n'arrive que si vous lancez une tâche plus fréquemment que son temps d'exécution.

La seule solution serait d'avoir une petite application - comme : jobq - qui gére pour vous un système de queue. Bien sûr, si le fait d'avoir une queue ne sert strictement à rien, cette solution peut être un peu overkill.

L'avantage de PeriodicTimer est que les tâches sont exécutées après un temps défini. Il n'y a aucune gestion d'heure de lancement. Il y a juste un lancement de la tâche après X secondes une fois que la précédente tâche est finie et qu'aucune autre tâche ne soit en cours d'exécution. Cela entraîne effectivement un glissement progressif de l'heure de lancement. Mais globalement, ça ne pose aucun problème. L'important est que la tâche soit exécutée régulièrement. C'est le cas, par exemple dans le cas de récupération de statistique.

Voici un exemple de code qui utilise PeriodicTimer

require 'eventmachine'
require 'timeout'
EventMachine.run {
 EventMachine::PeriodicTimer.new(10) do
   puts "#{Time.now} : I am 10"
   sleep 10
 end

 EventMachine::PeriodicTimer.new(1) do
   puts Time.now
 end
}

Voici la sortie qui est effectuée si on lance l'application pendant 50s.

$ ruby em_periodic.rb
Fri Mar 26 16:07:39 +0100 2010
Fri Mar 26 16:07:40 +0100 2010
Fri Mar 26 16:07:41 +0100 2010
Fri Mar 26 16:07:42 +0100 2010
Fri Mar 26 16:07:43 +0100 2010
Fri Mar 26 16:07:44 +0100 2010
Fri Mar 26 16:07:45 +0100 2010
Fri Mar 26 16:07:46 +0100 2010
Fri Mar 26 16:07:47 +0100 2010
Fri Mar 26 16:07:48 +0100 2010 : I am 10
Fri Mar 26 16:07:58 +0100 2010
Fri Mar 26 16:07:59 +0100 2010
Fri Mar 26 16:08:00 +0100 2010
Fri Mar 26 16:08:01 +0100 2010
Fri Mar 26 16:08:02 +0100 2010
Fri Mar 26 16:08:03 +0100 2010
Fri Mar 26 16:08:04 +0100 2010
Fri Mar 26 16:08:05 +0100 2010
Fri Mar 26 16:08:06 +0100 2010
Fri Mar 26 16:08:08 +0100 2010
Fri Mar 26 16:08:08 +0100 2010 : I am 10
Fri Mar 26 16:08:18 +0100 2010
Fri Mar 26 16:08:19 +0100 2010
Fri Mar 26 16:08:20 +0100 2010
Fri Mar 26 16:08:21 +0100 2010
Fri Mar 26 16:08:22 +0100 2010
Fri Mar 26 16:08:23 +0100 2010
Fri Mar 26 16:08:25 +0100 2010
Fri Mar 26 16:08:26 +0100 2010
Fri Mar 26 16:08:27 +0100 2010
Fri Mar 26 16:08:28 +0100 2010
Fri Mar 26 16:08:28 +0100 2010 : I am 10

On peut constater que la tâche qui doit s'exécuter toutes les secondes le fait bien. Par contre la tâche qui s'exécute au bout de 10 secondes effectue un lock sur le thread. Ainsi la tâche qui s'exécute toutes les secondes attend que le lock soit libéré. Une fois terminée, l'exécution de la tâche toutes les secondes recommence. La tache qui doit s'exécuter toutes les 10 secondes attendra, quand à elle, 10 nouvelles secondes après avoir été terminée.

C'est là une grande puissance de PeriodicTimer. On a facilement une succession de tâche qui ne se marchent jamais sur les pieds. Désormais, je n'utilise plus que

cette solution pour créer des scripts de récupération de données.

Ruby Summer of Code 2010

S’inspirant du désormais traditionnel Google Summer of Code visant à encourager la participation des étudiants au développement open source, Ruby Central, Engine Yard et la core team de Rails organisent le premier Ruby Summer of Code.

Rendez-vous sur rubysoc.org pour tous les détails, et sur @rubysoc pour l’actualité.

Le Ruby Summer sera très proche dans son organisation de l’évènement organisé par Google :
  • les étudiants obtiennent une bourse de $5000 pour travailler à temps plein sur leur projet pendant les vacances d’été ;
  • un groupe de gourous de la communauté Ruby se sont portés volontaires pour être leurs mentors ;
  • les mentors votent pour les propositions de projets faites par les étudiants, les critères objectifs étant l’utilité propre du projet, le bénéfice qu’il peut apporter à la communauté Ruby, et le passif des contributions open source de l’étudiant.

À défaut ou en plus de coder, vous pouvez participer financièrement : plus d’argent accumulé signifie plus de projets validés. Faites un don !

Core Animation avec MacRuby

Retour d’expérience sur dropbox

Cela va maintenant faire trois mois que j'ai basculé vers un compte payant dropbox (50go, 100€/an), voilà un compte rendu.

L'application permet de synchroniser les fichiers de votre dossier dropbox vers le site. L'objectif principal est donc de faire des backups et de partager des fichiers entre plusieurs machines.

Je trouve que ce service est vraiment bien fichu, mais il ne s'adresse pas forcément à tout le monde. Voilà selon moi les points forts de dropbox:

  • Synchronisation multi-poste (pratique pour partager les données mais aussi les fichiers de configuration de ses applications)
  • Supporte les liens symboliques
  • Existe sur les 3 OS majeurs et fonctionne bien sur les deux que j'ai pu tester (devine lesquels :-)).
  • La synchronisation est instantanée, un fichier créé sur A se synchronise immédiatement sur B.
  • Gestion du LAN: si la dernière version d'un fichier est disponible sur une machine A, dropbox ira la chercher sur A depuis B plutôt que depuis le site, ce qui économise de la bande passante.
  • Possibilité de retrouver un fichier j+30 après sa suppression, voire possibilité de le retrouver indéfiniment avec l'option pack-rat (40€)
  • interface web sobre et efficace
  • Votebox: tous les mois il est possible de voter pour les fonctionnalités que l'on souhaite mettre en avant.
  • Recherche en ligne performante (je vais parfois plus vite en passant par leur moteur de recherche qu'en recherchant manuellement sur ma machine)
  • Possibilité de partager des dossiers
  • Gestion des conflits
  • Prix correct

Points négatifs:

  • Il n'est pour l'instant pas possible de choisir uniquement quels dossiers synchroniser. Par exemple sur mon media center je voudrais synchroniser uniquement ma bibliothèque photo. C'est en tête des fonctionnalités demandées dans votebox et un membre de l'équipe a confirmé que ce serait implémenté en 0.8.
  • Le partage entre en compte dans le quota des deux (ou plus) personnes. D'un sens on comprend dropbox qui veut éviter les comptes basés uniquement sur des groupements de partages (x compte gratuits de 2go) mais c'est quand même pénible. Aux dernière nouvelles dropbox semblait vouloir mettre à disposition des offres de groupe pour palier ce manque.
  • Un simple renommage revient à supprimer et recréer le dossier complètement, ce qui est parfois très lourd pour un dossier contenant beaucoup de fichiers.
  • Bonne intégration à gnome mais pas kde.
  • Le syndrôme de la boîte noire: même s'il est affiché que la sécurité et la vie privée sont au cœur de la stratégie de dropbox on nest contraint de leur faire confiance de façon totalement aveugle.
  • Le support. En rapport avec le point précédent c'est très frustant quand on a un souci et qu'il faut se coltiner le support. D'une part il est en anglais uniquement, ce qui en rebutera plus d'un. D'autres part il y a le décalage horaire, donc il faut un certain temps avant d'avoir sa réponse.

Anedocte:

Peu de temps après avoir switché vers la version payante j'ai décidé de versionner ma lib photo (6go). J'ai voulu la partager avec un compte gratuit avant de me rendre compte que ça rentrait aussi dans son quota.

Du coup j'ai supprimé le partage en gardant le dossier. Et la catastrophe: le dossier n'était plus accessible par personne et les fichiers n'apparaissaient pas dans les fichiers supprimés.

Il m'a fallu exactement 1 mois, 2 personnes différentes au support et 3 tickets pour résoudre le problème.

Car l'équipe à tendance à traiter les tickets récents mais ne pas répondre aux anciens même quand ce n'est pas réglé.

Tout ceux qui ont déjà perdu des photos savent à quel point c'est stressant. Au final il s'avère que le dossier était «simplement» orphelin, il leur a suffit de le rattacher à mon compte.

Conclusion:

Malgré mes déboires c'est un service que je conseille tout de même pour sa qualité, il permet vraiment de dormir sur ses deux oreilles.

Génération d’url avec des ressources imbriquées en rails

Je suis tombé récemment sur ce qui me semble être un bug dans la génération d'url pour les nested resources, d'ailleurs je l'ai remonté;

Prenons un exemple d'une famille avec plusieurs personnes

map.resources :families, :has_many => :people

La définition des resources dans le fichier de routes permet la mise à disposition des générateurs d'urls. Par exemple:

family_people_path(1) => /families/1/people

Par contre le passage d'un id ou objet nil devrait générer une exception. Or dans une vue ou un contrôleur:

family_people_path(nil) => /families//people

Pourtant en console une exception est bien lancée:

include ActionController::UrlWriter
family_people_path(nil)
ActionController::RoutingError: family_people_url failed to generate from {:action=>"index", :family_id=>nil, :controller=>"people"}, expected: {:action=>"index", :controller=>"people"}, diff: {:family_id=>nil}

Est ce que cela signifie que les exceptions de génération d'URL sont capturées (et étouffées) à un plus haut niveau dans une application rails ?

Zlib::BufError et repository de gems down

SoapUI 3.5 (et pardon pour le crash)

Query Browser pour MongoDB