distribution_bucket_picker.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #![warn(missing_docs)]
  2. use sp_std::cell::RefCell;
  3. use sp_std::collections::btree_set::BTreeSet;
  4. use sp_std::marker::PhantomData;
  5. use sp_std::vec::Vec;
  6. use crate::{DistributionBucketId, DynamicBagType, Module, Trait};
  7. pub(crate) use super::{RandomBucketIdIterator, SequentialBucketIdIterator};
  8. // Generates distribution bucket IDs to assign to a new dynamic bag.
  9. pub(crate) struct DistributionBucketPicker<T> {
  10. trait_marker: PhantomData<T>,
  11. }
  12. impl<T: Trait> DistributionBucketPicker<T> {
  13. // Get random distribution buckets from distribution bucket families using the dynamic bag
  14. // creation policy.
  15. pub(crate) fn pick_distribution_buckets(
  16. bag_type: DynamicBagType,
  17. ) -> BTreeSet<DistributionBucketId<T>> {
  18. let creation_policy = Module::<T>::get_dynamic_bag_creation_policy(bag_type);
  19. if creation_policy.no_distribution_buckets_required() {
  20. return BTreeSet::new();
  21. }
  22. // Distribution bucket IDs accumulator.
  23. let bucket_ids_cell = RefCell::new(BTreeSet::<T::DistributionBucketIndex>::new());
  24. creation_policy
  25. .families
  26. .iter()
  27. .filter_map(|(family_id, bucket_num)| {
  28. Module::<T>::ensure_distribution_bucket_family_exists(family_id)
  29. .ok()
  30. .map(|fam| (family_id, fam, bucket_num))
  31. })
  32. .map(|(family_id, family, bucket_num)| {
  33. RandomBucketIdIterator::<T, T::DistributionBucketIndex>::new(
  34. family.next_distribution_bucket_index,
  35. )
  36. .chain(
  37. SequentialBucketIdIterator::<T, T::DistributionBucketIndex>::new(
  38. family.next_distribution_bucket_index,
  39. ),
  40. )
  41. .filter(|bucket_idx| {
  42. let bucket_id = DistributionBucketId::<T> {
  43. distribution_bucket_family_id: *family_id,
  44. distribution_bucket_index: *bucket_idx,
  45. };
  46. Module::<T>::ensure_distribution_bucket_exists(&bucket_id)
  47. .ok()
  48. .map(|bucket| bucket.accepting_new_bags)
  49. .unwrap_or(false)
  50. })
  51. .filter(|bucket_idx| {
  52. let bucket_ids = bucket_ids_cell.borrow();
  53. // Skips the iteration on existing ID.
  54. !bucket_ids.contains(bucket_idx)
  55. })
  56. .map(|bucket_idx| DistributionBucketId::<T> {
  57. distribution_bucket_family_id: *family_id,
  58. distribution_bucket_index: bucket_idx,
  59. })
  60. .take(*bucket_num as usize)
  61. .collect::<Vec<_>>()
  62. // rename buckets
  63. })
  64. .flatten()
  65. .collect::<BTreeSet<_>>()
  66. }
  67. }