Symfony Live : Particul.es s'invite à Paris

Friday, 12 Feb 2010 by vince - symfony - no comment

logo-sf-live.png

Tout le monde attend l'évènement avec impatience, Twitter est gavé de #sflive2010 et on a tous reçu nos confirmations.

Je parle évidemment du Symfony-Live 2010 ce mardi 16.

Particul.es sera encore et toujours de la partie. Donc si ca vous chiffonne, que vous voulez geeker ou que vous tournez sur place, n'hésitez pas à venir me voir !

Je serai facile à trouver, j'aurai une veste fluo, des semelles qui clignotent et un chapeau en tête de bison.

Et si jamais j'oublie les accessoires, j'aurai peut-être aussi un badge qui dit "Vincent Agnano"...

Doctrine generate migrations or how to upgrade your database in production

Tuesday, 02 Feb 2010 by vince - symfony - 4 comments

Doctrine migration

4 months ago, you published a website on a production server. Ok, no a big deal. You work on next iterations and today you must update the website.

Some git push here, git pull there (or whatever you use). Still ok. But what about the database ? You did upgade you schema, still you cannot delete all existing datas in the production database, right ?

How should you manage that ? Check every field you changed, go to phpMyAdmin and manually build each field and table, launch functional tests to check no error appears ? Come on, let's not get silly ! You'll use Doctrine migration task !


Starting up the project

One upon a time your schema was straight and clear. You basically has a list of members with a fistname and a lastname

Schema at its first version

Member:
  columns:
    id:         { type: integer(4), primary: true, autoincrement: true }
    firstname:  string(50)
    lastname:   string(50)

Of course you had some basic fixtures :

Member:
  pointbar:
    firstname:  Stéphane
    lastname:   Langlois
  ioo:
    firstname:  Lionel
    lastname:   Chanson
  vinyll:
    firstname:  Vincent
    lastname:   Agnano

Then you did something like :

symfony doctrine:build --all --and-load

Made your modules, wrote your tests, refactored, enjoyed, had lunch and fun, pushed your site on the staging, got it tested and validated and finally run it in production ! Phew, what a journey you had.

Some time later, you reached today. And today is a great new day because you must update your website. And its database. Push all that in production. Oh, and preserving the datas from that database. Ok ok, you got the point and its issue. Let's go then !

Updating the project

Members are required to get username. A new functionality also comes up as they may have tasks. Easy...

First thing first, you update your schema as necessary :

Task:
  columns:
    id:         { type: integer(4), primary: true, autoincrement: true }
    title:      string(100)
    body:       clob
    member_id:  integer(4)
  relations:
    Member:
      class:        Member
      local:        member_id
      foreign:      id
      foreignAlias: Tasks

Member:
  columns:
    id:         { type: integer(4), primary: true, autoincrement: true }
    firstname:  string(50)
    lastname:   string(50)
    username:   string(20)

And update your fixtures :

Member:
  pointbar:
    username:   pointbar
    firstname:  Stéphane
    lastname:   Langlois
  ioo:
    username:   ioo
    firstname:  Lionel
    lastname:   Chanson
  vinyll:
    username:   vinyll
    firstname:  Vincent
    lastname:   Agnano
    
Task: 
  migrations:
    title:    Finish blog article
    body:     Will I ever make it ?
    Member:   vinyll
  mediabrowser:
    title:    Fix sfMediaBrowser tickets
    body:     "Ask some Windows to solve http://github.com/vinyll/sfMediaBrowserPlugin/issues/issue/5"
    Member:   vinyll

Update your model

Here is the point. Don't update your schema as you're used to as it would fully recreate your model.

Instead, you'll use the migration generation from difference.

Generating a migration

As of Doctrine 1.1, you can generate migrations classes automatically from schema differences and not type the whole thing. Warning : Do NOT run some "symfony doctrine:build --model" if you don't want to run through some error.

So you may safely hit this line :

symfony doctrine:generate-migrations-diff

Magic comes out and as the tasks says, it generates migration classes from the differences.

Check out /lib/migration/doctrine/ and you'll see 2 new files (2 in our example case). Those are the classes that will updagrade-enable and downgrade-enable our application without reconstructing the whole structure. The first generated file is the basic columns modification while the second is for indexes and relations (as it must be done after columns creation/deletion, database-wise).

Applying a migration

Simply run !

symfony doctrine:migrate

What happened ?

Check out your Base model classes and your database. They have been updated, just as if you had run a "doctrine:build --all" but with the awareness of versionning. We could compare it to svn or git.


Doctrine's versionning system

