Flush() y los servicios

23 views
Skip to first unread message

Jordi Casadevall

unread,
Jun 13, 2012, 3:52:58 AM6/13/12
to symfony_...@googlegroups.com
Hola,

estoy refactorizando un proyecto, y pasando a servicios de bundles core
todas las llamadas a doctrine que se hac�an desde los controladores.

Ejemplo: $this->get('x_manager')->getXByDate($date_min,$date_max),
$this->get('y_manager')->getYById($id)...

Y dentro de "x_manager" el m�todo correspondiente que accede a doctrine.
Todo esto para independizar el frontend del core y poder tener
diferentes frontend accediendo al mismo core.


La duda, es que hasta ahora al modificar los objectos de modelo, hac�a
un �nico flush() al final del controlador. Descartando hacer flush()
para cada m�todo de los servicios "x_manager", "y_manager"... Veo la
opci�n de poner un m�todo a cada servicio que haga flush(), y llamar
este m�todo al final de los controladores. Pero no acaba de gustarme por
el hecho de que si se accede a 2 servicios, s�lo es necesario hacer
flush() en uno de los 2. Tambi�n hab�a pensado buscar si hay un evento
que se dispara al final de la ejecuci�n de una action de un controlador,
y que sea este evento que haga el flush().

Alguien se ha encontrado con este "dilema"? Alguna idea mejor?

Gracias,

Jordi

Francesc Rosàs

unread,
Jun 13, 2012, 6:00:51 AM6/13/12
to symfony_...@googlegroups.com
Jordi, yo estoy igual que tu.

En otro hilo Ronny comentó la implementación de los "Friends of Symfony". Básicamente tienen los métodos updateUser(), deleteUser(), ... en el manager. Algunos métodos (como el updateUser()) tienen la opción de no hacer el flush() después de persistir, supongo que para tener la opción de hacer un sólo flush al final (haciendo un $em->flush() directamente en el controller, por ejemplo) si estás trabajando con varias entidades a la vez. Un ejemplo.

Actualmente estoy tirando de ésta solución. Aún se me hace extraño que al persistir una entidad se me persista también cualquier otra que haya cambiado pero ya me voy acostumbrando :)

Salut!

2012/6/13 Jordi Casadevall <jordi.ca...@gmail.com>
Hola,

estoy refactorizando un proyecto, y pasando a servicios de bundles core todas las llamadas a doctrine que se hacían desde los controladores.


Ejemplo:   $this->get('x_manager')->getXByDate($date_min,$date_max),   $this->get('y_manager')->getYById($id)...

Y dentro de "x_manager" el método correspondiente que accede a doctrine. Todo esto para independizar el frontend del core y poder tener diferentes frontend accediendo al mismo core.


La duda, es que hasta ahora al modificar los objectos de modelo, hacía un único flush() al final del controlador. Descartando hacer flush() para cada método de los servicios "x_manager", "y_manager"...   Veo la opción de poner un método a cada servicio que haga flush(), y llamar este método al final de los controladores. Pero no acaba de gustarme por el hecho de que si se accede a 2 servicios, sólo es necesario hacer flush() en uno de los 2. También había pensado buscar si hay un evento que se dispara al final de la ejecución de una action de un controlador, y que sea este evento que haga el flush().

Jordi Casadevall

unread,
Jun 13, 2012, 1:55:59 PM6/13/12
to symfony_...@googlegroups.com
La solución finalmente ha sido crear un mini-wrapper encima del doctrine, "database_manager", con un método __destruct() que se llama automáticamente y donde se hace el flush() según si un flag "flush_required" està o no activado.  Entonces los diferentes servicios de core recuperan el doctrine siempre desde el "database_manager", e invocan un método que activa el flag  "flush_required" para los métodos que actualitzan la base de datos.  De esta forma se consigue que sólo se ejecute el flush() una sola vez al final cuando se hace el __destruct() del wrapper "database_manager".

Al 13/06/12 12:00, En/na Francesc Rosàs ha escrit:

Francesc Rosàs

unread,
Jun 13, 2012, 2:08:36 PM6/13/12
to symfony_...@googlegroups.com
Muy interesante. Por cómo planteas la solución entiendo que todo esto lo haces por temas de rendimiento no?

Bueno, ya contarás qué tal te funciona.

2012/6/13 Jordi Casadevall <jordi.ca...@gmail.com>

Jordi Casadevall

unread,
Jun 13, 2012, 2:14:10 PM6/13/12
to symfony_...@googlegroups.com
De rendimiento para hacer un sólo flush() y desacople para que el controlador de frontend sólo invoque métodos de los servicios de core, sin tener que hacer flush() ni nada referente a la base de datos.


Al 13/06/12 20:08, En/na Francesc Rosàs ha escrit:

Francesc Rosàs

unread,
Jun 13, 2012, 2:33:50 PM6/13/12
to symfony_...@googlegroups.com
No entiendo lo del desacople. En tus servicios, en vez de hacer:

$em->flush();

supongo que harás algo como:

$dbManager->requireFlush();

El acople es el mismo no?

Por otra parte se podrían evitar estas llamadas al "requireFlush()" haciendo que el "database_manager" hiciera siempre el flush pero supongo que luego sí que bajaría el rendimiento.

Jordi Casadevall

unread,
Jun 13, 2012, 2:40:22 PM6/13/12
to symfony_...@googlegroups.com
El tema està en que el flush sólo se haga una sola vez al final de todo. Sería equivalente a hacer el flush() en la última linea del controlador de frontend. Pero para un buen desacople, no es lógico que el controlador de frontend invoque una función de base de datos...   En cambio si el flush se pone en __destruct(), es symfony quien lo invoca automáticamente al destruir el wrapper database_manager.

El flush() sólo debe hacerse cuando se actualiza la base de datos. En operaciones de sólo lectura no es necesario ni conveniente para el rendimiento.


Al 13/06/12 20:33, En/na Francesc Rosàs ha escrit:

theUniC

unread,
Jun 13, 2012, 4:07:04 PM6/13/12
to symfony_...@googlegroups.com
Sinceramente, no acabo de ver hacer un flush en un __destruct (qué no lo invoca Symfony, sino PHP). Está bien que el controlador no se responsabilize de hacer flush (qué más bien es un método relacionado más con el EntityManager y con la capa de persistencia, que no con la base de datos). Pero quizá y como mucho, antes de meterlo en un __destruct lo metería en un servicio de persistencia, al que se le pudieran pasar diversas entities y sea el mismo servicio el que haga el flush explícitamente al final de su propia ejecución.

Lo veo más algo relacionado con que tener que tratar con "transacciones a nivel de código", dónde tu controlas cuándo se hace commit (porqué el desarrollador sabe cuál es el punto dónde hay que hacerlo o ejecutar un rollback). Al fin y al cabo, si "te da la sensación" que se están ejecutando flushes de manera excesiva, es que hay algo que está mal y debe corregirse.

Saludos,
Christian.
Reply all
Reply to author
Forward
0 new messages