diff options
| author | Géry Debongnie <ged@odoo.com> | 2018-04-26 09:38:47 +0200 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2018-04-26 09:44:22 +0200 |
| commit | 535490a073934a1950989dcb56461dc6db326780 (patch) | |
| tree | bea537845e91bbed8b04ed3afca2f2ff91eaecff | |
| parent | 549573e24c1f0b0a4a31636732db007bfe1a11d7 (diff) | |
[FIX] web: fix a race condition in web client
Here is an interesting scenario, involving the reconciliation tour again
(because it is our only tour that does async stuff before changing url):
- web client starts normally
- tour reconciliation starts, perform an rpc to find some id
- web client fetches users default action, it is empty, so clicks on
first menu item to load initial action, which is discuss. this will
make the web client load the action with datamanager (it should be the
action manager's job!).
- reconciliation tour rpc completes, it changes the url, this will do a
do_action
- the load_action rpc from the web client completes, it will then
perform a do_action, which will drop the action initiated by the tour
- tour fails.
The issue here is that the on_menu_action method from the web client is
not really safe, from a concurrency point of view: it performs some
asynchronous work, and then unilateraly decides to do a doAction. With
this commit, we simply add the do_action request to the action manager,
which uses internally a "dropprevious" system. This means that it will
always use the last action, just as expected.
| -rw-r--r-- | addons/web/static/src/js/chrome/web_client.js | 25 |
1 files changed, 4 insertions, 21 deletions
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js index e2b3a23d2a6..c4886cd0e89 100644 --- a/addons/web/static/src/js/chrome/web_client.js +++ b/addons/web/static/src/js/chrome/web_client.js @@ -157,27 +157,10 @@ return AbstractWebClient.extend({ }); }, on_menu_action: function(options) { - var self = this; - return this.menu_dm.add(data_manager.load_action(options.action_id)) - .then(function (result) { - return self.action_mutex.exec(function() { - var completed = $.Deferred(); - self.action_manager.doAction(result, { - clear_breadcrumbs: true, - action_menu_id: options.id, - }).fail(function() { - self.menu.open_menu(options.previous_menu_id); - }).always(function() { - completed.resolve(); - }); - setTimeout(function() { - completed.resolve(); - }, 2000); - // We block the menu when clicking on an element until the action has correctly finished - // loading. If something crash, there is a 2 seconds timeout before it's unblocked. - return completed; - }); - }); + this.action_manager.doAction(options.action_id, { + clear_breadcrumbs: true, + action_menu_id: options.id, + }); }, toggle_fullscreen: function(fullscreen) { this._super(fullscreen); |
