SlideShare a Scribd company logo
SaaS con Symfony2 
un caso *molto* concreto di applicazione multitenant
@ftassi 
Francesco Tassi 
@matteomoretti85 
Matteo Moretti
SaaS con Symfony2
Nuvola e i suoi 50GB
Nuvola e i suoi 50GB 
• Difficoltà di manutenzione (backup/ripristino) 
• Difficoltà di evoluzione (alter dello schema) 
• Impossibile replicare il sistema (debug)
Applicazioni multi 
tenant
Applicazioni multi 
tenant 
“Multi-tenant si riferisce ad una architettura 
software in cui una singola istanza del suddetto 
software gira su un server ed è utilizzata da più di 
una client organization (tenant)”. 
– wikipedia
Sharding
Sharding 
A database shard is a horizontal partition of data 
in a database. Each individual partition is referred 
to as a shard or database shard. Each shard is 
held on a separate database server instance, to 
spread load. 
– wikipedia
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
user_id username 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus 
Shard 1 
Shard 2
Vantaggi 
• Suddivide anche il carico di scrittura 
• Indici più piccoli 
• distribuzione dei dati migliore
Svantaggi 
• Difficile o impossibile effettuare query su shard 
differenti 
• Consistenza dei dati 
• Complessità extra
Supporto nativo 
http://en.wikipedia.org/wiki/ 
Shard_(database_architecture)#Support_for_sh 
ards
Sharding con Doctrine
Sharding con Doctrine 
Starting with 2.3 Doctrine DBAL contains some 
functionality to simplify the development of 
horizontally sharded applications. 
! 
In this first release it contains a ShardManager 
interface. This interface allows to programatically 
select a shard to send queries to. 
- http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
Sharding con Doctrine 
At the moment there are no functionalities yet to 
dynamically pick a shard based on ID, query or 
database row yet 
- http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
ShardManager Interface 
$shardManager = new PoolingShardManager($conn); 
! 
$currentCustomerId = 1234; 
$shardManager->selectShard($currentCustomerId); 
// all queries after this call hit the shard 
// where customer with id 1234 is on. 
! 
$shardManager->selectGlobal(); 
// the global database is selected.
SaaS con Symfony2
https://www.flickr.com/photos/reallyboring/3234624436 
Il Piano
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
SaaS con Symfony2
Strategia di 
frazionamento
KEEP CALM 
AND 
SPLIT YOUR DATA
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
2 2 bouffant 
3 1 skedaddle 
4 1 tweezers 
5 2 igloo 
6 1 foibles 
7 1 oocephalus
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
2 2 bouffant 
3 1 skedaddle 
4 1 tweezers 
5 2 igloo 
6 1 foibles 
7 1 oocephalus
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
3 1 skedaddle 
4 1 tweezers 
6 1 foibles 
7 1 oocephalus 
user_id istituto_id! username 
2 2 bouffant 
5 2 igloo 
Shard 1 
Shard 2
Strategia di selezione 
del DB
Sottodominio?
Sottodominio
Chiedilo all’utente
Chiedilo all’utente 
• Login tramite database unico (default) ! 
• Selezione manuale dell’istituto 
• Switch della connessione 
• Sincronizzazione dei dati duplicati
Una connessione “default” 
doctrine: 
dbal: 
default_connection: default 
connections: 
default: 
driver: "%database_driver%" 
host: "%database_host%" 
port: "%database_port%" 
dbname: "%database_name%" 
user: "%database_user%" 
password: "%database_password%" 
charset: UTF8
500 Shards 
shards: 
mc12345678: 
id: 1 
host: '%database_host%' 
user: '%database_user%' 
password: '%database_password%' 
dbname: nuvolamc12345678 
charset: UTF8 
mcps015006: 
id: 2 
host: '%database_host%' 
user: '%database_user%' 
password: '%database_password%' 
dbname: mcps015006 
charset: UTF8
UUID 
user_id istituto_id! username uuid 
1 1 idiopathic 
e5f0b536- 
c4cd-47c4- 
a810- 
2 2 bouffant 
ea5d2eb4-851c 
-462d-a25e- 
1756bece 
3 1 skedaddle 
a5889369-61d8 
-4b3c-b93f-cd4a3d449c46 
4 1 tweezers 
cd5759ae-7a7e 
-42d1- 
b4cf-0cd0701b 
5 2 igloo 
64976e7a-54d2 
-4230-a8ef-d624dc320cee 
6 1 foibles 
202528c0-7028 
-4a6f-9c0b-e97c6544693c 
7 1 oocephalus 
30bd250c-0a9c 
-4cf2- 
a54c-020804d1
Sincronizzazione 
(onFlush, prePersist) 
$this 
->eventDispatcher 
->dispatch( 
MultiDbSyncEntityEvent::SYNC_UTENTE, 
new MultiDbSyncEntityEvent($utente) 
);
Sincronizzazione 
public function onSyncUtente(MultiDbSyncEntityEvent 
$event) 
{ 
$user = $event->getEntity(); 
$shard = $this->getShardToSync($user); 
/** @var $connection DoctrineDBALConnection */ 
$connection = $this->doctrine->getConnection($this- 
>getConnectionNameFromShard($shard)); 
$this->syncUser($user, $connection); 
}
500 Connessioni 
nuvolamc12345678: 
driver: '%database_driver%' 
host: '%database_host%' 
port: '%database_port%' 
dbname: nuvolamc12345678 
user: '%database_user%' 
password: '%database_password%' 
charset: UTF8 
nuvolamcps015006: 
driver: '%database_driver%' 
host: '%database_host%' 
port: '%database_port%' 
dbname: nuvolamcps015006 
user: '%database_user%' 
password: '%database_password%' 
charset: UTF8
Switch della 
connessione
Switch della connessione 
private function selectDbForIstituto( 
Istituto $istituto, 
SessionInterface $session 
) 
{ 
$shardManager = $this->get('shard_manager'); 
$shardManager->selectShard($istituto); 
! 
$session->set('shard', $istituto->getShardId()); 
}
Switch della connessione 
public function onKernelRequest(GetResponseEvent $event) 
{ 
if (!$event->isMasterRequest()) { 
return; 
} 
! 
$this->shardManager->selectShard( 
$this->session->get(‘shard') 
); 
}
https://www.flickr.com/photos/jdhancock/8671399450/ 
Gestire 500 DB 
Help needed
Configurare gli shards 
protected function configure() 
{ 
$this->setName('nuvola:shard:add-config') 
->setDescription('Aggiunge la configurazione 
necessaria ad uno shard') 
->addOption('host', null, InputOption::VALUE_OPTIONAL, 
'L'host della connessione al db') 
->addOption('codiceMeccanografico', null, 
InputOption::VALUE_OPTIONAL, 'Codice meccanografico per lo 
shard'); 
}
Configurare gli shards 
protected function configure() 
{ 
$this->setName('nuvola:shard:create-config') 
->setDescription('Crea il file di configurazione per gli 
shards') 
->addOption( 
'append', 
null, 
InputOption::VALUE_NONE, 
'Se impostato a false cancella la configurazione attuale, 
altrimenit la aggiunge. Default a true' 
) 
//CUT 
}
Ad ognuno il suo shard 
public function onConsoleCommand(ConsoleCommandEvent $event) 
{ 
$shardManager = new SafeShardManager($connection); 
$istituto = $input->getParameterOption(['--istituto', '-i']); 
! 
if ('global' === $istituto) { 
$shardManager->selectGlobal(); 
} else { 
$shardManager->selectShard($istituto); 
} 
! 
}
Ciclare gli shards 
class ListShardsCommand extends AbstractShardCommand 
{ 
protected function configure() 
{ 
$this->setName('nuvola:shard:list-shards') 
->setDescription('Restituisce l'elenco degli shard configurati') 
->addOption( 
'letteraInizioIntervallo', 
null, 
InputOption::VALUE_OPTIONAL, 
'Lettera di inizio intervallo per lo shard da esportare (estremo 
compreso)' 
) 
->addOption( 
'letteraFineIntervallo', 
null, 
InputOption::VALUE_OPTIONAL, 
'Lettera di fine intervallo per lo shard da esportare (estremo compreso)' 
); 
} 
}
Ciclare gli shards 
app/console nu:sha:li | while read 
shard; do app/console doctrine:mig:mig - 
i $shard -n;done;
Parallelizzare FTW 
class MigrateCommand extends AbstractParallelCommand 
{ 
protected function execute(InputInterface $input, OutputInterface 
$output) 
{ 
/** @var GearmanClient $gearman */ 
$gearman = $this->getContainer()->get('gearman'); 
//[CUT] 
foreach ($shards as $shard) { 
$job = 'NuvolaMultiDbBundleWorkerShardWorker~migrate' . 
$shard['queue']; 
$gearman->addTask($job, $shard['shard']); 
} 
! 
$gearman->runTasks(); 
} 
}
Parallelizzare FTW 
protected function doMigrate(GearmanJob $job) 
{ 
$shard = $job->workload(); 
$command = sprintf( 
'app/console doctrine:migrations:migrate -n -i %s --env=%s', 
$shard, 
$this->env 
); 
! 
$process = $this->runProcess($job, $command); 
! 
if (!$process->isSuccessful()) { 
$this->sendErrorsToJob($job, $process, $command, 'Errore migrando ' . $shard); 
return; 
} 
! 
$success = [sprintf('Migrazione per %s completata', $shard)]; 
$job->sendComplete(serialize($success)); 
! 
return; 
}
Parallelizzare FTW 
app/console gearman:job:execute 
NuvolaMultiDbBundleWorkerShardWorker~mig 
rate0 -n —env=prod
Conclusioni
Fa al caso tuo?
Si, lo rifarei
Domande?
https://joind.in/12212
Hiring! 
http://www.ideato.it/offerta-cercasi-sviluppatore- 
php/
Thanks

More Related Content

PPTX
Back to Basics, webinar 6: Messa in esercizio
PDF
Introduzione DevOps con Ansible
PDF
Node.js - Server Side Javascript
PDF
MySQL Tech Tour 2015 - Progettare, installare e configurare MySQL Cluster
PDF
Laboratorio Di Basi Di Dati 01 Introduzione
PDF
Laboratorio Di Basi Di Dati 03 Il D B M S Postgre S Q L
PDF
Laboratorio Di Basi Di Dati 10 P H P Cookie E Sessioni
PDF
Laboratorio Di Basi Di Dati 11 P H P Interazione Con I D B M S
Back to Basics, webinar 6: Messa in esercizio
Introduzione DevOps con Ansible
Node.js - Server Side Javascript
MySQL Tech Tour 2015 - Progettare, installare e configurare MySQL Cluster
Laboratorio Di Basi Di Dati 01 Introduzione
Laboratorio Di Basi Di Dati 03 Il D B M S Postgre S Q L
Laboratorio Di Basi Di Dati 10 P H P Cookie E Sessioni
Laboratorio Di Basi Di Dati 11 P H P Interazione Con I D B M S

What's hot (18)

PPTX
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
PDF
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
PDF
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
PDF
Backup di un sito Joomla! - Procedure semplici, veloci e sicure
PPTX
Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)
PDF
Drupal Day 2011 - Node.js e Drupal
ODP
Cloud storage in azienda: perche` Riak ci e` piaciuto
PDF
Seminario team working - 21-1-2015
PDF
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
PDF
Pgtraining bdr
PDF
Elasticsearch a quick introduction
PDF
JBoss Data Grid Tech Lab
PDF
Programmazione web libera dai framework
PPTX
SQL Saturday 871 - Sardegna 2019 - SQL Server DR on Azure
PDF
Data grid
PDF
High Performance Web Apps con PHP e Symfony 2
PDF
October 2009 - JBoss Cloud
PDF
Async navigation with a lightweight ES6 framework
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
Backup di un sito Joomla! - Procedure semplici, veloci e sicure
Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)
Drupal Day 2011 - Node.js e Drupal
Cloud storage in azienda: perche` Riak ci e` piaciuto
Seminario team working - 21-1-2015
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
Pgtraining bdr
Elasticsearch a quick introduction
JBoss Data Grid Tech Lab
Programmazione web libera dai framework
SQL Saturday 871 - Sardegna 2019 - SQL Server DR on Azure
Data grid
High Performance Web Apps con PHP e Symfony 2
October 2009 - JBoss Cloud
Async navigation with a lightweight ES6 framework
Ad

Viewers also liked (20)

PDF
Scaling symfony apps
PDF
Nuvola: a tale of migration to AWS
PPTX
La scuola entra nella nuvola- Matteo Moretti
PDF
Symfony как микрофреймворк
PDF
Multi kernelowa aplikacja w oparciu o Symfony 3 i microkernele
DOCX
Research 2
PPTX
Demo: How to make air refreshener ? (Powder form & Spray form)
PPTX
Black Box Testing
PDF
พีระมิด
PPTX
Gross u11a3
PDF
ใบงาน
PDF
ทรงกระบอก
PPT
Diapositivas
PPTX
Презентация слайды2
PPS
Lets see the reality around us
PDF
Converted by pdf suite
PPT
DOCX
Excel trick
PPTX
Prolog (present)
PPTX
Mot 3033
Scaling symfony apps
Nuvola: a tale of migration to AWS
La scuola entra nella nuvola- Matteo Moretti
Symfony как микрофреймворк
Multi kernelowa aplikacja w oparciu o Symfony 3 i microkernele
Research 2
Demo: How to make air refreshener ? (Powder form & Spray form)
Black Box Testing
พีระมิด
Gross u11a3
ใบงาน
ทรงกระบอก
Diapositivas
Презентация слайды2
Lets see the reality around us
Converted by pdf suite
Excel trick
Prolog (present)
Mot 3033
Ad

Similar to SaaS con Symfony2 (20)

PDF
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
PDF
Fare con Zend Framework 2 ciò che facevo con ZF1
PDF
Php mysql3
PDF
MongoDB User Group Padova - Overviews iniziale su MongoDB
PDF
Disaccoppiare il codice di dominio dal framework e dall’infrastruttura (Sfday...
PDF
Sviluppo web dall'antichità all'avanguardia e ritorno
PDF
EE Incremental Store
PDF
Mantenere una distribuzione Drupal attraverso test coverage: Paddle case study
PDF
Come Drupal costruisce le tue pagine
PDF
Levate l'ancora! Rotte senza problemi con ZF2
PDF
Dominare il codice legacy
PDF
Programmazione e gestione della sicurezza: Verbale elettronico
PDF
Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.
PDF
SQL Server & GDPR
PDF
September 2010 - Gatein
PDF
Idp, passo dopo passo!
PDF
DDAY2014 - Performance in Drupal 8
PDF
(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...
PDF
Perl Template Toolkit
PDF
Spring, IBatis e Transazioni Aop Nel Jug Avis Web
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
Fare con Zend Framework 2 ciò che facevo con ZF1
Php mysql3
MongoDB User Group Padova - Overviews iniziale su MongoDB
Disaccoppiare il codice di dominio dal framework e dall’infrastruttura (Sfday...
Sviluppo web dall'antichità all'avanguardia e ritorno
EE Incremental Store
Mantenere una distribuzione Drupal attraverso test coverage: Paddle case study
Come Drupal costruisce le tue pagine
Levate l'ancora! Rotte senza problemi con ZF2
Dominare il codice legacy
Programmazione e gestione della sicurezza: Verbale elettronico
Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.
SQL Server & GDPR
September 2010 - Gatein
Idp, passo dopo passo!
DDAY2014 - Performance in Drupal 8
(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...
Perl Template Toolkit
Spring, IBatis e Transazioni Aop Nel Jug Avis Web

SaaS con Symfony2

  • 1. SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
  • 2. @ftassi Francesco Tassi @matteomoretti85 Matteo Moretti
  • 4. Nuvola e i suoi 50GB
  • 5. Nuvola e i suoi 50GB • Difficoltà di manutenzione (backup/ripristino) • Difficoltà di evoluzione (alter dello schema) • Impossibile replicare il sistema (debug)
  • 7. Applicazioni multi tenant “Multi-tenant si riferisce ad una architettura software in cui una singola istanza del suddetto software gira su un server ed è utilizzata da più di una client organization (tenant)”. – wikipedia
  • 9. Sharding A database shard is a horizontal partition of data in a database. Each individual partition is referred to as a shard or database shard. Each shard is held on a separate database server instance, to spread load. – wikipedia
  • 10. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle 4 tweezers 5 igloo 6 foibles 7 oocephalus
  • 11. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle 4 tweezers 5 igloo 6 foibles 7 oocephalus
  • 12. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle user_id username 4 tweezers 5 igloo 6 foibles 7 oocephalus Shard 1 Shard 2
  • 13. Vantaggi • Suddivide anche il carico di scrittura • Indici più piccoli • distribuzione dei dati migliore
  • 14. Svantaggi • Difficile o impossibile effettuare query su shard differenti • Consistenza dei dati • Complessità extra
  • 15. Supporto nativo http://en.wikipedia.org/wiki/ Shard_(database_architecture)#Support_for_sh ards
  • 17. Sharding con Doctrine Starting with 2.3 Doctrine DBAL contains some functionality to simplify the development of horizontally sharded applications. ! In this first release it contains a ShardManager interface. This interface allows to programatically select a shard to send queries to. - http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
  • 18. Sharding con Doctrine At the moment there are no functionalities yet to dynamically pick a shard based on ID, query or database row yet - http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
  • 19. ShardManager Interface $shardManager = new PoolingShardManager($conn); ! $currentCustomerId = 1234; $shardManager->selectShard($currentCustomerId); // all queries after this call hit the shard // where customer with id 1234 is on. ! $shardManager->selectGlobal(); // the global database is selected.
  • 22. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 23. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 24. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 25. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 26. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 29. KEEP CALM AND SPLIT YOUR DATA
  • 30. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 2 2 bouffant 3 1 skedaddle 4 1 tweezers 5 2 igloo 6 1 foibles 7 1 oocephalus
  • 31. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 2 2 bouffant 3 1 skedaddle 4 1 tweezers 5 2 igloo 6 1 foibles 7 1 oocephalus
  • 32. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 3 1 skedaddle 4 1 tweezers 6 1 foibles 7 1 oocephalus user_id istituto_id! username 2 2 bouffant 5 2 igloo Shard 1 Shard 2
  • 37. Chiedilo all’utente • Login tramite database unico (default) ! • Selezione manuale dell’istituto • Switch della connessione • Sincronizzazione dei dati duplicati
  • 38. Una connessione “default” doctrine: dbal: default_connection: default connections: default: driver: "%database_driver%" host: "%database_host%" port: "%database_port%" dbname: "%database_name%" user: "%database_user%" password: "%database_password%" charset: UTF8
  • 39. 500 Shards shards: mc12345678: id: 1 host: '%database_host%' user: '%database_user%' password: '%database_password%' dbname: nuvolamc12345678 charset: UTF8 mcps015006: id: 2 host: '%database_host%' user: '%database_user%' password: '%database_password%' dbname: mcps015006 charset: UTF8
  • 40. UUID user_id istituto_id! username uuid 1 1 idiopathic e5f0b536- c4cd-47c4- a810- 2 2 bouffant ea5d2eb4-851c -462d-a25e- 1756bece 3 1 skedaddle a5889369-61d8 -4b3c-b93f-cd4a3d449c46 4 1 tweezers cd5759ae-7a7e -42d1- b4cf-0cd0701b 5 2 igloo 64976e7a-54d2 -4230-a8ef-d624dc320cee 6 1 foibles 202528c0-7028 -4a6f-9c0b-e97c6544693c 7 1 oocephalus 30bd250c-0a9c -4cf2- a54c-020804d1
  • 41. Sincronizzazione (onFlush, prePersist) $this ->eventDispatcher ->dispatch( MultiDbSyncEntityEvent::SYNC_UTENTE, new MultiDbSyncEntityEvent($utente) );
  • 42. Sincronizzazione public function onSyncUtente(MultiDbSyncEntityEvent $event) { $user = $event->getEntity(); $shard = $this->getShardToSync($user); /** @var $connection DoctrineDBALConnection */ $connection = $this->doctrine->getConnection($this- >getConnectionNameFromShard($shard)); $this->syncUser($user, $connection); }
  • 43. 500 Connessioni nuvolamc12345678: driver: '%database_driver%' host: '%database_host%' port: '%database_port%' dbname: nuvolamc12345678 user: '%database_user%' password: '%database_password%' charset: UTF8 nuvolamcps015006: driver: '%database_driver%' host: '%database_host%' port: '%database_port%' dbname: nuvolamcps015006 user: '%database_user%' password: '%database_password%' charset: UTF8
  • 45. Switch della connessione private function selectDbForIstituto( Istituto $istituto, SessionInterface $session ) { $shardManager = $this->get('shard_manager'); $shardManager->selectShard($istituto); ! $session->set('shard', $istituto->getShardId()); }
  • 46. Switch della connessione public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } ! $this->shardManager->selectShard( $this->session->get(‘shard') ); }
  • 48. Configurare gli shards protected function configure() { $this->setName('nuvola:shard:add-config') ->setDescription('Aggiunge la configurazione necessaria ad uno shard') ->addOption('host', null, InputOption::VALUE_OPTIONAL, 'L'host della connessione al db') ->addOption('codiceMeccanografico', null, InputOption::VALUE_OPTIONAL, 'Codice meccanografico per lo shard'); }
  • 49. Configurare gli shards protected function configure() { $this->setName('nuvola:shard:create-config') ->setDescription('Crea il file di configurazione per gli shards') ->addOption( 'append', null, InputOption::VALUE_NONE, 'Se impostato a false cancella la configurazione attuale, altrimenit la aggiunge. Default a true' ) //CUT }
  • 50. Ad ognuno il suo shard public function onConsoleCommand(ConsoleCommandEvent $event) { $shardManager = new SafeShardManager($connection); $istituto = $input->getParameterOption(['--istituto', '-i']); ! if ('global' === $istituto) { $shardManager->selectGlobal(); } else { $shardManager->selectShard($istituto); } ! }
  • 51. Ciclare gli shards class ListShardsCommand extends AbstractShardCommand { protected function configure() { $this->setName('nuvola:shard:list-shards') ->setDescription('Restituisce l'elenco degli shard configurati') ->addOption( 'letteraInizioIntervallo', null, InputOption::VALUE_OPTIONAL, 'Lettera di inizio intervallo per lo shard da esportare (estremo compreso)' ) ->addOption( 'letteraFineIntervallo', null, InputOption::VALUE_OPTIONAL, 'Lettera di fine intervallo per lo shard da esportare (estremo compreso)' ); } }
  • 52. Ciclare gli shards app/console nu:sha:li | while read shard; do app/console doctrine:mig:mig - i $shard -n;done;
  • 53. Parallelizzare FTW class MigrateCommand extends AbstractParallelCommand { protected function execute(InputInterface $input, OutputInterface $output) { /** @var GearmanClient $gearman */ $gearman = $this->getContainer()->get('gearman'); //[CUT] foreach ($shards as $shard) { $job = 'NuvolaMultiDbBundleWorkerShardWorker~migrate' . $shard['queue']; $gearman->addTask($job, $shard['shard']); } ! $gearman->runTasks(); } }
  • 54. Parallelizzare FTW protected function doMigrate(GearmanJob $job) { $shard = $job->workload(); $command = sprintf( 'app/console doctrine:migrations:migrate -n -i %s --env=%s', $shard, $this->env ); ! $process = $this->runProcess($job, $command); ! if (!$process->isSuccessful()) { $this->sendErrorsToJob($job, $process, $command, 'Errore migrando ' . $shard); return; } ! $success = [sprintf('Migrazione per %s completata', $shard)]; $job->sendComplete(serialize($success)); ! return; }
  • 55. Parallelizzare FTW app/console gearman:job:execute NuvolaMultiDbBundleWorkerShardWorker~mig rate0 -n —env=prod
  • 57. Fa al caso tuo?