37 lines
1.8 KiB
JavaScript
37 lines
1.8 KiB
JavaScript
// سقفِ کلیِ (نه روزانه/ماهانه) بیلبورد رایگان — طبق خواستهی صریحِ کاربر: ۲۰۰ تا
|
||
// در کلِ عمرِ حساب، مستقل از سهمیهی مشترکِ daily_free_request (که بین پروژه/بیلبورد/
|
||
// درخواست تقسیم میشه) و مستقل از سقفِ عمومیِ FREE_LIFETIME_CREATION_LIMIT
|
||
// (utils/freeCreationLimit.js)
|
||
const BILLBOARD_FREE_LIMIT = 200
|
||
|
||
function canUseFreeBillboard (user) {
|
||
const used = user?.free_billboard_count || 0
|
||
return used < BILLBOARD_FREE_LIMIT
|
||
}
|
||
|
||
/**
|
||
* نسخهی atomic — چک (free_billboard_count < سقف) و افزایش توی یه عملیاتِ واحدِ
|
||
* MongoDB (findOneAndUpdate با شرط توی query) انجام میشه، نه در دو مرحلهی جدا
|
||
* (قبلاً canUseFreeBillboard روی یه user از قبل fetchشده چک میشد و بعد جداگانه
|
||
* $inc میخورد) — وگرنه دو درخواستِ همزمان (دابلکلیکِ «تلاشِ دوباره» روی صفحهی
|
||
* پرداختِ ناموفق، که تا امروز گاردِ submitting هم نداشت) هر دو میتونستن همون
|
||
* user رو با free_billboard_count زیرِ سقف بخونن و هر دو از سقف رد بشن
|
||
*/
|
||
async function tryConsumeFreeBillboard (UserModel, userId) {
|
||
const updated = await UserModel.findOneAndUpdate(
|
||
{ _id: userId, free_billboard_count: { $lt: BILLBOARD_FREE_LIMIT } },
|
||
{ $inc: { free_billboard_count: 1 } },
|
||
{ new: true }
|
||
)
|
||
if (!updated) {
|
||
return { ok: false, message: `سقف ${BILLBOARD_FREE_LIMIT} بیلبورد رایگان به پایان رسیده است.` }
|
||
}
|
||
return { ok: true, user: updated }
|
||
}
|
||
|
||
module.exports = {
|
||
BILLBOARD_FREE_LIMIT,
|
||
canUseFreeBillboard,
|
||
tryConsumeFreeBillboard
|
||
}
|