@@ -9,7 +9,7 @@ import * as path from 'path';
9
9
import * as fs from 'fs' ;
10
10
import { retryDecorator , NotRetryableError } from 'ts-retry-promise' ;
11
11
import { ConfigFile , Logger , Org , Messages , Lifecycle , SfError } from '@salesforce/core' ;
12
- import { Dictionary , Optional } from '@salesforce/ts-types' ;
12
+ import { Dictionary , Optional , definiteEntriesOf } from '@salesforce/ts-types' ;
13
13
import { env , Duration } from '@salesforce/kit' ;
14
14
import { ChangeResult , RemoteChangeElement , MemberRevision , SourceMember , RemoteSyncInput } from './types' ;
15
15
import { getMetadataKeyFromFileResponse , mappingsForSourceMemberTypesToMetadataType } from './metadataKeys' ;
@@ -124,13 +124,7 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
124
124
}
125
125
return path . isAbsolute ( fileToDelete ) ? fileToDelete : path . join ( process . cwd ( ) , fileToDelete ) ;
126
126
}
127
- private static convertRevisionToChange ( memberKey : string , memberRevision : MemberRevision ) : RemoteChangeElement {
128
- return {
129
- type : memberRevision . memberType ,
130
- name : memberKey . replace ( `${ memberRevision . memberType } __` , '' ) ,
131
- deleted : memberRevision . isNameObsolete ,
132
- } ;
133
- }
127
+
134
128
/**
135
129
* Initializes the service with existing remote source tracking data, or sets
136
130
* the state to begin source tracking of metadata changes in the org.
@@ -225,7 +219,7 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
225
219
public getTrackedElement ( key : string ) : RemoteChangeElement | undefined {
226
220
const memberRevision = this . getSourceMembers ( ) [ key ] ;
227
221
if ( memberRevision ) {
228
- return RemoteSourceTrackingService . convertRevisionToChange ( key , memberRevision ) ;
222
+ return convertRevisionToChange ( key , memberRevision ) ;
229
223
}
230
224
}
231
225
@@ -337,21 +331,15 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
337
331
338
332
// Look for any changed that haven't been synced. I.e, the lastRetrievedFromServer
339
333
// does not match the serverRevisionCounter.
340
- const trackedRevisions = this . getSourceMembers ( ) ;
341
- const returnElements : RemoteChangeElement [ ] = [ ] ;
342
-
343
- for ( const key of Object . keys ( trackedRevisions ) ) {
344
- const member = trackedRevisions [ key ] ;
345
- if ( member && member . serverRevisionCounter !== member . lastRetrievedFromServer ) {
346
- returnElements . push ( RemoteSourceTrackingService . convertRevisionToChange ( key , member ) ) ;
347
- }
348
- }
334
+ const returnElements = definiteEntriesOf ( this . getSourceMembers ( ) )
335
+ . filter ( ( [ , member ] ) => member . serverRevisionCounter !== member . lastRetrievedFromServer )
336
+ . map ( ( [ key , member ] ) => convertRevisionToChange ( key , member ) ) ;
349
337
350
- if ( returnElements . length ) {
351
- this . logger . debug ( `Found ${ returnElements . length } elements not synced with org` ) ;
352
- } else {
353
- this . logger . debug ( 'Remote source tracking is up to date' ) ;
354
- }
338
+ this . logger . debug (
339
+ returnElements . length
340
+ ? `Found ${ returnElements . length } elements not synced with org`
341
+ : 'Remote source tracking is up to date'
342
+ ) ;
355
343
356
344
return returnElements ;
357
345
}
@@ -370,19 +358,21 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
370
358
return ;
371
359
}
372
360
373
- const outstandingSourceMembers = calculateExpectedSourceMembers ( expectedMembers ) ;
374
- if ( expectedMembers . length === 0 || outstandingSourceMembers . size === 0 ) {
375
- // Don't bother polling if we're not matching SourceMembers
361
+ if ( expectedMembers . length === 0 ) {
376
362
return ;
377
363
}
378
364
365
+ const outstandingSourceMembers = calculateExpectedSourceMembers ( expectedMembers ) ;
366
+
379
367
const originalOutstandingSize = outstandingSourceMembers . size ;
380
368
// this will be the absolute timeout from the start of the poll. We can also exit early if it doesn't look like more results are coming in
381
369
const pollingTimeout = this . calculateTimeout ( outstandingSourceMembers . size ) ;
382
370
let highestRevisionSoFar = this . getServerMaxRevision ( ) ;
383
371
let pollAttempts = 0 ;
384
372
let consecutiveEmptyResults = 0 ;
385
373
let someResultsReturned = false ;
374
+ /** we weren't expecting these SourceMembers, based on the deployment results */
375
+ const bonusTypes = new Set < string > ( ) ;
386
376
387
377
this . logger . debug (
388
378
`Polling for ${ outstandingSourceMembers . size } SourceMembers from revision ${ highestRevisionSoFar } with timeout of ${ pollingTimeout . seconds } s`
@@ -402,7 +392,11 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
402
392
if ( queriedMembers . length ) {
403
393
queriedMembers . map ( ( member ) => {
404
394
// remove anything returned from the query list
405
- outstandingSourceMembers . delete ( getMetadataKey ( member . MemberType , member . MemberName ) ) ;
395
+ const metadataKey = getMetadataKey ( member . MemberType , member . MemberName ) ;
396
+ const deleted = outstandingSourceMembers . delete ( metadataKey ) ;
397
+ if ( ! deleted ) {
398
+ bonusTypes . add ( metadataKey ) ;
399
+ }
406
400
highestRevisionSoFar = Math . max ( highestRevisionSoFar , member . RevisionCounter ) ;
407
401
} ) ;
408
402
consecutiveEmptyResults = 0 ;
@@ -446,6 +440,15 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
446
440
try {
447
441
await pollingFunction ( ) ;
448
442
this . logger . debug ( `Retrieved all SourceMember data after ${ pollAttempts } attempts` ) ;
443
+ // find places where the expectedSourceMembers might be too pruning too aggressively
444
+ if ( bonusTypes . size ) {
445
+ void Lifecycle . getInstance ( ) . emitTelemetry ( {
446
+ eventName : 'sourceMemberBonusTypes' ,
447
+ library : 'SourceTracking' ,
448
+ deploymentSize : expectedMembers . length ,
449
+ bonusTypes : Array . from ( bonusTypes ) . sort ( ) . join ( ',' ) ,
450
+ } ) ;
451
+ }
449
452
} catch {
450
453
this . logger . warn (
451
454
`Polling for SourceMembers timed out after ${ pollAttempts } attempts (last ${ consecutiveEmptyResults } were empty) )`
@@ -467,6 +470,7 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking
467
470
consecutiveEmptyResults,
468
471
missingQuantity : outstandingSourceMembers . size ,
469
472
deploymentSize : expectedMembers . length ,
473
+ bonusTypes : Array . from ( bonusTypes ) . sort ( ) . join ( ',' ) ,
470
474
types : [ ...new Set ( Array . from ( outstandingSourceMembers . values ( ) ) . map ( ( member ) => member . type ) ) ]
471
475
. sort ( )
472
476
. join ( ',' ) ,
@@ -578,3 +582,9 @@ export const remoteChangeElementToChangeResult = (rce: RemoteChangeElement): Cha
578
582
: { } ) ,
579
583
origin : 'remote' , // we know they're remote
580
584
} ) ;
585
+
586
+ const convertRevisionToChange = ( memberKey : string , memberRevision : MemberRevision ) : RemoteChangeElement => ( {
587
+ type : memberRevision . memberType ,
588
+ name : memberKey . replace ( `${ memberRevision . memberType } __` , '' ) ,
589
+ deleted : memberRevision . isNameObsolete ,
590
+ } ) ;
0 commit comments