fix(authorization): fix race condition in reward distribution calculation
When calculating reward distribution for community/province/city benefits, the totalTeamPlantingCount was being read after referral-service had already updated it with the current planting. This caused incorrect distribution where benefits were given to the community holder before they completed their assessment target. Fix: Subtract treeCount from rawTeamCount to restore the "before planting" team count, ensuring correct assessment calculation. Affected methods: - getCommunityRewardDistribution - getProvinceTeamRewardDistribution - getCityTeamRewardDistribution 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fc55afb7b9
commit
f94e7283d5
|
|
@ -859,12 +859,20 @@ export class AuthorizationApplicationService {
|
||||||
const communityStats = await this.statsRepository.findByAccountSequence(
|
const communityStats = await this.statsRepository.findByAccountSequence(
|
||||||
nearestCommunity.userId.accountSequence,
|
nearestCommunity.userId.accountSequence,
|
||||||
)
|
)
|
||||||
const currentTeamCount = communityStats?.totalTeamPlantingCount ?? 0
|
const rawTeamCount = communityStats?.totalTeamPlantingCount ?? 0
|
||||||
|
|
||||||
|
// 重要:由于 referral-service 和 reward-service 都消费同一个 Kafka 事件,
|
||||||
|
// 存在竞态条件,此时查询到的 totalTeamPlantingCount 可能已经包含了本次认种。
|
||||||
|
// 因此需要减去本次认种数量来还原"认种前"的团队数。
|
||||||
|
// 注意:如果 referral-service 还没处理完,rawTeamCount 可能还是旧值,
|
||||||
|
// 此时 currentTeamCount 可能为负数,需要取 max(0, ...)
|
||||||
|
const currentTeamCount = Math.max(0, rawTeamCount - treeCount)
|
||||||
const initialTarget = nearestCommunity.getInitialTarget() // 社区初始考核目标:10棵
|
const initialTarget = nearestCommunity.getInitialTarget() // 社区初始考核目标:10棵
|
||||||
|
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`[getCommunityRewardDistribution] Community ${nearestCommunity.userId.accountSequence} ` +
|
`[getCommunityRewardDistribution] Community ${nearestCommunity.userId.accountSequence} ` +
|
||||||
`benefitActive=false, currentTeamCount=${currentTeamCount}, initialTarget=${initialTarget}`,
|
`benefitActive=false, rawTeamCount=${rawTeamCount}, treeCount=${treeCount}, ` +
|
||||||
|
`currentTeamCount(before)=${currentTeamCount}, initialTarget=${initialTarget}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
// 6. 查找上级社区(用于接收考核前的权益)
|
// 6. 查找上级社区(用于接收考核前的权益)
|
||||||
|
|
@ -1023,9 +1031,15 @@ export class AuthorizationApplicationService {
|
||||||
|
|
||||||
// 5. 权益未激活,计算考核分配
|
// 5. 权益未激活,计算考核分配
|
||||||
const stats = await this.statsRepository.findByAccountSequence(nearestAuthProvince.userId.accountSequence)
|
const stats = await this.statsRepository.findByAccountSequence(nearestAuthProvince.userId.accountSequence)
|
||||||
const currentTeamCount = stats?.totalTeamPlantingCount ?? 0
|
const rawTeamCount = stats?.totalTeamPlantingCount ?? 0
|
||||||
|
// 修复竞态条件:减去本次认种数量来还原"认种前"的团队数
|
||||||
|
const currentTeamCount = Math.max(0, rawTeamCount - treeCount)
|
||||||
const initialTarget = nearestAuthProvince.getInitialTarget() // 500棵
|
const initialTarget = nearestAuthProvince.getInitialTarget() // 500棵
|
||||||
|
|
||||||
|
this.logger.debug(
|
||||||
|
`[getProvinceTeamRewardDistribution] rawTeamCount=${rawTeamCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`,
|
||||||
|
)
|
||||||
|
|
||||||
// 6. 查找上级(用于接收考核前的权益)
|
// 6. 查找上级(用于接收考核前的权益)
|
||||||
let parentAccountSequence: number = HEADQUARTERS_ACCOUNT_SEQUENCE
|
let parentAccountSequence: number = HEADQUARTERS_ACCOUNT_SEQUENCE
|
||||||
let parentReason = '上级为总部社区'
|
let parentReason = '上级为总部社区'
|
||||||
|
|
@ -1227,9 +1241,15 @@ export class AuthorizationApplicationService {
|
||||||
|
|
||||||
// 5. 权益未激活,计算考核分配
|
// 5. 权益未激活,计算考核分配
|
||||||
const stats = await this.statsRepository.findByAccountSequence(nearestAuthCity.userId.accountSequence)
|
const stats = await this.statsRepository.findByAccountSequence(nearestAuthCity.userId.accountSequence)
|
||||||
const currentTeamCount = stats?.totalTeamPlantingCount ?? 0
|
const rawTeamCount = stats?.totalTeamPlantingCount ?? 0
|
||||||
|
// 修复竞态条件:减去本次认种数量来还原"认种前"的团队数
|
||||||
|
const currentTeamCount = Math.max(0, rawTeamCount - treeCount)
|
||||||
const initialTarget = nearestAuthCity.getInitialTarget() // 100棵
|
const initialTarget = nearestAuthCity.getInitialTarget() // 100棵
|
||||||
|
|
||||||
|
this.logger.debug(
|
||||||
|
`[getCityTeamRewardDistribution] rawTeamCount=${rawTeamCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`,
|
||||||
|
)
|
||||||
|
|
||||||
// 6. 查找上级
|
// 6. 查找上级
|
||||||
let parentAccountSequence: number = HEADQUARTERS_ACCOUNT_SEQUENCE
|
let parentAccountSequence: number = HEADQUARTERS_ACCOUNT_SEQUENCE
|
||||||
let parentReason = '上级为总部社区'
|
let parentReason = '上级为总部社区'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue