@@ -89,7 +89,7 @@ export abstract class MetadataTransfer<
8989
9090 /**
9191 * Poll for the status of the metadata transfer request.
92- * Default frequency is 100 ms .
92+ * Default frequency is 1000ms minimum, scaling with deploy size (zip bytes or component count) .
9393 * Default timeout is 60 minutes.
9494 *
9595 * @param options Polling options; frequency, timeout, polling function.
@@ -98,7 +98,7 @@ export abstract class MetadataTransfer<
9898 public async pollStatus ( options ?: Partial < PollingClient . Options > ) : Promise < Result > ;
9999 /**
100100 * Poll for the status of the metadata transfer request.
101- * Default frequency is based on the number of SourceComponents, n, in the transfer, it ranges from 100ms -> n
101+ * Default frequency is 1000ms minimum, scaling with deploy size (zip bytes or component count, capped at 10s).
102102 * Default timeout is 60 minutes.
103103 *
104104 * @param frequency Polling frequency in milliseconds.
@@ -110,7 +110,12 @@ export abstract class MetadataTransfer<
110110 frequencyOrOptions ?: number | Partial < PollingClient . Options > ,
111111 timeout ?: number
112112 ) : Promise < Result | undefined > {
113- const normalizedOptions = normalizePollingInputs ( frequencyOrOptions , timeout , sizeOfComponentSet ( this . components ) ) ;
113+ const normalizedOptions = normalizePollingInputs (
114+ frequencyOrOptions ,
115+ timeout ,
116+ sizeOfComponentSet ( this . components ) ,
117+ this . getZipSize ( )
118+ ) ;
114119 // Initialize error retry tracking
115120 this . consecutiveErrorRetries = 0 ;
116121 this . errorRetryLimit = calculateErrorRetryLimit ( this . logger ) ;
@@ -204,6 +209,11 @@ export abstract class MetadataTransfer<
204209 this . event . on ( 'error' , subscriber ) ;
205210 }
206211
212+ // eslint-disable-next-line class-methods-use-this
213+ protected getZipSize ( ) : number | undefined {
214+ return undefined ;
215+ }
216+
207217 protected async maybeSaveTempDirectory ( target : SfdxFileFormat , cs ?: ComponentSet ) : Promise < void > {
208218 if ( this . mdapiTempDir ) {
209219 await Lifecycle . getInstance ( ) . emitWarning (
@@ -367,10 +377,11 @@ const getConnectionNoHigherThanOrgAllows = async (conn: Connection, requestedVer
367377export const normalizePollingInputs = (
368378 frequencyOrOptions ?: number | Partial < PollingClient . Options > ,
369379 timeout ?: number ,
370- componentSetSize = 0
380+ componentSetSize = 0 ,
381+ zipSize ?: number
371382) : Pick < PollingClient . Options , 'frequency' | 'timeout' > => {
372383 let pollingOptions : Pick < PollingClient . Options , 'frequency' | 'timeout' > = {
373- frequency : Duration . milliseconds ( calculatePollingFrequency ( componentSetSize ) ) ,
384+ frequency : Duration . milliseconds ( calculatePollingFrequency ( componentSetSize , zipSize ) ) ,
374385 timeout : Duration . minutes ( 60 ) ,
375386 } ;
376387 if ( isNumber ( frequencyOrOptions ) ) {
@@ -383,7 +394,7 @@ export const normalizePollingInputs = (
383394 }
384395 // from the overloaded methods, there's a possibility frequency/timeout isn't set
385396 // guarantee frequency and timeout are set
386- pollingOptions . frequency ??= Duration . milliseconds ( calculatePollingFrequency ( componentSetSize ) ) ;
397+ pollingOptions . frequency ??= Duration . milliseconds ( calculatePollingFrequency ( componentSetSize , zipSize ) ) ;
387398 pollingOptions . timeout ??= Duration . minutes ( 60 ) ;
388399
389400 return pollingOptions ;
@@ -392,21 +403,25 @@ export const normalizePollingInputs = (
392403/** yeah, there's a size property on CS. But we want the actual number of source components */
393404const sizeOfComponentSet = ( cs ?: ComponentSet ) : number => cs ?. getSourceComponents ( ) . toArray ( ) . length ?? 0 ;
394405
395- /** based on the size of the components, pick a reasonable polling frequency */
396- export const calculatePollingFrequency = ( size : number ) : number => {
397- if ( size === 0 ) {
398- // no component set size is possible for retrieve
399- return 1000 ;
400- } else if ( size <= 10 ) {
401- return 100 ;
402- } else if ( size <= 50 ) {
403- return 250 ;
404- } else if ( size <= 100 ) {
405- return 500 ;
406- } else if ( size <= 1000 ) {
406+ /** based on the size of the deploy (zip bytes for large deploys, component count for small ones), pick a reasonable polling frequency */
407+ export const calculatePollingFrequency = ( componentCount : number , zipSize ?: number ) : number => {
408+ // Use zip size only for large payloads where component count alone underestimates deploy time
409+ if ( zipSize !== undefined && zipSize > 1_000_000 ) {
410+ const ONE_MB = 1_000_000 ;
411+ if ( zipSize <= 5 * ONE_MB ) {
412+ return 2000 ;
413+ } else if ( zipSize <= 15 * ONE_MB ) {
414+ return 5000 ;
415+ } else {
416+ // large deploys (15MB+ up to 39MB limit) — poll every 10s
417+ return 10_000 ;
418+ }
419+ }
420+
421+ if ( componentCount <= 1000 ) {
407422 return 1000 ;
408423 } else {
409- return size ;
424+ return Math . min ( componentCount , 10_000 ) ;
410425 }
411426} ;
412427
0 commit comments