What happened?
The recsExpire cron in src/inngest/functions/maintenance.ts expires stale
recommendations, but its query filters .eq('status', 'open') so it only ever
expires open recommendations. A recommendation in claimed status is never
expired, no matter how long ago its expires_at passed.
claimRecommendation in src/app/actions/recommendations.ts enforces a 3-claim
limit by counting every status = 'claimed' row for the user, with no expires_at
filter. So once a contributor claims 3 recommendations and abandons them, those
claims count against the limit forever claimRecommendation permanently returns
claim_limit, and the contributor can never claim new work again.
The expires_at window (7 days) is meant to auto-recover abandoned claims, but it
is only enforced for open recs, so it never fires for claimed ones.
Steps to Reproduce
- As a contributor, claim 3 recommendations (
claimRecommendation).
- Do not act on them. Wait until their
expires_at passes (or set it in the past).
- Let the hourly
recsExpire cron run.
- Try to claim a 4th recommendation.
Expected Behavior
the abandoned claims past expires_at are released/expired, freeing
the claim slots, so a new claim succeeds.
Actual: the claimed recs are untouched, still count toward the limit, and
claimRecommendation returns claim_limit permanently.
Where does this occur?
Other
Environment
Not environment-specific this is a logic gap in the recsExpire cron in
src/inngest/functions/maintenance.ts, reproducible on any OS / Node version.
No browser involved Inngest background job.
Screenshots / Logs
No error log this is a silent lifecycle gap, shown by the code itself.
recsExpire only expires open recommendations (src/inngest/functions/maintenance.ts):
await sb.from('recommendations')
.update({ status: 'expired' })
.lt('expires_at', now)
.eq('status', 'open') // claimed recs are never expired
.select('id');
But claimRecommendation counts every claimed row toward the limit, with no
expires_at filter (src/app/actions/recommendations.ts):
.eq('user_id', user.id)
.eq('status', 'claimed');
if ((claimedCount ?? 0) >= 3) return err('claim_limit', ...);
So a claimed rec past its expires_at is never released, keeps counting toward the
3-claim limit forever, and the contributor is permanently locked out of claiming
new work.
What happened?
The
recsExpirecron insrc/inngest/functions/maintenance.tsexpires stalerecommendations, but its query filters
.eq('status', 'open')so it only everexpires
openrecommendations. A recommendation inclaimedstatus is neverexpired, no matter how long ago its
expires_atpassed.claimRecommendationinsrc/app/actions/recommendations.tsenforces a 3-claimlimit by counting every
status = 'claimed'row for the user, with noexpires_atfilter. So once a contributor claims 3 recommendations and abandons them, those
claims count against the limit forever
claimRecommendationpermanently returnsclaim_limit, and the contributor can never claim new work again.The
expires_atwindow (7 days) is meant to auto-recover abandoned claims, but itis only enforced for
openrecs, so it never fires for claimed ones.Steps to Reproduce
claimRecommendation).expires_atpasses (or set it in the past).recsExpirecron run.Expected Behavior
the abandoned claims past
expires_atare released/expired, freeingthe claim slots, so a new claim succeeds.
Actual: the claimed recs are untouched, still count toward the limit, and
claimRecommendationreturnsclaim_limitpermanently.Where does this occur?
Other
Environment
Not environment-specific this is a logic gap in the recsExpire cron in
src/inngest/functions/maintenance.ts, reproducible on any OS / Node version.
No browser involved Inngest background job.
Screenshots / Logs
No error log this is a silent lifecycle gap, shown by the code itself.
recsExpire only expires
openrecommendations (src/inngest/functions/maintenance.ts):But claimRecommendation counts every claimed row toward the limit, with no
expires_at filter (src/app/actions/recommendations.ts):
So a claimed rec past its expires_at is never released, keeps counting toward the
3-claim limit forever, and the contributor is permanently locked out of claiming
new work.