Forum: Rails France Atomicité lors de la création

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-04 08:52
(Received via mailing list)
Bonjour, j'ai 2 modèles qui, au niveau métier sont liés de la manière
suivante :

- Une classe AR "production" contient entre autre une info de stock
(dans le
sens quantité)
- Une classe AR "mission" puise dans ce stock pour apporter (camion) de
la
marchandise vers une autre ville
- Une mission n'est possible que si le stock correspondant est
strictement
positif.

Jusqu'à présent tout se passe dans la classe "mission" :
- un "validate_on_create" s'assure que le stock est suffisant
- un "after_create" décrémente le stock de la valeur correspondant à la
mission

Mon soucis est de rendre ça atomique : lors d'un accès concurrent au
meme
stock, je ne veux pas que 2 personnes pensent qu'il y a du stock, que
les 2
décrémentes, et que finalement le stock devienne négatif vu qu'en fait
il
n'y en avait pas pour les 2.

J'ai bien vu les transactions[1], mais je ne sais pas comment faire pour
la
mettre dans le modèle, vu que ça touche des actions avant et après la
création.

Merci (-:

gUI

[1]
http://api.rubyonrails.com/classes/ActiveRecord/Tr...
--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2009-02-04 10:33
(Received via mailing list)
2009/2/4 Guillaume Betous <guillaume.betous@gmail.com>:
> Jusqu'à présent tout se passe dans la classe "mission" :
> mettre dans le modèle, vu que ça touche des actions avant et après la
> création.
>

Je pense que pour être vraiment sur du résultat, tu devrais utiliser
des contraintes sur ta base de données directement.

--
http://fabien.jakimowicz.com
047a4fc673336a70a6b58338bc6d677d?d=identicon&s=25 Michel Belleville (Guest)
on 2009-02-04 10:41
(Received via mailing list)
Sinon, tu peux faire une méthode qui décore create en mettant une
transaction autour, du genre :

class Mission < AR::B
...
def create_according_to_stock(*args, &block)
self.transaction do
self.create(args, block)
end
...
end

Et dans ton contrôleur, tu appelles ta méthode décorante à la place du
create normal.

Michel Belleville


2009/2/4 Fabien Jakimowicz <fabien@jakimowicz.com>
047a4fc673336a70a6b58338bc6d677d?d=identicon&s=25 Michel Belleville (Guest)
on 2009-02-04 10:41
(Received via mailing list)
(bon je m'apercois en me relistant que j'ai oublié des indentations et
des
'end' mais le principe reste valable)

Michel Belleville


2009/2/4 Michel Belleville <michel.belleville@gmail.com>
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-04 10:47
(Received via mailing list)
oui, c'est pas mal comme solution.

je vais tenter ça. merci !

gUI

Le 4 février 2009 10:41, Michel Belleville <michel.belleville@gmail.com>
a
écrit :

>>
>> create normal.
>>> >
>>> > Jusqu'à présent tout se passe dans la classe "mission" :
>>> > n'y en avait pas pour les 2.
>>> --
>>> http://fabien.jakimowicz.com
>>>
>>>
>>>
>>
>
> >
>


--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
79b719d7f060027f31511f43f030e5c7?d=identicon&s=25 Tony Chauveau (kusanar)
on 2009-02-04 19:45
Peut-être celà serait plus sur avec un lock?

http://api.rubyonrails.org/classes/ActiveRecord/Lo...

Car là, avec une transaction, 2 utilisateurs peuvent passer si leur
validation se fait en même temps (la 1ère requête de la transaction
passe et la seconde n'a aucune contrainte pour ne pas passer)
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-04 20:38
(Received via mailing list)
J'avais lu ça, mais apparemment c'est réellement pour les cas extrêmes.
Le
mien est un classique, et s'approche de très près du cas d'école du
transfert d'argent entre 2 comptes.

gUI

Le 4 février 2009 19:45, Tony Chauveau <list-incoming@andreas-s.net> a
écrit
:

>
> >
>


--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2009-02-04 20:43
(Received via mailing list)
2009/2/4 Guillaume Betous <guillaume.betous@gmail.com>:
> J'avais lu ça, mais apparemment c'est réellement pour les cas extrêmes. Le
> mien est un classique, et s'approche de très près du cas d'école du
> transfert d'argent entre 2 comptes.
>

C'est un cas qui peut se produire bien plus souvent qu'on ne le pense
: il suffit d'avoir la malchance de 2 utilisateurs qui font au même
moment (proche de la milliseconde) la même action ...

Quitte à faire un lock, une contrainte sur la base/table est encore
plus sage : cela ne bloque pas la base de données comme un lock et ca
laisse la base gérer la fiabilité des données.

--
http://fabien.jakimowicz.com
603047efae3b7b158019fb1228a3b2d0?d=identicon&s=25 Renaud Chaput (Guest)
on 2009-02-04 20:56
(Received via mailing list)
Fabien Jakimowicz a écrit :
> Quitte à faire un lock, une contrainte sur la base/table est encore
> plus sage : cela ne bloque pas la base de données comme un lock et ca
> laisse la base gérer la fiabilité des données.
Sauf que la philosophie de rails est de ne rien faire en DB et de tout
gérer dans le modèle ou via l'ORM, dans l'application.
Je ne suis pas trop d'accord avec cette idée, et préfèrerais un moyen
d'implémenter des contraintes (FK, ...) au niveau de la DB si celle ci
la gère, mais cela n'est pas du tout prévu (un choix de conception de
DHH, qui a été discuté).

renchap
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2009-02-04 21:02
(Received via mailing list)
2009/2/4 Renaud Chaput <renchap@cocoa-x.com>:
> DHH, qui a été discuté).
>