It actually happens in 2 places :

  • One that holds the current version : that's your database ! If you have a look at it, you'll see a table called "migration_version" that has 1 column named "version" and 1 record that holds "2" ("2" in our specific case). That "2" is as you understood the current version you are at !
  • The file system : these classes you opened earlier (/lib/migration/doctrine/*) are named by their version number.

Therefore it will be very easy to know at what version you currently are, how far your are from head version and what happens in next/previous version just reading the class files.

Update in staging/prod environment

You'll be required to migrate your prod version as well. First update your files going for a "git pull" or whatever. That brings in your migration classes. Next you just need to run your migration task :

symfony doctrine:migrate

Now you may run your tests again. All datas are preserved. You can go back for lunch and fun.

You may freely comment or tweet me.

Time machine à la mano pour un site Web

Tuesday, 19 Jan 2010 by stef - symfony - 6 comments

ds210j
En quelques semaines, le disque dur de mon pwG4 est passé en mode casserole et les pistons de ma 306 ont gaufrés leurs soupapes - #fail
J'ai regardé mon vieux serveur de backup... prise de conscience... et achat rapide d'un petit NAS[1].

Pas convaincu par la wonderful ajax webadmin de synology, j'ai préféré une solution de backup incrémental avec rsnapshot. L'occasion de poster un billet éclair.

rsnapshot


rsnapshot, basé sur rsync, permet de prendre des instantanés d'un système de fichiers à un moment T. Il créé l'illusion de multiples sauvegardes complètes mais n'occupe, en réalité, qu'une seule sauvegarde accompagnée des incréments.

Facile à mettre en place, c'est une solution plutôt souple et efficace pour garantir l'intégrité des sites Web versatiles.

Installation et configuration

Quelques scripts perl à télécharger et le tour est presque joué.
Tuning du fichier de conf. /etc/rsnapshot.conf :

On spéc. la racine du répertoire de backup :

# All snapshots will be stored under this root directory.
snapshot_root   /mnt/backup

On spéc. les snapshots, ici :
2 par jour
7 jours sur 7
1 par semaine
et les 3 derniers mois

#########################################
#           BACKUP INTERVALS            #
# Must be unique and in ascending order #
# i.e. hourly, daily, weekly, etc.      #
#########################################

interval        hourly  2
interval        daily   7
interval        weekly  4
interval        monthly 3

On en profite pour exclure les lourdos :

# The include_file and exclude_file parameters, if enabled, simply get
# passed directly to rsync. Please look up the --include-from and
# --exclude-from options in the rsync man page for more details.
#
#include_file   /path/to/include/file
exclude_file    /mnt/backup/exclude

Avec dans /mnt/backup/exclude des trucs du genre :

cache/

Pour être cohérent avec le précédent billet sur l'accès sécurisé au serveur on spéc. le port :

ssh_args        -p 10068

Enfin, le coeur, on spéc. l'adresse du distant et le lien relatif sur le local :

# EXAMPLE.COM
#backup root@example.com:/etc/  example.com/
backup  particul@88.191.38.139:/www/ particul.es/

Pour les pépins de passphrase et d'authentification par clé : La-Nuit-des-morts-vivants

Test et automatisation

Pour tester la validité du fichier de config :

.-$ rsnapshot configtest

Pour tirer à blanc :

rsnapshot -t hourly

Reste plus qu'à croner :

.-$ sudo crontab -e 

0 */12 * * * /usr/local/bin/rsnapshot hourly
50 3 * * *  /usr/local/bin/rsnapshot daily
40 2 * * 6  /usr/local/bin/rsnapshot weekly
30 1 1 * *  /usr/local/bin/rsnapshot monthly

Résultat

Nous disposons de snapshots où les sauvegardes sont stockées. Les dossiers sont créés pour les différents intervalles qui ont été définis. Après quelques mois, le dossier de backup devrait ressembler à çà :

.-$ rsnapshot du particul.es/
5.2G    /.snapshots/hourly.0/particul.es/
5.4M    /.snapshots/hourly.1/particul.es/
5.4M    /.snapshots/daily.0/particul.es/
728M    /.snapshots/daily.1/particul.es/
4.8M    /.snapshots/daily.2/particul.es/
4.8M    /.snapshots/daily.3/particul.es/
6.2M    /.snapshots/daily.4/particul.es/
4.8M    /.snapshots/daily.5/particul.es/
4.8M    /.snapshots/daily.6/particul.es/
12M     /.snapshots/weekly.0/particul.es/
5.3M    /.snapshots/weekly.1/particul.es/
5.4M    /.snapshots/weekly.2/particul.es/
4.9M    /.snapshots/weekly.3/particul.es/
4.8M    /.snapshots/monthly.0/particul.es/
120M     /.snapshots/monthly.1/particul.es/
5.3M    /.snapshots/monthly.2/particul.es/
6.0G    total

Sauvegarde SQL

Ne pas oublier de sauvegarder la BD du site, une petit ajout dans le fichier de conf :

$.- vi /etc/rsnapshot.conf

backup_script ssh particul@88.191.38.139 mysqldump -u particul --password=s|<1llz --quick --single-transaction particul | /bin/gzip >| ./mysqldump.gz

Conclusion

Quelques liens devraient suffire pour clôturer le post...

Rsnapshot est très largement inspiré de l'article de Mike Rubel
Un petit livre pour aller plus loin.

See ya !!!

Poste de développeur symfony à Nice

Tuesday, 05 Jan 2010 by ioO - symfony - no comment

L'Agence Pix recherche un développeur symfony confirmé pour démarrer dès janvier 2010 sur un projet de grosse envergure.

Votre rôle

Avec le directeur multimédia de l'agence et l'équipe technique, vous travaillerez sur les aspects suivants :

  • conseil fonctionnel auprès du client
  • conception et rédaction du cahier des charges technique
  • développement
  • maintenance et suivi

skills

  • développeur symfony confirmé (1 an minimum)
  • bonne connaissance d'un framework javascript
  • passionné par les nouvelles technologies

Le site de l'agence : http://www.agencepix.com/

Envoyez votre candidature à : recrutement(chez)agencepix(.)com