Data: faites appel à un plombier

Équipe DATA

  • Géomaticiens
  • Experts PostgreSQL
  • Développeurs

Équipe COPS

Luigi

Très peu de fonctionnalités

N'évolue plus beaucoup

Pas de scalabilité automagique

Tout est chaîné statiquement

Tout ou rien

Va consommer (vraiment) beaucoup d'espace disque

Impossible de lancer 2 fois le même traitement

Une fois le traitement terminé, le worker s'éteint

Pas fait pour du temps réel

Pas fait pour avoir des worflows de plusieurs millions de tâches

En gros, ne tiens pas la comparaison avec Airflow

Voilà, voilà ...

L'inspiration : GNU Make

2 notions à connaître

ConstruireCarte(realtor_id=2248)

Workflow

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : découverte

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : découverte

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : découverte

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : découverte

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : découverte

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : exécution

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : exécution

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : exécution

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Workflow : reprise

ConstruireCarte(realtor_id=2248)

GeoJSONSilver(realtor_id=2248)

GeoJSONGold(realtor_id=2248)

ClassementAgence(address_id=1)

CollectData(realtor_id=2248)

ClassementAgence(address_id=2)

ClassementAgence(address_id=3)

Task

import luigi


class MyTask(luigi.Task):
    param = luigi.Parameter(default=42)
    
    def requires(self):
    	return SomeOtherTask(self.param)
        
    def run(self):
    	with self.output().open("w") as output:
            output.write("Hello, world")
        
    def output(self):
    	return luigi.LocalTarget("/tmp/foo/bar-%s.txt" % self.params)

Target

import contextlib

import luigi



class MyTarget(luigi.Target):

    def exists(self):
        """ Return true if data already exists """
     
    @contextlib.contextmanager 
    def open(self):
         """ Not required but recommanded """

Execution

luigi --module CarteVisibilite ConstruireCarte --realtor_id 2248 [--local-scheduler]
import luigi

from carte_visibilite import ConstruireCarte


luigi.build([ConstruireCarte(realtor_id=2248)], workers=10)

Patterns plutôt que fonctionnalités

import itertools


class DummyTarget(luigi.Target):

    def __init__(self):
        self.result_gen = itertools.chain(
            (False, ), itertools.repeat(True)
        )

    def exists(self):
        return next(self.result_gen)

Pattern COMMANDE

Quelques outils

Cas d'usage

Production incrémentale

Équipe de développeurs Python

Livrable == base

Ensemble cohérent de données

Yoshi

Synchro de base de données pour une mailing list

Assets generator

Carte de visibilité

Applaudissez-moi !

Maintenant !!

Data: faites appel à un plombier

By Romain Commandé

Data: faites appel à un plombier

  • 735