en effet, mais les index uniques (qui sont implémentés dans rails)
contredisent totalement cette logique rails.

De plus, tout n'est pas possible depuis les modèles ;)

--
http://fabien.jakimowicz.com
79b719d7f060027f31511f43f030e5c7?d=identicon&s=25 Tony Chauveau (kusanar)
on 2009-02-04 21:02
Renaud Chaput wrote:
> Fabien Jakimowicz a écrit :
>> Quitte à faire un lock, une contrainte sur la base/table est encore
>> plus sage : cela ne bloque pas la base de données comme un lock et ca
>> laisse la base gérer la fiabilité des données.
> Sauf que la philosophie de rails est de ne rien faire en DB et de tout
> gérer dans le modèle ou via l'ORM, dans l'application.
> Je ne suis pas trop d'accord avec cette idée, et préfèrerais un moyen
> d'implémenter des contraintes (FK, ...) au niveau de la DB si celle ci
> la gère, mais cela n'est pas du tout prévu (un choix de conception de
> DHH, qui a été discuté).
>
> renchap

C'est un choix qui se comprend si l'on souhaite réellement ne pas
dépendre de la base de donnée choisie. Mais celà ne doit pas non plus
empêcher toute optimisation dans le cas d'un projet où le choix de la
base est connu et pérenne
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-04 22:56
(Received via mailing list)
> C'est un cas qui peut se produire bien plus souvent qu'on ne le pense
> : il suffit d'avoir la malchance de 2 utilisateurs qui font au même
> moment (proche de la milliseconde) la même action ...


Je sais, c'est pour ça que je m'en inquiète, mais la transaction Rails
sert
à ça non ?

gUI

--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
79b719d7f060027f31511f43f030e5c7?d=identicon&s=25 Tony Chauveau (kusanar)
on 2009-02-04 23:35
>
> Je sais, c'est pour ça que je m'en inquiète, mais la transaction Rails
> sert
> à ça non ?
>

C'est pas exactement le même problème. La transaction permet d'enchainer
plusieurs requêtes en annulant tout si l'une d'entre elles échoue.
Le lock interdit l'accès en écriture à une table (ou juste une ligne de
cette table) tant qu'on a pas rendu la main.
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-05 07:26
(Received via mailing list)
> C'est pas exactement le même problème. La transaction permet d'enchainer
> plusieurs requêtes en annulant tout si l'une d'entre elles échoue.
> Le lock interdit l'accès en écriture à une table (ou juste une ligne de
> cette table) tant qu'on a pas rendu la main.


Ah bin j'avais rien compris (-:

Donc oui en effet j'ai bien besoin d'un lock.

gUI

--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
047a4fc673336a70a6b58338bc6d677d?d=identicon&s=25 Michel Belleville (Guest)
on 2009-02-05 07:27
(Received via mailing list)
En fait, à ta place je ferais les deux approches à la fois. Le blocage
de
l'objet t'assure la non-concurrence des requêtes (le script est le seul
à
passer à la fois), et la transaction t'assure l'atomicité (tout passe à
la
fois ou rien ne passe du tout).
Michel Belleville


2009/2/4 Tony Chauveau <list-incoming@andreas-s.net>
98d4d4be867fc17d3120f683513d3819?d=identicon&s=25 Guillaume Betous (Guest)
on 2009-02-05 08:15
(Received via mailing list)
Je peux toujours essayer, ne serait-ce que pour l'exercice.

Mais cela dit, je me suis trompé. En y réfléchissant bien, si j'ai la
non
concurrence, j'ai pas besoin de l'atomicité.

Et au passage j'ajouterais que il me semble que "atomicité" est ici
impropre
: l'atomicité garantissant normalement la non-concurrence (en tous cas
dans
le cadre des instructions processeur), puisque dans opération atomique
on
parle de operation non interruptible.

gUI

Le 5 février 2009 07:26, Michel Belleville <michel.belleville@gmail.com>
a
écrit :

>>
>> --
>> Posted via http://www.ruby-forum.com/.
>>
>>
>>
>
> >
>


--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
047a4fc673336a70a6b58338bc6d677d?d=identicon&s=25 Michel Belleville (Guest)
on 2009-02-05 10:03
(Received via mailing list)
Disons, dans ce cas-là c'est un peu toi qui assure l'atomicité en
vérifiant
que le compte y est et que tu ne décrémente que si le nouvel objet est
validé. Si tu ne faisais pas ça, le lock ne serait pas suffisant.

Michel Belleville


2009/2/5 Guillaume Betous <guillaume.betous@gmail.com>
This topic is locked and can not be replied to.