feat: add CampaignApplicants index and campaign_applicants view function - #53
feat: add CampaignApplicants index and campaign_applicants view function#53EmeditWeb wants to merge 1 commit into
Conversation
Replace O(1) ApplicantCount counter with CampaignApplicants Vec<Address> to support listing all applicants for a campaign. - Add DataKey::CampaignApplicants(u64) storing Vec<Address> - Update add_campaign_applicant to push_back creator to the ordered list - Add campaign_applicants(campaign_id) view function returning Vec<Address> - Add TTL bump on both read and write for CampaignApplicants key - Guard against double-application via existing get_application check - Update has_campaign_applicants to check non-empty Vec - Add tests: 3 creators returned in order, empty list, double-apply guard Close Ads-Bazaar#8
JamesVictor-O
left a comment
There was a problem hiding this comment.
Thanks for picking up #8 — a campaign_applicants view function is a real gap, and the enumeration approach (mirroring SelectedCreators) is the right shape for it.
Requesting changes on the storage design, though: this PR replaces DataKey::ApplicantCount with DataKey::CampaignApplicants(Vec<Address>), which reverts #50 — merged three PRs ago specifically to fix #43 (add_campaign_applicant rewriting an ever-growing Vec<Address> on every single apply_to_campaign call). That issue explicitly laid out two acceptable resolutions:
- Replace the Vec with a counter (what #50 did)
- Or, if the ordered list is intentionally useful for something else (e.g. #8) — keep the Vec, but add a hard cap on total applications per campaign so growth is at least bounded
This PR takes the Vec back but doesn't add the cap from option 2, so it silently reintroduces #43's exact problem: every apply_to_campaign on a popular campaign gets progressively more expensive to write, unbounded. has_campaign_applicants also goes back to deserializing the whole list just to check non-emptiness, on every update_campaign_metadata lock check.
Could you add a cap — something like MAX_APPLICANTS_PER_CAMPAIGN, checked in add_campaign_applicant/apply_to_campaign, returning a dedicated error once exceeded (mirroring the existing max_creators / MaxCreatorsReached pattern for approved creators)? That satisfies both #8 and #43 as issue #43 itself anticipated, with a regression test for the cap alongside the enumeration tests you've already written.
Everything else here — the campaign_applicants shape, TTL-bump-on-read, and the new test coverage for ordering/empty-list — looks solid. This is the one thing blocking merge.
Summary
Replaces the O(1)
ApplicantCountcounter with aCampaignApplicantsVec<Address>index per campaign, and adds a newcampaign_applicants(campaign_id)view function so clients can list all applicants without relying on event logs alone.Changes
storage.rsDataKey::ApplicantCount(CampaignId)withDataKey::CampaignApplicants(CampaignId)storingVec<Address>add_campaign_applicantto push the creator onto the ordered listhas_campaign_applicantsto check for non-empty Vecget_campaign_applicantswith TTL bump on readlib.rscampaign_applicants(env, campaign_id) -> Vec<Address>view functionVecfromsoroban_sdktest.rscampaign_applicants_returns_all_applicants_in_order: 3 creators apply → returned in ordercampaign_applicants_empty_when_no_applicants: returns empty Vecdouble_apply_via_index: second apply returnsAlreadyAppliedand index has only 1 entrycampaign_applicants_lock_metadata: brief locks once applicant existsTesting
All 106 workspace tests pass (89 campaign-escrow + 17 dispute-resolution).
Close #8