@@ -1893,6 +1893,14 @@ var Component = class {
18931893 off ( hookName , callback ) {
18941894 this . hooks . unregister ( hookName , callback ) ;
18951895 }
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+ }
18961904 set ( model , value , reRender = false , debounce = false ) {
18971905 const promise = this . nextRequestPromise ;
18981906 const modelName = normalizeModelName ( model ) ;
@@ -2584,52 +2592,195 @@ var PageUnloadingPlugin_default = class {
25842592
25852593// src/PollingDirector.ts
25862594var PollingDirector_default = class {
2595+ // Lock system for active polling
25872596 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 ( ) ;
25902606 this . component = component ;
25912607 }
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 ) ;
25962615 }
2616+ this . initiatePoll ( actionName , duration ) ;
25972617 }
2618+ /**
2619+ * Start All Pollings In PollingStates Map Entires
2620+ */
25982621 startAllPolling ( ) {
2599- if ( this . isPollingActive ) {
2600- return ;
2622+ for ( const [ actionName ] of this . pollingConfigs . entries ( ) ) {
2623+ this . start ( actionName ) ;
26012624 }
2602- this . isPollingActive = true ;
2603- this . polls . forEach ( ( { actionName, duration } ) => {
2604- this . initiatePoll ( actionName , duration ) ;
2605- } ) ;
26062625 }
2626+ /**
2627+ * Stop All Pollings In PollingStates Map Entires
2628+ */
26072629 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+ }
26122633 }
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+ }
26172647 }
26182648 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 ) ) ;
26312696 } , 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" ;
26332784 }
26342785} ;
26352786
@@ -2639,6 +2790,7 @@ var PollingPlugin_default = class {
26392790 this . element = component . element ;
26402791 this . pollingDirector = new PollingDirector_default ( component ) ;
26412792 this . initializePolling ( ) ;
2793+ component . pollingDirector = this . pollingDirector ;
26422794 component . on ( "connect" , ( ) => {
26432795 this . pollingDirector . startAllPolling ( ) ;
26442796 } ) ;
@@ -2649,11 +2801,11 @@ var PollingPlugin_default = class {
26492801 this . initializePolling ( ) ;
26502802 } ) ;
26512803 }
2652- addPoll ( actionName , duration ) {
2653- this . pollingDirector . addPoll ( actionName , duration ) ;
2804+ addPoll ( actionName , duration , limit ) {
2805+ this . pollingDirector . addPoll ( actionName , duration , limit ) ;
26542806 }
26552807 clearPolling ( ) {
2656- this . pollingDirector . clearPolling ( ) ;
2808+ this . pollingDirector . clearAllPolling ( true ) ;
26572809 }
26582810 initializePolling ( ) {
26592811 this . clearPolling ( ) ;
@@ -2664,18 +2816,26 @@ var PollingPlugin_default = class {
26642816 const directives = parseDirectives ( rawPollConfig || "$render" ) ;
26652817 directives . forEach ( ( directive ) => {
26662818 let duration = 2e3 ;
2819+ let limit = 0 ;
26672820 directive . modifiers . forEach ( ( modifier ) => {
26682821 switch ( modifier . name ) {
26692822 case "delay" :
26702823 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 ;
26722832 }
26732833 break ;
26742834 default :
26752835 console . warn ( `Unknown modifier "${ modifier . name } " in data-poll "${ rawPollConfig } ".` ) ;
26762836 }
26772837 } ) ;
2678- this . addPoll ( directive . action , duration ) ;
2838+ this . addPoll ( directive . action , duration , limit ) ;
26792839 } ) ;
26802840 }
26812841} ;
0 commit comments