@@ -649,7 +649,7 @@ pub mod pallet {
649
649
impl < T : Config > Hooks < BlockNumberFor < T > > for Pallet < T > {
650
650
fn on_initialize ( _n : BlockNumberFor < T > ) -> Weight {
651
651
if let Some ( weight_limit) = T :: ServiceWeight :: get ( ) {
652
- Self :: service_queues ( weight_limit)
652
+ Self :: service_queues_impl ( weight_limit, ServiceQueuesContext :: OnInitialize )
653
653
} else {
654
654
Weight :: zero ( )
655
655
}
@@ -658,7 +658,10 @@ pub mod pallet {
658
658
fn on_idle ( _n : BlockNumberFor < T > , remaining_weight : Weight ) -> Weight {
659
659
if let Some ( weight_limit) = T :: IdleMaxServiceWeight :: get ( ) {
660
660
// Make use of the remaining weight to process enqueued messages.
661
- Self :: service_queues ( weight_limit. min ( remaining_weight) )
661
+ Self :: service_queues_impl (
662
+ weight_limit. min ( remaining_weight) ,
663
+ ServiceQueuesContext :: OnIdle ,
664
+ )
662
665
} else {
663
666
Weight :: zero ( )
664
667
}
@@ -777,6 +780,18 @@ enum MessageExecutionStatus {
777
780
StackLimitReached ,
778
781
}
779
782
783
+ /// The context to pass to [`Pallet::service_queues_impl`] through on_idle and on_initialize hooks
784
+ /// We don't want to throw the defensive message if called from on_idle hook
785
+ #[ derive( PartialEq ) ]
786
+ enum ServiceQueuesContext {
787
+ /// Context of on_idle hook.
788
+ OnIdle ,
789
+ /// Context of on_initialize hook.
790
+ OnInitialize ,
791
+ /// Context `service_queues` trait function.
792
+ ServiceQueues ,
793
+ }
794
+
780
795
impl < T : Config > Pallet < T > {
781
796
/// Knit `origin` into the ready ring right at the end.
782
797
///
@@ -1511,6 +1526,53 @@ impl<T: Config> Pallet<T> {
1511
1526
} ,
1512
1527
}
1513
1528
}
1529
+
1530
+ fn service_queues_impl ( weight_limit : Weight , context : ServiceQueuesContext ) -> Weight {
1531
+ let mut weight = WeightMeter :: with_limit ( weight_limit) ;
1532
+
1533
+ // Get the maximum weight that processing a single message may take:
1534
+ let max_weight = Self :: max_message_weight ( weight_limit) . unwrap_or_else ( || {
1535
+ if matches ! ( context, ServiceQueuesContext :: OnInitialize ) {
1536
+ defensive ! ( "Not enough weight to service a single message." ) ;
1537
+ }
1538
+ Weight :: zero ( )
1539
+ } ) ;
1540
+
1541
+ match with_service_mutex ( || {
1542
+ let mut next = match Self :: bump_service_head ( & mut weight) {
1543
+ Some ( h) => h,
1544
+ None => return weight. consumed ( ) ,
1545
+ } ;
1546
+ // The last queue that did not make any progress.
1547
+ // The loop aborts as soon as it arrives at this queue again without making any progress
1548
+ // on other queues in between.
1549
+ let mut last_no_progress = None ;
1550
+
1551
+ loop {
1552
+ let ( progressed, n) = Self :: service_queue ( next. clone ( ) , & mut weight, max_weight) ;
1553
+ next = match n {
1554
+ Some ( n) =>
1555
+ if !progressed {
1556
+ if last_no_progress == Some ( n. clone ( ) ) {
1557
+ break
1558
+ }
1559
+ if last_no_progress. is_none ( ) {
1560
+ last_no_progress = Some ( next. clone ( ) )
1561
+ }
1562
+ n
1563
+ } else {
1564
+ last_no_progress = None ;
1565
+ n
1566
+ } ,
1567
+ None => break ,
1568
+ }
1569
+ }
1570
+ weight. consumed ( )
1571
+ } ) {
1572
+ Err ( ( ) ) => weight. consumed ( ) ,
1573
+ Ok ( w) => w,
1574
+ }
1575
+ }
1514
1576
}
1515
1577
1516
1578
/// Run a closure that errors on re-entrance. Meant to be used by anything that services queues.
@@ -1580,48 +1642,7 @@ impl<T: Config> ServiceQueues for Pallet<T> {
1580
1642
type OverweightMessageAddress = ( MessageOriginOf < T > , PageIndex , T :: Size ) ;
1581
1643
1582
1644
fn service_queues ( weight_limit : Weight ) -> Weight {
1583
- let mut weight = WeightMeter :: with_limit ( weight_limit) ;
1584
-
1585
- // Get the maximum weight that processing a single message may take:
1586
- let max_weight = Self :: max_message_weight ( weight_limit) . unwrap_or_else ( || {
1587
- defensive ! ( "Not enough weight to service a single message." ) ;
1588
- Weight :: zero ( )
1589
- } ) ;
1590
-
1591
- match with_service_mutex ( || {
1592
- let mut next = match Self :: bump_service_head ( & mut weight) {
1593
- Some ( h) => h,
1594
- None => return weight. consumed ( ) ,
1595
- } ;
1596
- // The last queue that did not make any progress.
1597
- // The loop aborts as soon as it arrives at this queue again without making any progress
1598
- // on other queues in between.
1599
- let mut last_no_progress = None ;
1600
-
1601
- loop {
1602
- let ( progressed, n) = Self :: service_queue ( next. clone ( ) , & mut weight, max_weight) ;
1603
- next = match n {
1604
- Some ( n) =>
1605
- if !progressed {
1606
- if last_no_progress == Some ( n. clone ( ) ) {
1607
- break
1608
- }
1609
- if last_no_progress. is_none ( ) {
1610
- last_no_progress = Some ( next. clone ( ) )
1611
- }
1612
- n
1613
- } else {
1614
- last_no_progress = None ;
1615
- n
1616
- } ,
1617
- None => break ,
1618
- }
1619
- }
1620
- weight. consumed ( )
1621
- } ) {
1622
- Err ( ( ) ) => weight. consumed ( ) ,
1623
- Ok ( w) => w,
1624
- }
1645
+ Self :: service_queues_impl ( weight_limit, ServiceQueuesContext :: ServiceQueues )
1625
1646
}
1626
1647
1627
1648
/// Execute a single overweight message.
0 commit comments