[REF] web, *: remove legacy MutexedDropPrevious
In our continued effort to remove legacy code, this commit replaces the unique usage of the legacy MutexedDropPrevious util with the new mutex util. The legacy MutexedDropPrevious has been removed. Part-of task-id 3439226 closes odoo/odoo#132948 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -107,7 +107,6 @@
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
|
||||
@@ -142,7 +142,6 @@
|
||||
# FIXME POSREF legacy dependencies to remove
|
||||
'web/static/lib/moment/moment.js',
|
||||
'web/static/src/legacy/js/promise_extension.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/legacy_component.js',
|
||||
],
|
||||
# Bundle that starts the pos, loaded on /pos/ui
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
|
||||
import { Order, Orderline } from "@point_of_sale/app/store/models";
|
||||
import { Mutex } from "@web/core/utils/concurrency";
|
||||
import concurrency from "@web/legacy/js/core/concurrency";
|
||||
import { roundDecimals, roundPrecision } from "@web/core/utils/numbers";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_popup";
|
||||
|
||||
// FIXME: Perhaps MutexedDropPrevious can be replaced by the new KeepLast.
|
||||
// > This might require thorough investigation on how _updateRewards work.
|
||||
// > If successful, we can fully get rid of the legacy concurrency module.
|
||||
const dropPrevious = new concurrency.MutexedDropPrevious(); // Used for queuing reward updates
|
||||
const mutex = new Mutex(); // Used for sequential cache updates
|
||||
const updateRewardsMutex = new Mutex();
|
||||
|
||||
function _newRandomRewardCode() {
|
||||
return (Math.random() + 1).toString(36).substring(3);
|
||||
@@ -150,9 +146,9 @@ patch(Order.prototype, {
|
||||
|
||||
/** @override */
|
||||
getEmailItems() {
|
||||
return super.getEmailItems(...arguments).concat(
|
||||
this.has_pdf_gift_card ? [_t("the gift cards")] : []
|
||||
);
|
||||
return super
|
||||
.getEmailItems(...arguments)
|
||||
.concat(this.has_pdf_gift_card ? [_t("the gift cards")] : []);
|
||||
},
|
||||
|
||||
export_as_JSON() {
|
||||
@@ -300,15 +296,18 @@ patch(Order.prototype, {
|
||||
return orderLines[orderLines.length - 1];
|
||||
},
|
||||
set_pricelist(pricelist) {
|
||||
const oldPricelist = this.pricelist
|
||||
const oldPricelist = this.pricelist;
|
||||
super.set_pricelist(...arguments);
|
||||
if (this.couponPointChanges && oldPricelist !== pricelist) {
|
||||
// Remove couponPointChanges for cards in no longer available programs.
|
||||
// This makes sure that counting of points on loyalty and ewallet programs is updated after pricelist changes.
|
||||
const loyaltyProgramIds = new Set(
|
||||
this.pos.programs
|
||||
.filter((program) => program.pricelist_ids.length > 0
|
||||
&& (!pricelist || !program.pricelist_ids.includes(pricelist.id)))
|
||||
.filter(
|
||||
(program) =>
|
||||
program.pricelist_ids.length > 0 &&
|
||||
(!pricelist || !program.pricelist_ids.includes(pricelist.id))
|
||||
)
|
||||
.map((program) => program.id)
|
||||
);
|
||||
for (const [key, pointChange] of Object.entries(this.couponPointChanges)) {
|
||||
@@ -367,33 +366,30 @@ patch(Order.prototype, {
|
||||
if (this.pos.programs.length === 0) {
|
||||
return;
|
||||
}
|
||||
dropPrevious
|
||||
.exec(() => {
|
||||
return this._updateLoyaltyPrograms().then(async () => {
|
||||
// Try auto claiming rewards
|
||||
const claimableRewards = this.getClaimableRewards(false, false, true);
|
||||
let changed = false;
|
||||
for (const { coupon_id, reward } of claimableRewards) {
|
||||
if (
|
||||
reward.program_id.rewards.length === 1 &&
|
||||
!reward.program_id.is_nominative &&
|
||||
(reward.reward_type !== "product" ||
|
||||
(reward.reward_type == "product" && !reward.multi_product))
|
||||
) {
|
||||
this._applyReward(reward, coupon_id);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
updateRewardsMutex.exec(() => {
|
||||
return this._updateLoyaltyPrograms().then(async () => {
|
||||
// Try auto claiming rewards
|
||||
const claimableRewards = this.getClaimableRewards(false, false, true);
|
||||
let changed = false;
|
||||
for (const { coupon_id, reward } of claimableRewards) {
|
||||
if (
|
||||
reward.program_id.rewards.length === 1 &&
|
||||
!reward.program_id.is_nominative &&
|
||||
(reward.reward_type !== "product" ||
|
||||
(reward.reward_type == "product" && !reward.multi_product))
|
||||
) {
|
||||
this._applyReward(reward, coupon_id);
|
||||
changed = true;
|
||||
}
|
||||
// Rewards may impact the number of points gained
|
||||
if (changed) {
|
||||
await this._updateLoyaltyPrograms();
|
||||
}
|
||||
this._updateRewardLines();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
/* catch the reject of dp when calling `add` to avoid unhandledrejection */
|
||||
}
|
||||
// Rewards may impact the number of points gained
|
||||
if (changed) {
|
||||
await this._updateLoyaltyPrograms();
|
||||
}
|
||||
this._updateRewardLines();
|
||||
});
|
||||
});
|
||||
},
|
||||
async _updateLoyaltyPrograms() {
|
||||
await this._checkMissingCoupons();
|
||||
@@ -716,7 +712,10 @@ patch(Order.prototype, {
|
||||
if (program.limit_usage && program.total_order_count >= program.max_usage) {
|
||||
return false;
|
||||
}
|
||||
if (program.pricelist_ids.length > 0 && (!this.pricelist || !program.pricelist_ids.includes(this.pricelist.id))) {
|
||||
if (
|
||||
program.pricelist_ids.length > 0 &&
|
||||
(!this.pricelist || !program.pricelist_ids.includes(this.pricelist.id))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -949,8 +948,10 @@ patch(Order.prototype, {
|
||||
: 0;
|
||||
for (const couponProgram of allCouponPrograms) {
|
||||
const program = this.pos.program_by_id[couponProgram.program_id];
|
||||
if (program.pricelist_ids.length > 0
|
||||
&& (!this.pricelist || !program.pricelist_ids.includes(this.pricelist.id))) {
|
||||
if (
|
||||
program.pricelist_ids.length > 0 &&
|
||||
(!this.pricelist || !program.pricelist_ids.includes(this.pricelist.id))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (program.trigger == "with_code") {
|
||||
@@ -1165,7 +1166,7 @@ patch(Order.prototype, {
|
||||
let cheapestLine = false;
|
||||
for (const lines of Object.values(discountLinesPerReward)) {
|
||||
const lineReward = this.pos.reward_by_id[lines[0].reward_id];
|
||||
if (lineReward.reward_type !== 'discount') {
|
||||
if (lineReward.reward_type !== "discount") {
|
||||
continue;
|
||||
}
|
||||
let discountedLines = orderLines;
|
||||
@@ -1496,9 +1497,11 @@ patch(Order.prototype, {
|
||||
let claimableRewards = null;
|
||||
let coupon = null;
|
||||
if (rule) {
|
||||
let program_pricelists = rule.program_id.pricelist_ids;
|
||||
if (program_pricelists.length > 0
|
||||
&& (!this.pricelist || !program_pricelists.includes(this.pricelist.id))) {
|
||||
const program_pricelists = rule.program_id.pricelist_ids;
|
||||
if (
|
||||
program_pricelists.length > 0 &&
|
||||
(!this.pricelist || !program_pricelists.includes(this.pricelist.id))
|
||||
) {
|
||||
return _t("That promo code program requires a specific pricelist.");
|
||||
}
|
||||
if (this.codeActivatedProgramRules.includes(rule.id)) {
|
||||
@@ -1515,7 +1518,13 @@ patch(Order.prototype, {
|
||||
const { successful, payload } = await this.env.services.orm.call(
|
||||
"pos.config",
|
||||
"use_coupon_code",
|
||||
[[this.pos.config.id], code, this.creation_date, customerId, this.pricelist ? this.pricelist.id : false]
|
||||
[
|
||||
[this.pos.config.id],
|
||||
code,
|
||||
this.creation_date,
|
||||
customerId,
|
||||
this.pricelist ? this.pricelist.id : false,
|
||||
]
|
||||
);
|
||||
if (successful) {
|
||||
// Allow rejecting a gift card that is not yet paid.
|
||||
|
||||
@@ -158,7 +158,6 @@
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
|
||||
@@ -107,7 +107,6 @@ This module provides the core of the Odoo Web Client.
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
@@ -265,7 +264,6 @@ This module provides the core of the Odoo Web Client.
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
/**
|
||||
* Concurrency Utils
|
||||
*
|
||||
* This file contains a short collection of useful helpers designed to help with
|
||||
* everything concurrency related in Odoo.
|
||||
*
|
||||
* The basic concurrency primitives in Odoo JS are the callback, and the
|
||||
* promises. Promises (promise) are more composable, so we usually use them
|
||||
* whenever possible. We use the jQuery implementation.
|
||||
*
|
||||
* Those functions are really nothing special, but are simply the result of how
|
||||
* we solved some concurrency issues, when we noticed that a pattern emerged.
|
||||
*/
|
||||
|
||||
import Class from "@web/legacy/js/core/class";
|
||||
|
||||
const concurrency = {
|
||||
/**
|
||||
* A MutexedDropPrevious is a primitive for serializing computations while
|
||||
* skipping the ones that where executed between a current one and before
|
||||
* the execution of a new one. This is useful to avoid useless RPCs.
|
||||
*
|
||||
* You can read the Mutex description to understand its role ; for the
|
||||
* DropPrevious part of this abstraction, imagine the following situation:
|
||||
* you have a code that call the server with a fixed argument and a list of
|
||||
* operations that only grows after each call and you only care about the
|
||||
* RPC result (the server code doesn't do anything). If this code is called
|
||||
* three times (A B C) and C is executed before B has started, it's useless
|
||||
* to make an extra RPC (B) if you know that it won't have an impact and you
|
||||
* won't use its result.
|
||||
*
|
||||
* Note that the promise returned by the exec call won't be resolved if
|
||||
* exec is called before the first exec call resolution ; only the promise
|
||||
* returned by the last exec call will be resolved (the other are rejected);
|
||||
*
|
||||
* A MutexedDropPrevious has to be a class, and not a function, because we
|
||||
* have to keep track of some internal state. The exec function takes as
|
||||
* argument an action (and not a promise as DropPrevious for example)
|
||||
* because it's the MutexedDropPrevious role to trigger the RPC call that
|
||||
* returns a promise when it's time.
|
||||
*/
|
||||
MutexedDropPrevious: Class.extend({
|
||||
init: function () {
|
||||
this.locked = false;
|
||||
this.currentProm = null;
|
||||
this.pendingAction = null;
|
||||
this.pendingProm = null;
|
||||
},
|
||||
/**
|
||||
* @param {function} action a function which may return a promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
exec: function (action) {
|
||||
var self = this;
|
||||
var resolution;
|
||||
var rejection;
|
||||
if (this.locked) {
|
||||
this.pendingAction = action;
|
||||
var oldPendingDef = this.pendingProm;
|
||||
|
||||
this.pendingProm = new Promise(function (resolve, reject) {
|
||||
resolution = resolve;
|
||||
rejection = reject;
|
||||
if (oldPendingDef) {
|
||||
oldPendingDef.reject();
|
||||
}
|
||||
self.currentProm.reject();
|
||||
});
|
||||
this.pendingProm.resolve = resolution;
|
||||
this.pendingProm.reject = rejection;
|
||||
return this.pendingProm;
|
||||
} else {
|
||||
this.locked = true;
|
||||
this.currentProm = new Promise(function (resolve, reject) {
|
||||
resolution = resolve;
|
||||
rejection = reject;
|
||||
function unlock() {
|
||||
self.locked = false;
|
||||
if (self.pendingAction) {
|
||||
var action = self.pendingAction;
|
||||
var prom = self.pendingProm;
|
||||
self.pendingAction = null;
|
||||
self.pendingProm = null;
|
||||
self.exec(action)
|
||||
.then(prom.resolve)
|
||||
.guardedCatch(prom.reject);
|
||||
}
|
||||
}
|
||||
Promise.resolve(action())
|
||||
.then(function (result) {
|
||||
resolve(result);
|
||||
unlock();
|
||||
})
|
||||
.guardedCatch(function (reason) {
|
||||
reject(reason);
|
||||
unlock();
|
||||
});
|
||||
});
|
||||
this.currentProm.resolve = resolution;
|
||||
this.currentProm.reject = rejection;
|
||||
return this.currentProm;
|
||||
}
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
export default concurrency;
|
||||
@@ -1,379 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import concurrency from "@web/legacy/js/core/concurrency";
|
||||
import { Mutex } from "@web/core/utils/concurrency";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
var makeTestPromise = testUtils.makeTestPromise;
|
||||
var makeTestPromiseWithAssert = testUtils.makeTestPromiseWithAssert;
|
||||
|
||||
QUnit.module('core', {}, function () {
|
||||
|
||||
QUnit.module('concurrency');
|
||||
|
||||
QUnit.test('mutex: simple scheduling', async function (assert) {
|
||||
assert.expect(5);
|
||||
var mutex = new Mutex();
|
||||
|
||||
var prom1 = makeTestPromiseWithAssert(assert, 'prom1');
|
||||
var prom2 = makeTestPromiseWithAssert(assert, 'prom2');
|
||||
|
||||
mutex.exec(function () { return prom1; });
|
||||
mutex.exec(function () { return prom2; });
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
await prom1.resolve();
|
||||
|
||||
assert.verifySteps(['ok prom1']);
|
||||
|
||||
await prom2.resolve();
|
||||
|
||||
assert.verifySteps(['ok prom2']);
|
||||
});
|
||||
|
||||
QUnit.test('mutex: simpleScheduling2', async function (assert) {
|
||||
assert.expect(5);
|
||||
var mutex = new Mutex();
|
||||
|
||||
var prom1 = makeTestPromiseWithAssert(assert, 'prom1');
|
||||
var prom2 = makeTestPromiseWithAssert(assert, 'prom2');
|
||||
|
||||
mutex.exec(function () { return prom1; });
|
||||
mutex.exec(function () { return prom2; });
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
await prom2.resolve();
|
||||
|
||||
assert.verifySteps(['ok prom2']);
|
||||
|
||||
await prom1.resolve();
|
||||
|
||||
assert.verifySteps(['ok prom1']);
|
||||
});
|
||||
|
||||
QUnit.test('mutex: reject', async function (assert) {
|
||||
assert.expect(7);
|
||||
var mutex = new Mutex();
|
||||
|
||||
var prom1 = makeTestPromiseWithAssert(assert, 'prom1');
|
||||
var prom2 = makeTestPromiseWithAssert(assert, 'prom2');
|
||||
var prom3 = makeTestPromiseWithAssert(assert, 'prom3');
|
||||
|
||||
mutex.exec(function () { return prom1; }).catch(function () {});
|
||||
mutex.exec(function () { return prom2; }).catch(function () {});
|
||||
mutex.exec(function () { return prom3; }).catch(function () {});
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
prom1.resolve();
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok prom1']);
|
||||
|
||||
prom2.catch(function () {
|
||||
assert.verifySteps(['ko prom2']);
|
||||
});
|
||||
prom2.reject({name: "sdkjfmqsjdfmsjkdfkljsdq"});
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
prom3.resolve();
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok prom3']);
|
||||
});
|
||||
|
||||
QUnit.test('mutex: getUnlockedDef checks', async function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
var mutex = new Mutex();
|
||||
|
||||
var prom1 = makeTestPromiseWithAssert(assert, 'prom1');
|
||||
var prom2 = makeTestPromiseWithAssert(assert, 'prom2');
|
||||
|
||||
mutex.getUnlockedDef().then(function () {
|
||||
assert.step('mutex unlocked (1)');
|
||||
});
|
||||
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['mutex unlocked (1)']);
|
||||
|
||||
mutex.exec(function () { return prom1; });
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
mutex.getUnlockedDef().then(function () {
|
||||
assert.step('mutex unlocked (2)');
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
mutex.exec(function () { return prom2; });
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
await prom1.resolve();
|
||||
|
||||
assert.verifySteps(['ok prom1']);
|
||||
|
||||
prom2.resolve();
|
||||
await testUtils.nextTick();
|
||||
|
||||
assert.verifySteps(['ok prom2', 'mutex unlocked (2)']);
|
||||
});
|
||||
|
||||
QUnit.test('mutex: error and getUnlockedDef', async function (assert) {
|
||||
const mutex = new Mutex();
|
||||
mutex.exec(async () => {
|
||||
await Promise.resolve();
|
||||
throw new Error("boom");
|
||||
}).catch(() => assert.step("prom rejected"));
|
||||
await testUtils.nextTick();
|
||||
assert.verifySteps(['prom rejected']);
|
||||
|
||||
mutex.getUnlockedDef().then(function () {
|
||||
assert.step('mutex unlocked');
|
||||
});
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['mutex unlocked']);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: simple', async function (assert) {
|
||||
assert.expect(5);
|
||||
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
var d1 = makeTestPromise();
|
||||
|
||||
d1.then(function () {
|
||||
assert.step("d1 resolved");
|
||||
});
|
||||
m.exec(function () { return d1; }).then(function (result) {
|
||||
assert.step("p1 done");
|
||||
assert.strictEqual(result, 'd1');
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(["d1 resolved","p1 done"]);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: d2 arrives after d1 resolution', async function (assert) {
|
||||
assert.expect(8);
|
||||
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
var d1 = makeTestPromiseWithAssert(assert, 'd1');
|
||||
|
||||
m.exec(function () { return d1; }).then(function () {
|
||||
assert.step("p1 resolved");
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok d1','p1 resolved']);
|
||||
|
||||
var d2 = makeTestPromiseWithAssert(assert, 'd2');
|
||||
m.exec(function () { return d2; }).then(function () {
|
||||
assert.step("p2 resolved");
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
d2.resolve('d2');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok d2','p2 resolved']);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: p1 does not return a deferred', async function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
|
||||
m.exec(function () { return 42; }).then(function () {
|
||||
assert.step("p1 resolved");
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['p1 resolved']);
|
||||
|
||||
var d2 = makeTestPromiseWithAssert(assert, 'd2');
|
||||
m.exec(function () { return d2; }).then(function () {
|
||||
assert.step("p2 resolved");
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
d2.resolve('d2');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['ok d2','p2 resolved']);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: p2 arrives before p1 resolution', async function (assert) {
|
||||
assert.expect(8);
|
||||
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
var d1 = makeTestPromiseWithAssert(assert, 'd1');
|
||||
|
||||
m.exec(function () { return d1; }).catch(function () {
|
||||
assert.step("p1 rejected");
|
||||
});
|
||||
assert.verifySteps([]);
|
||||
|
||||
var d2 = makeTestPromiseWithAssert(assert, 'd2');
|
||||
m.exec(function () { return d2; }).then(function () {
|
||||
assert.step("p2 resolved");
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['p1 rejected', 'ok d1']);
|
||||
|
||||
d2.resolve('d2');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['ok d2', 'p2 resolved']);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: 3 arrives before 2 initialization', async function (assert) {
|
||||
assert.expect(10);
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
|
||||
var d1 = makeTestPromiseWithAssert(assert, 'd1');
|
||||
var d3 = makeTestPromiseWithAssert(assert, 'd3');
|
||||
|
||||
m.exec(function () { return d1; }).catch(function () {
|
||||
assert.step('p1 rejected');
|
||||
});
|
||||
|
||||
m.exec(function () {
|
||||
assert.ok(false, "should not execute this function");
|
||||
}).catch(function () {
|
||||
assert.step('p2 rejected');
|
||||
});
|
||||
|
||||
m.exec(function () { return d3; }).then(function (result) {
|
||||
assert.strictEqual(result, 'd3');
|
||||
assert.step('p3 resolved');
|
||||
});
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['p1 rejected', 'p2 rejected']);
|
||||
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok d1']);
|
||||
|
||||
d3.resolve('d3');
|
||||
await testUtils.nextTick();
|
||||
|
||||
|
||||
assert.verifySteps(['ok d3','p3 resolved']);
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: 3 arrives after 2 initialization', async function (assert) {
|
||||
assert.expect(15);
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
|
||||
var d1 = makeTestPromiseWithAssert(assert, 'd1');
|
||||
var d2 = makeTestPromiseWithAssert(assert, 'd2');
|
||||
var d3 = makeTestPromiseWithAssert(assert, 'd3');
|
||||
|
||||
m.exec(function () {
|
||||
assert.step('execute d1');
|
||||
return d1;
|
||||
}).catch(function () {
|
||||
assert.step('p1 rejected');
|
||||
});
|
||||
|
||||
m.exec(function () {
|
||||
assert.step('execute d2');
|
||||
return d2;
|
||||
}).catch(function () {
|
||||
assert.step('p2 rejected');
|
||||
});
|
||||
|
||||
assert.verifySteps(['execute d1']);
|
||||
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['p1 rejected']);
|
||||
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextMicrotaskTick();
|
||||
|
||||
assert.verifySteps(['ok d1', 'execute d2']);
|
||||
|
||||
m.exec(function () {
|
||||
assert.step('execute d3');
|
||||
return d3;
|
||||
}).then(function () {
|
||||
assert.step('p3 resolved');
|
||||
});
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['p2 rejected']);
|
||||
|
||||
d2.resolve();
|
||||
await testUtils.nextMicrotaskTick();
|
||||
assert.verifySteps(['ok d2', 'execute d3']);
|
||||
|
||||
d3.resolve();
|
||||
await testUtils.nextTick();
|
||||
assert.verifySteps(['ok d3', 'p3 resolved']);
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('MutexedDropPrevious: 2 in then of 1 with 3', async function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
var m = new concurrency.MutexedDropPrevious();
|
||||
|
||||
var d1 = makeTestPromiseWithAssert(assert, 'd1');
|
||||
var d2 = makeTestPromiseWithAssert(assert, 'd2');
|
||||
var d3 = makeTestPromiseWithAssert(assert, 'd3');
|
||||
var p3;
|
||||
|
||||
m.exec(function () { return d1; })
|
||||
.catch(function () {
|
||||
assert.step('p1 rejected');
|
||||
p3 = m.exec(function () {
|
||||
return d3;
|
||||
}).then(function () {
|
||||
assert.step('p3 resolved');
|
||||
});
|
||||
return p3;
|
||||
});
|
||||
|
||||
await testUtils.nextTick();
|
||||
assert.verifySteps([]);
|
||||
|
||||
m.exec(function () {
|
||||
assert.ok(false, 'should not execute this function');
|
||||
return d2;
|
||||
}).catch(function () {
|
||||
assert.step('p2 rejected');
|
||||
});
|
||||
|
||||
await testUtils.nextTick();
|
||||
assert.verifySteps(['p1 rejected', 'p2 rejected']);
|
||||
|
||||
d1.resolve('d1');
|
||||
await testUtils.nextTick();
|
||||
|
||||
assert.verifySteps(['ok d1']);
|
||||
|
||||
d3.resolve('d3');
|
||||
await testUtils.nextTick();
|
||||
|
||||
assert.verifySteps(['ok d3', 'p3 resolved']);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -97,7 +97,6 @@ Odoo Web Editor widget.
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
|
||||
@@ -200,7 +200,6 @@ Featuring
|
||||
'web/static/src/legacy/js/core/ajax.js',
|
||||
'web/static/src/legacy/js/core/bus.js',
|
||||
'web/static/src/legacy/js/core/class.js',
|
||||
'web/static/src/legacy/js/core/concurrency.js',
|
||||
'web/static/src/legacy/js/core/dialog.js',
|
||||
'web/static/src/legacy/xml/dialog.xml',
|
||||
'web/static/src/legacy/js/core/dom.js',
|
||||
|
||||
Reference in New Issue
Block a user