@@ -1893,6 +1893,14 @@ var Component = class {
1893
1893
off ( hookName , callback ) {
1894
1894
this . hooks . unregister ( hookName , callback ) ;
1895
1895
}
1896
+ /**
1897
+ * Trigger Polling Hook Events In PollingDirector
1898
+ * @param event
1899
+ * @param context
1900
+ */
1901
+ triggerPollHook ( event , context ) {
1902
+ this . hooks . triggerHook ( event , context ) ;
1903
+ }
1896
1904
set ( model , value , reRender = false , debounce = false ) {
1897
1905
const promise = this . nextRequestPromise ;
1898
1906
const modelName = normalizeModelName ( model ) ;
@@ -2584,52 +2592,195 @@ var PageUnloadingPlugin_default = class {
2584
2592
2585
2593
// src/PollingDirector.ts
2586
2594
var PollingDirector_default = class {
2595
+ // Lock system for active polling
2587
2596
constructor ( component ) {
2588
- this . isPollingActive = true ;
2589
- this . pollingIntervals = [ ] ;
2597
+ this . pollingIntervals = /* @__PURE__ */ new Map ( ) ;
2598
+ // actionName → intervalId
2599
+ this . pollingCounts = /* @__PURE__ */ new Map ( ) ;
2600
+ // actionName → current count
2601
+ this . pollingConfigs = /* @__PURE__ */ new Map ( ) ;
2602
+ // All Polling's Map
2603
+ this . pollingStates = /* @__PURE__ */ new Map ( ) ;
2604
+ // All Polling's States Map
2605
+ this . isPollingRunnig = /* @__PURE__ */ new Map ( ) ;
2590
2606
this . component = component ;
2591
2607
}
2592
- addPoll ( actionName , duration ) {
2593
- this . polls . push ( { actionName, duration } ) ;
2594
- if ( this . isPollingActive ) {
2595
- this . initiatePoll ( actionName , duration ) ;
2608
+ addPoll ( actionName , duration , limit = 0 ) {
2609
+ this . pollingConfigs . set ( actionName , { duration, limit } ) ;
2610
+ if ( ! this . pollingStates . has ( actionName ) ) {
2611
+ this . pollingStates . set ( actionName , "active" ) ;
2612
+ }
2613
+ if ( ! this . pollingCounts . has ( actionName ) ) {
2614
+ this . pollingCounts . set ( actionName , 0 ) ;
2596
2615
}
2616
+ this . initiatePoll ( actionName , duration ) ;
2597
2617
}
2618
+ /**
2619
+ * Start All Pollings In PollingStates Map Entires
2620
+ */
2598
2621
startAllPolling ( ) {
2599
- if ( this . isPollingActive ) {
2600
- return ;
2622
+ for ( const [ actionName ] of this . pollingConfigs . entries ( ) ) {
2623
+ this . start ( actionName ) ;
2601
2624
}
2602
- this . isPollingActive = true ;
2603
- this . polls . forEach ( ( { actionName, duration } ) => {
2604
- this . initiatePoll ( actionName , duration ) ;
2605
- } ) ;
2606
2625
}
2626
+ /**
2627
+ * Stop All Pollings In PollingStates Map Entires
2628
+ */
2607
2629
stopAllPolling ( ) {
2608
- this . isPollingActive = false ;
2609
- this . pollingIntervals . forEach ( ( interval ) => {
2610
- clearInterval ( interval ) ;
2611
- } ) ;
2630
+ for ( const [ actionName ] of this . pollingConfigs . entries ( ) ) {
2631
+ this . stop ( actionName ) ;
2632
+ }
2612
2633
}
2613
- clearPolling ( ) {
2614
- this . stopAllPolling ( ) ;
2615
- this . polls = [ ] ;
2616
- this . startAllPolling ( ) ;
2634
+ /**
2635
+ * Stop All Pollings and Clear All Pollings Data
2636
+ */
2637
+ clearAllPolling ( soft = false ) {
2638
+ for ( const intervalId of this . pollingIntervals . values ( ) ) {
2639
+ clearTimeout ( intervalId ) ;
2640
+ }
2641
+ this . pollingIntervals . clear ( ) ;
2642
+ this . pollingConfigs . clear ( ) ;
2643
+ if ( ! soft ) {
2644
+ this . pollingStates . clear ( ) ;
2645
+ this . pollingCounts . clear ( ) ;
2646
+ }
2617
2647
}
2618
2648
initiatePoll ( actionName , duration ) {
2619
- let callback ;
2620
- if ( actionName === "$render" ) {
2621
- callback = ( ) => {
2622
- this . component . render ( ) ;
2623
- } ;
2624
- } else {
2625
- callback = ( ) => {
2626
- this . component . action ( actionName , { } , 0 ) ;
2627
- } ;
2628
- }
2629
- const timer = window . setInterval ( ( ) => {
2630
- callback ( ) ;
2649
+ this . isPollingRunnig . set ( actionName , false ) ;
2650
+ const callback = async ( ) => {
2651
+ if ( this . isPollingRunnig . get ( actionName ) ) return ;
2652
+ this . isPollingRunnig . set ( actionName , true ) ;
2653
+ const limit = this . pollingConfigs . get ( actionName ) ?. limit ?? 0 ;
2654
+ const currentCount = this . pollingCounts . get ( actionName ) ?? 0 ;
2655
+ if ( currentCount === 0 ) {
2656
+ this . component . triggerPollHook ( "poll:started" , { actionName, limit } ) ;
2657
+ }
2658
+ this . pollingCounts . set ( actionName , currentCount + 1 ) ;
2659
+ if ( limit > 0 && currentCount >= limit ) {
2660
+ this . stop ( actionName ) ;
2661
+ return ;
2662
+ }
2663
+ try {
2664
+ if ( actionName === "$render" ) {
2665
+ await this . component . render ( ) ;
2666
+ } else {
2667
+ const response = await this . component . action ( actionName , { } , 0 ) ;
2668
+ if ( response ?. response ?. status === 500 ) {
2669
+ this . stop ( actionName ) ;
2670
+ throw new Error ( this . decodeErrorMessage ( await response . getBody ( ) ) ) ;
2671
+ }
2672
+ }
2673
+ this . component . triggerPollHook ( "poll:running" , {
2674
+ actionName,
2675
+ count : currentCount + 1 ,
2676
+ limit
2677
+ } ) ;
2678
+ } catch ( error ) {
2679
+ this . component . triggerPollHook ( "poll:error" , {
2680
+ actionName,
2681
+ finalCount : currentCount + 1 ,
2682
+ limit,
2683
+ errorMessage : error instanceof Error ? error . message : String ( error )
2684
+ } ) ;
2685
+ } finally {
2686
+ this . isPollingRunnig . set ( actionName , false ) ;
2687
+ }
2688
+ } ;
2689
+ const intervalId = window . setInterval ( ( ) => {
2690
+ if ( this . pollingStates . get ( actionName ) !== "active" ) {
2691
+ clearInterval ( intervalId ) ;
2692
+ this . pollingIntervals . delete ( actionName ) ;
2693
+ return ;
2694
+ }
2695
+ callback ( ) . catch ( ( e ) => console . error ( e ) ) ;
2631
2696
} , duration ) ;
2632
- this . pollingIntervals . push ( timer ) ;
2697
+ this . pollingIntervals . set ( actionName , intervalId ) ;
2698
+ }
2699
+ /**
2700
+ * Pause Polling by action Name
2701
+ * Pause if polling's status is active only
2702
+ */
2703
+ pause ( actionName = "$render" ) {
2704
+ if ( this . pollingStates . get ( actionName ) !== "active" ) return ;
2705
+ const intervalId = this . pollingIntervals . get ( actionName ) ;
2706
+ if ( intervalId !== void 0 ) {
2707
+ clearInterval ( intervalId ) ;
2708
+ this . pollingIntervals . delete ( actionName ) ;
2709
+ }
2710
+ this . pollingStates . set ( actionName , "paused" ) ;
2711
+ const count = this . pollingCounts . get ( actionName ) ?? 0 ;
2712
+ const limit = this . pollingConfigs . get ( actionName ) ?. limit ?? 0 ;
2713
+ this . component . triggerPollHook ( "poll:paused" , { actionName, count, limit } ) ;
2714
+ }
2715
+ /**
2716
+ * Resume Polling by action Name
2717
+ * Resume if polling's status is paused only
2718
+ */
2719
+ resume ( actionName = "$render" ) {
2720
+ const config = this . pollingConfigs . get ( actionName ) ;
2721
+ if ( this . pollingStates . get ( actionName ) !== "paused" || ! config ) {
2722
+ return ;
2723
+ }
2724
+ this . pollingStates . set ( actionName , "active" ) ;
2725
+ this . initiatePoll ( actionName , config . duration ) ;
2726
+ }
2727
+ /**
2728
+ * Stop Polling by action Name
2729
+ * Stop if polling's status is active or paused
2730
+ */
2731
+ stop ( actionName = "$render" ) {
2732
+ const state = this . pollingStates . get ( actionName ) ;
2733
+ if ( state !== "active" && state !== "paused" ) {
2734
+ return ;
2735
+ }
2736
+ const intervalId = this . pollingIntervals . get ( actionName ) ;
2737
+ if ( intervalId !== void 0 ) {
2738
+ clearInterval ( intervalId ) ;
2739
+ this . pollingIntervals . delete ( actionName ) ;
2740
+ }
2741
+ const currentCount = this . pollingCounts . get ( actionName ) ?? 1 ;
2742
+ const limit = this . pollingConfigs . get ( actionName ) ?. limit ?? 0 ;
2743
+ this . component . triggerPollHook ( "poll:stopped" , {
2744
+ actionName,
2745
+ finalCount : currentCount ,
2746
+ limit
2747
+ } ) ;
2748
+ this . pollingCounts . delete ( actionName ) ;
2749
+ this . pollingStates . set ( actionName , "stopped" ) ;
2750
+ }
2751
+ /**
2752
+ * Start Polling by action Name
2753
+ * Start if polling's status is stopped only
2754
+ */
2755
+ start ( actionName = "$render" ) {
2756
+ const config = this . pollingConfigs . get ( actionName ) ;
2757
+ if ( ! config || this . pollingStates . get ( actionName ) !== "stopped" ) return ;
2758
+ this . clearForAction ( actionName ) ;
2759
+ this . pollingCounts . set ( actionName , 0 ) ;
2760
+ this . pollingStates . set ( actionName , "active" ) ;
2761
+ this . initiatePoll ( actionName , config . duration ) ;
2762
+ }
2763
+ /**
2764
+ * Clear Polling Count and Interval data by action Name
2765
+ */
2766
+ clearForAction ( actionName = "$render" ) {
2767
+ this . pollingCounts . delete ( actionName ) ;
2768
+ const intervalId = this . pollingIntervals . get ( actionName ) ;
2769
+ if ( intervalId !== void 0 ) {
2770
+ clearInterval ( intervalId ) ;
2771
+ this . pollingIntervals . delete ( actionName ) ;
2772
+ }
2773
+ }
2774
+ /**
2775
+ * Decode Error Message
2776
+ */
2777
+ decodeErrorMessage ( errorMessage ) {
2778
+ errorMessage = errorMessage . split ( "<!--" ) [ 1 ] ?. split ( "-->" ) [ 0 ] ?. trim ( ) ;
2779
+ if ( errorMessage ) {
2780
+ const decoded = errorMessage . replace ( / & q u o t ; / g, '"' ) . replace ( / & # 0 3 9 ; / g, "'" ) . replace ( / & l t ; / g, "<" ) . replace ( / & g t ; / g, ">" ) . replace ( / & a m p ; / g, "&" ) ;
2781
+ return `Poll\xB7error:\xB7${ decoded } ` ;
2782
+ }
2783
+ return "Poll error: 500 Internal Server Error" ;
2633
2784
}
2634
2785
} ;
2635
2786
@@ -2639,6 +2790,7 @@ var PollingPlugin_default = class {
2639
2790
this . element = component . element ;
2640
2791
this . pollingDirector = new PollingDirector_default ( component ) ;
2641
2792
this . initializePolling ( ) ;
2793
+ component . pollingDirector = this . pollingDirector ;
2642
2794
component . on ( "connect" , ( ) => {
2643
2795
this . pollingDirector . startAllPolling ( ) ;
2644
2796
} ) ;
@@ -2649,11 +2801,11 @@ var PollingPlugin_default = class {
2649
2801
this . initializePolling ( ) ;
2650
2802
} ) ;
2651
2803
}
2652
- addPoll ( actionName , duration ) {
2653
- this . pollingDirector . addPoll ( actionName , duration ) ;
2804
+ addPoll ( actionName , duration , limit ) {
2805
+ this . pollingDirector . addPoll ( actionName , duration , limit ) ;
2654
2806
}
2655
2807
clearPolling ( ) {
2656
- this . pollingDirector . clearPolling ( ) ;
2808
+ this . pollingDirector . clearAllPolling ( true ) ;
2657
2809
}
2658
2810
initializePolling ( ) {
2659
2811
this . clearPolling ( ) ;
@@ -2664,18 +2816,26 @@ var PollingPlugin_default = class {
2664
2816
const directives = parseDirectives ( rawPollConfig || "$render" ) ;
2665
2817
directives . forEach ( ( directive ) => {
2666
2818
let duration = 2e3 ;
2819
+ let limit = 0 ;
2667
2820
directive . modifiers . forEach ( ( modifier ) => {
2668
2821
switch ( modifier . name ) {
2669
2822
case "delay" :
2670
2823
if ( modifier . value ) {
2671
- duration = Number . parseInt ( modifier . value ) ;
2824
+ const parsed = Number . parseInt ( modifier . value ) ;
2825
+ duration = Number . isNaN ( parsed ) || parsed <= 0 ? 2e3 : parsed ;
2826
+ }
2827
+ break ;
2828
+ case "limit" :
2829
+ if ( modifier . value ) {
2830
+ const parsed = Number . parseInt ( modifier . value ) ;
2831
+ limit = Number . isNaN ( parsed ) || parsed <= 0 ? 1 : parsed ;
2672
2832
}
2673
2833
break ;
2674
2834
default :
2675
2835
console . warn ( `Unknown modifier "${ modifier . name } " in data-poll "${ rawPollConfig } ".` ) ;
2676
2836
}
2677
2837
} ) ;
2678
- this . addPoll ( directive . action , duration ) ;
2838
+ this . addPoll ( directive . action , duration , limit ) ;
2679
2839
} ) ;
2680
2840
}
2681
2841
} ;
0 commit comments