meadow-integration 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meadow-integration",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"description": "Meadow Data Integration",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mdwint": "source/cli/Meadow-Integration-CLI-Run.js"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"author": "steven velozo <steven@velozo.com>",
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"quackage": "^1.0.
|
|
19
|
+
"quackage": "^1.0.64"
|
|
20
20
|
},
|
|
21
21
|
"mocha": {
|
|
22
22
|
"diff": true,
|
|
@@ -41,6 +41,7 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
41
41
|
this.PageSize = this.options.PageSize || 100;
|
|
42
42
|
this.SyncDeletedRecords = this.options.SyncDeletedRecords || false;
|
|
43
43
|
this.MaxRecordsPerEntity = this.options.MaxRecordsPerEntity || 0;
|
|
44
|
+
this.UseAdvancedIDPagination = this.options.UseAdvancedIDPagination || false;
|
|
44
45
|
|
|
45
46
|
this.Meadow = false;
|
|
46
47
|
|
|
@@ -447,9 +448,10 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
447
448
|
tmpSyncState.EstimatedRecordCount = tmpSyncState.Server.RecordCount - tmpSyncState.Local.RecordCount;
|
|
448
449
|
|
|
449
450
|
// Apply MaxRecordsPerEntity cap if configured
|
|
450
|
-
|
|
451
|
+
tmpSyncState.RecordCap = (this.MaxRecordsPerEntity > 0)
|
|
451
452
|
? Math.min(tmpSyncState.Server.RecordCount, this.MaxRecordsPerEntity)
|
|
452
453
|
: tmpSyncState.Server.RecordCount;
|
|
454
|
+
let tmpRecordCap = tmpSyncState.RecordCap;
|
|
453
455
|
|
|
454
456
|
if (this.MaxRecordsPerEntity > 0 && tmpSyncState.EstimatedRecordCount > this.MaxRecordsPerEntity)
|
|
455
457
|
{
|
|
@@ -459,14 +461,21 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
459
461
|
this.operation.createProgressTracker(tmpSyncState.EstimatedRecordCount, `FullSync-${this.EntitySchema.TableName}`);
|
|
460
462
|
this.operation.printProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`);
|
|
461
463
|
|
|
462
|
-
|
|
463
|
-
tmpSyncState.URLPartials = [];
|
|
464
|
-
for (let i = 0; i < tmpRecordCap; i += this.PageSize)
|
|
464
|
+
if (this.UseAdvancedIDPagination)
|
|
465
465
|
{
|
|
466
|
-
|
|
466
|
+
this.fable.log.info(`${this.EntitySchema.TableName}: using advanced ID pagination (local: ${tmpSyncState.Local.RecordCount}/${tmpSyncState.Local.MaxIDEntity}, server: ${tmpSyncState.Server.RecordCount}/${tmpSyncState.Server.MaxIDEntity}, estimated new: ${tmpSyncState.EstimatedRecordCount}${this.MaxRecordsPerEntity > 0 ? `, capped at ${this.MaxRecordsPerEntity}` : ''})`);
|
|
467
467
|
}
|
|
468
|
+
else
|
|
469
|
+
{
|
|
470
|
+
// Generate paginated URL partials
|
|
471
|
+
tmpSyncState.URLPartials = [];
|
|
472
|
+
for (let i = 0; i < tmpRecordCap; i += this.PageSize)
|
|
473
|
+
{
|
|
474
|
+
tmpSyncState.URLPartials.push(`${this.EntitySchema.TableName}s/FilteredTo/FBV~${this.DefaultIdentifier}~GT~${tmpSyncState.Local.MaxIDEntity}~FSF~${this.DefaultIdentifier}~ASC~ASC/${i}/${this.PageSize}`);
|
|
475
|
+
}
|
|
468
476
|
|
|
469
|
-
|
|
477
|
+
this.fable.log.info(`${this.EntitySchema.TableName}: downloading ${tmpSyncState.URLPartials.length} pages (local: ${tmpSyncState.Local.RecordCount}/${tmpSyncState.Local.MaxIDEntity}, server: ${tmpSyncState.Server.RecordCount}/${tmpSyncState.Server.MaxIDEntity}, estimated new: ${tmpSyncState.EstimatedRecordCount}${this.MaxRecordsPerEntity > 0 ? `, capped at ${this.MaxRecordsPerEntity}` : ''})`);
|
|
478
|
+
}
|
|
470
479
|
|
|
471
480
|
return fStageComplete();
|
|
472
481
|
},
|
|
@@ -477,149 +486,216 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
477
486
|
let tmpRecordsSkipped = 0;
|
|
478
487
|
let tmpRecordsErrored = 0;
|
|
479
488
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
489
|
+
// Shared record-processing function used by both pagination modes
|
|
490
|
+
const fProcessPageRecords = (pBody, fPageProcessComplete) =>
|
|
491
|
+
{
|
|
492
|
+
this.fable.Utility.eachLimit(pBody, 5,
|
|
493
|
+
(pEntityRecord, fEntitySyncComplete) =>
|
|
494
|
+
{
|
|
495
|
+
const tmpRecord = pEntityRecord;
|
|
496
|
+
const tmpQuery = this.Meadow.query;
|
|
484
497
|
|
|
485
|
-
|
|
486
|
-
(pDownloadError, pResponse, pBody) =>
|
|
498
|
+
if ((typeof(tmpRecord[this.DefaultIdentifier]) !== 'undefined') && (tmpRecord[this.DefaultIdentifier] > 0))
|
|
487
499
|
{
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
this.fable.log.error(`${this.EntitySchema.TableName}: page ${tmpPageIndex} download error: ${pDownloadError}`);
|
|
491
|
-
return fDownloadComplete();
|
|
492
|
-
}
|
|
493
|
-
if (pBody && Array.isArray(pBody) && pBody.length > 0)
|
|
494
|
-
{
|
|
495
|
-
this.fable.Utility.eachLimit(pBody, 5,
|
|
496
|
-
(pEntityRecord, fEntitySyncComplete) =>
|
|
497
|
-
{
|
|
498
|
-
const tmpRecord = pEntityRecord;
|
|
499
|
-
const tmpQuery = this.Meadow.query;
|
|
500
|
-
|
|
501
|
-
if ((typeof(tmpRecord[this.DefaultIdentifier]) !== 'undefined') && (tmpRecord[this.DefaultIdentifier] > 0))
|
|
502
|
-
{
|
|
503
|
-
tmpQuery.addFilter(this.DefaultIdentifier, tmpRecord[this.DefaultIdentifier]);
|
|
504
|
-
}
|
|
500
|
+
tmpQuery.addFilter(this.DefaultIdentifier, tmpRecord[this.DefaultIdentifier]);
|
|
501
|
+
}
|
|
505
502
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
503
|
+
if (!tmpSyncState.HasDeletedColumn)
|
|
504
|
+
{
|
|
505
|
+
tmpQuery.setDisableDeleteTracking(true);
|
|
506
|
+
}
|
|
510
507
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
508
|
+
this.Meadow.doRead(tmpQuery,
|
|
509
|
+
(pReadError, pQuery, pRecord) =>
|
|
510
|
+
{
|
|
511
|
+
if (pReadError)
|
|
512
|
+
{
|
|
513
|
+
tmpRecordsErrored++;
|
|
514
|
+
return fEntitySyncComplete();
|
|
515
|
+
}
|
|
516
|
+
if (!pRecord)
|
|
517
|
+
{
|
|
518
|
+
// Record not found -- create it
|
|
519
|
+
const tmpRecordToCommit = this.marshalRecord(tmpRecord);
|
|
523
520
|
|
|
524
|
-
|
|
521
|
+
const tmpCreateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
525
522
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
523
|
+
tmpCreateQuery.setDisableAutoIdentity(true);
|
|
524
|
+
tmpCreateQuery.setDisableAutoDateStamp(true);
|
|
525
|
+
tmpCreateQuery.setDisableAutoUserStamp(true);
|
|
526
|
+
tmpCreateQuery.setDisableDeleteTracking(true);
|
|
530
527
|
|
|
531
|
-
|
|
528
|
+
tmpCreateQuery.AllowIdentityInsert = true;
|
|
532
529
|
|
|
533
|
-
|
|
534
|
-
|
|
530
|
+
this.Meadow.doCreate(tmpCreateQuery,
|
|
531
|
+
(pCreateError) =>
|
|
532
|
+
{
|
|
533
|
+
if (pCreateError)
|
|
534
|
+
{
|
|
535
|
+
let tmpErrorStr = (typeof(pCreateError) === 'string') ? pCreateError : JSON.stringify(pCreateError);
|
|
536
|
+
if (tmpErrorStr.toLowerCase().indexOf('duplicate') > -1 || tmpErrorStr.toLowerCase().indexOf('unique') > -1)
|
|
537
|
+
{
|
|
538
|
+
// Duplicate key (likely GUID conflict) -- fall back to update
|
|
539
|
+
this.log.warn(`${this.EntitySchema.TableName}: duplicate key on create for ID ${tmpRecord[this.DefaultIdentifier]}; falling back to update.`);
|
|
540
|
+
const tmpUpdateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
541
|
+
tmpUpdateQuery.setDisableAutoIdentity(true);
|
|
542
|
+
tmpUpdateQuery.setDisableAutoDateStamp(true);
|
|
543
|
+
tmpUpdateQuery.setDisableAutoUserStamp(true);
|
|
544
|
+
tmpUpdateQuery.setDisableDeleteTracking(true);
|
|
545
|
+
this.Meadow.doUpdate(tmpUpdateQuery,
|
|
546
|
+
(pUpdateError) =>
|
|
535
547
|
{
|
|
536
|
-
if (
|
|
548
|
+
if (pUpdateError)
|
|
537
549
|
{
|
|
538
|
-
let tmpErrorStr = (typeof(pCreateError) === 'string') ? pCreateError : JSON.stringify(pCreateError);
|
|
539
|
-
if (tmpErrorStr.toLowerCase().indexOf('duplicate') > -1 || tmpErrorStr.toLowerCase().indexOf('unique') > -1)
|
|
540
|
-
{
|
|
541
|
-
// Duplicate key (likely GUID conflict) -- fall back to update
|
|
542
|
-
this.log.warn(`${this.EntitySchema.TableName}: duplicate key on create for ID ${tmpRecord[this.DefaultIdentifier]}; falling back to update.`);
|
|
543
|
-
const tmpUpdateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
544
|
-
tmpUpdateQuery.setDisableAutoIdentity(true);
|
|
545
|
-
tmpUpdateQuery.setDisableAutoDateStamp(true);
|
|
546
|
-
tmpUpdateQuery.setDisableAutoUserStamp(true);
|
|
547
|
-
tmpUpdateQuery.setDisableDeleteTracking(true);
|
|
548
|
-
this.Meadow.doUpdate(tmpUpdateQuery,
|
|
549
|
-
(pUpdateError) =>
|
|
550
|
-
{
|
|
551
|
-
if (pUpdateError)
|
|
552
|
-
{
|
|
553
|
-
tmpRecordsErrored++;
|
|
554
|
-
this.log.error(`${this.EntitySchema.TableName}: fallback update also failed for ID ${tmpRecord[this.DefaultIdentifier]}: ${pUpdateError}`);
|
|
555
|
-
return fEntitySyncComplete();
|
|
556
|
-
}
|
|
557
|
-
tmpRecordsCreated++;
|
|
558
|
-
this.operation.incrementProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`, 1);
|
|
559
|
-
return fEntitySyncComplete();
|
|
560
|
-
});
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
550
|
tmpRecordsErrored++;
|
|
564
|
-
this.log.error(`${this.EntitySchema.TableName}:
|
|
551
|
+
this.log.error(`${this.EntitySchema.TableName}: fallback update also failed for ID ${tmpRecord[this.DefaultIdentifier]}: ${pUpdateError}`);
|
|
565
552
|
return fEntitySyncComplete();
|
|
566
553
|
}
|
|
567
554
|
tmpRecordsCreated++;
|
|
568
555
|
this.operation.incrementProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`, 1);
|
|
569
556
|
return fEntitySyncComplete();
|
|
570
557
|
});
|
|
558
|
+
return;
|
|
571
559
|
}
|
|
572
|
-
|
|
573
|
-
{
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
if (pEntitySyncError)
|
|
583
|
-
{
|
|
584
|
-
this.log.error(`Problem or early completion syncing entity ${this.EntitySchema.TableName}: ${pEntitySyncError}`, pEntitySyncError);
|
|
585
|
-
}
|
|
586
|
-
return fDownloadComplete();
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
else
|
|
590
|
-
{
|
|
591
|
-
if (Array.isArray(pBody) && pBody.length == 0)
|
|
560
|
+
tmpRecordsErrored++;
|
|
561
|
+
this.log.error(`${this.EntitySchema.TableName}: doCreate error for ID ${tmpRecord[this.DefaultIdentifier]}: ${pCreateError}`);
|
|
562
|
+
return fEntitySyncComplete();
|
|
563
|
+
}
|
|
564
|
+
tmpRecordsCreated++;
|
|
565
|
+
this.operation.incrementProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`, 1);
|
|
566
|
+
return fEntitySyncComplete();
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
else
|
|
592
570
|
{
|
|
593
|
-
|
|
571
|
+
tmpRecordsSkipped++;
|
|
572
|
+
return fEntitySyncComplete();
|
|
594
573
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
574
|
+
});
|
|
575
|
+
},
|
|
576
|
+
(pEntitySyncError) =>
|
|
577
|
+
{
|
|
578
|
+
this.operation.printProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`);
|
|
579
|
+
if (pEntitySyncError)
|
|
580
|
+
{
|
|
581
|
+
this.log.error(`Problem or early completion syncing entity ${this.EntitySchema.TableName}: ${pEntitySyncError}`, pEntitySyncError);
|
|
582
|
+
}
|
|
583
|
+
return fPageProcessComplete(pEntitySyncError);
|
|
584
|
+
});
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
const fSyncComplete = (pDownloadError) =>
|
|
588
|
+
{
|
|
589
|
+
this.fable.log.info(`${this.EntitySchema.TableName}: sync complete — created: ${tmpRecordsCreated}, skipped: ${tmpRecordsSkipped}, errors: ${tmpRecordsErrored}`);
|
|
590
|
+
if (pDownloadError)
|
|
591
|
+
{
|
|
592
|
+
this.fable.log.error(`Error returned URL Partial .. this may not be an error: ${pDownloadError}`);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Store sync results on the entity so callers can inspect the breakdown
|
|
596
|
+
this.syncResults = (
|
|
597
|
+
{
|
|
598
|
+
Created: tmpRecordsCreated,
|
|
599
|
+
Skipped: tmpRecordsSkipped,
|
|
600
|
+
Errors: tmpRecordsErrored,
|
|
601
|
+
Deleted: 0,
|
|
602
|
+
ServerRecordCount: tmpSyncState.Server.RecordCount,
|
|
603
|
+
LocalRecordCount: tmpSyncState.Local.RecordCount,
|
|
604
|
+
ServerMaxID: tmpSyncState.Server.MaxIDEntity,
|
|
605
|
+
LocalMaxID: tmpSyncState.Local.MaxIDEntity,
|
|
606
|
+
EstimatedNew: tmpSyncState.EstimatedRecordCount
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
fStageComplete();
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
if (this.UseAdvancedIDPagination)
|
|
613
|
+
{
|
|
614
|
+
// Advanced ID pagination: use keyset pagination (WHERE ID > lastMaxID)
|
|
615
|
+
// instead of OFFSET to avoid progressive table scan slowdown on large datasets.
|
|
616
|
+
let tmpLastMaxID = tmpSyncState.Local.MaxIDEntity;
|
|
617
|
+
let tmpTotalFetched = 0;
|
|
618
|
+
|
|
619
|
+
const fFetchPage = () =>
|
|
600
620
|
{
|
|
601
|
-
|
|
602
|
-
if (pDownloadError)
|
|
621
|
+
if (tmpTotalFetched >= tmpSyncState.RecordCap)
|
|
603
622
|
{
|
|
604
|
-
|
|
623
|
+
return fSyncComplete();
|
|
605
624
|
}
|
|
606
625
|
|
|
607
|
-
|
|
608
|
-
|
|
626
|
+
tmpPageIndex++;
|
|
627
|
+
let tmpURL = `${this.EntitySchema.TableName}s/FilteredTo/FBV~${this.DefaultIdentifier}~GT~${tmpLastMaxID}~FSF~${this.DefaultIdentifier}~ASC~ASC/0/${this.PageSize}`;
|
|
628
|
+
|
|
629
|
+
this.fable.MeadowCloneRestClient.getJSON(tmpURL,
|
|
630
|
+
(pDownloadError, pResponse, pBody) =>
|
|
609
631
|
{
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
632
|
+
if (pDownloadError)
|
|
633
|
+
{
|
|
634
|
+
this.fable.log.error(`${this.EntitySchema.TableName}: page ${tmpPageIndex} download error: ${pDownloadError}`);
|
|
635
|
+
return fSyncComplete(pDownloadError);
|
|
636
|
+
}
|
|
637
|
+
if (pBody && Array.isArray(pBody) && pBody.length > 0)
|
|
638
|
+
{
|
|
639
|
+
// Track the max ID from this page for the next page filter
|
|
640
|
+
for (let r = 0; r < pBody.length; r++)
|
|
641
|
+
{
|
|
642
|
+
if (pBody[r][this.DefaultIdentifier] > tmpLastMaxID)
|
|
643
|
+
{
|
|
644
|
+
tmpLastMaxID = pBody[r][this.DefaultIdentifier];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
tmpTotalFetched += pBody.length;
|
|
648
|
+
|
|
649
|
+
fProcessPageRecords(pBody, (pProcessError) =>
|
|
650
|
+
{
|
|
651
|
+
if (pProcessError)
|
|
652
|
+
{
|
|
653
|
+
return fSyncComplete(pProcessError);
|
|
654
|
+
}
|
|
655
|
+
return setImmediate(fFetchPage);
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
else
|
|
659
|
+
{
|
|
660
|
+
// No more records
|
|
661
|
+
return fSyncComplete();
|
|
662
|
+
}
|
|
619
663
|
});
|
|
664
|
+
};
|
|
665
|
+
fFetchPage();
|
|
666
|
+
}
|
|
667
|
+
else
|
|
668
|
+
{
|
|
669
|
+
// Standard offset-based pagination
|
|
670
|
+
this.fable.Utility.eachLimit(tmpSyncState.URLPartials, 1,
|
|
671
|
+
(pURLPartial, fDownloadComplete) =>
|
|
672
|
+
{
|
|
673
|
+
tmpPageIndex++;
|
|
620
674
|
|
|
621
|
-
|
|
622
|
-
|
|
675
|
+
this.fable.MeadowCloneRestClient.getJSON(pURLPartial,
|
|
676
|
+
(pDownloadError, pResponse, pBody) =>
|
|
677
|
+
{
|
|
678
|
+
if (pDownloadError)
|
|
679
|
+
{
|
|
680
|
+
this.fable.log.error(`${this.EntitySchema.TableName}: page ${tmpPageIndex} download error: ${pDownloadError}`);
|
|
681
|
+
return fDownloadComplete();
|
|
682
|
+
}
|
|
683
|
+
if (pBody && Array.isArray(pBody) && pBody.length > 0)
|
|
684
|
+
{
|
|
685
|
+
fProcessPageRecords(pBody, fDownloadComplete);
|
|
686
|
+
}
|
|
687
|
+
else
|
|
688
|
+
{
|
|
689
|
+
if (Array.isArray(pBody) && pBody.length == 0)
|
|
690
|
+
{
|
|
691
|
+
return fDownloadComplete(new Error('Records depleted!'));
|
|
692
|
+
}
|
|
693
|
+
return fDownloadComplete();
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
},
|
|
697
|
+
fSyncComplete);
|
|
698
|
+
}
|
|
623
699
|
},
|
|
624
700
|
],
|
|
625
701
|
(pError) =>
|
|
@@ -65,6 +65,18 @@ class MeadowSync extends libFableServiceProviderBase
|
|
|
65
65
|
this.MaxRecordsPerEntity = parseInt(this.options.MaxRecordsPerEntity, 10) || 0;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// When true, use ID-based keyset pagination instead of OFFSET pagination.
|
|
69
|
+
// This avoids table scans on large datasets by filtering WHERE ID > lastMaxID.
|
|
70
|
+
this.UseAdvancedIDPagination = false;
|
|
71
|
+
if (this.fable.ProgramConfiguration.hasOwnProperty('UseAdvancedIDPagination'))
|
|
72
|
+
{
|
|
73
|
+
this.UseAdvancedIDPagination = !!this.fable.ProgramConfiguration.UseAdvancedIDPagination;
|
|
74
|
+
}
|
|
75
|
+
else if (this.options.hasOwnProperty('UseAdvancedIDPagination'))
|
|
76
|
+
{
|
|
77
|
+
this.UseAdvancedIDPagination = !!this.options.UseAdvancedIDPagination;
|
|
78
|
+
}
|
|
79
|
+
|
|
68
80
|
// Tolerance window in milliseconds for cross-database timestamp precision differences.
|
|
69
81
|
// Passed through to Ongoing sync entities for bisection date comparison.
|
|
70
82
|
this.DateTimePrecisionMS = 1000;
|
|
@@ -114,6 +126,7 @@ class MeadowSync extends libFableServiceProviderBase
|
|
|
114
126
|
SyncDeletedRecords: this.SyncDeletedRecords,
|
|
115
127
|
MaxRecordsPerEntity: this.MaxRecordsPerEntity,
|
|
116
128
|
DateTimePrecisionMS: this.DateTimePrecisionMS,
|
|
129
|
+
UseAdvancedIDPagination: this.UseAdvancedIDPagination,
|
|
117
130
|
};
|
|
118
131
|
|
|
119
132
|
let tmpSyncEntity;
|