meadow-integration 1.0.30 → 1.0.32
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
|
@@ -458,7 +458,13 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
458
458
|
},
|
|
459
459
|
(fStageComplete) =>
|
|
460
460
|
{
|
|
461
|
-
|
|
461
|
+
// The raw diff can be negative when local has more records
|
|
462
|
+
// than the server (e.g. records were deleted server-side but
|
|
463
|
+
// the local copy still has them). Clamp the estimate to 0
|
|
464
|
+
// so progress trackers and downstream reports never show a
|
|
465
|
+
// negative total.
|
|
466
|
+
let tmpRawEstimate = tmpSyncState.Server.RecordCount - tmpSyncState.Local.RecordCount;
|
|
467
|
+
tmpSyncState.EstimatedRecordCount = Math.max(0, tmpRawEstimate);
|
|
462
468
|
|
|
463
469
|
// Apply MaxRecordsPerEntity cap if configured
|
|
464
470
|
tmpSyncState.RecordCap = (this.MaxRecordsPerEntity > 0)
|
|
@@ -474,6 +480,29 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
474
480
|
this.operation.createProgressTracker(tmpSyncState.EstimatedRecordCount, `FullSync-${this.EntitySchema.TableName}`);
|
|
475
481
|
this.operation.printProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`);
|
|
476
482
|
|
|
483
|
+
// Fast path: if there is nothing new to pull (estimate is
|
|
484
|
+
// zero or negative), skip the download phase entirely.
|
|
485
|
+
// Running the paginated loop would otherwise make one or
|
|
486
|
+
// more requests just to receive an empty response and then
|
|
487
|
+
// short-circuit with an "Error: Records depleted!" log —
|
|
488
|
+
// noisy and a waste of round-trips. Zero out RecordCap
|
|
489
|
+
// as well so the advanced-ID-pagination loop
|
|
490
|
+
// (which gates on RecordCap, not URLPartials) also skips.
|
|
491
|
+
if (tmpSyncState.EstimatedRecordCount <= 0)
|
|
492
|
+
{
|
|
493
|
+
tmpSyncState.URLPartials = [];
|
|
494
|
+
tmpSyncState.RecordCap = 0;
|
|
495
|
+
if (tmpRawEstimate < 0)
|
|
496
|
+
{
|
|
497
|
+
this.fable.log.info(`${this.EntitySchema.TableName}: local has ${-tmpRawEstimate} more record(s) than server (local: ${tmpSyncState.Local.RecordCount}, server: ${tmpSyncState.Server.RecordCount}); nothing to download.`);
|
|
498
|
+
}
|
|
499
|
+
else
|
|
500
|
+
{
|
|
501
|
+
this.fable.log.info(`${this.EntitySchema.TableName}: record counts match (${tmpSyncState.Server.RecordCount}); nothing to download.`);
|
|
502
|
+
}
|
|
503
|
+
return fStageComplete();
|
|
504
|
+
}
|
|
505
|
+
|
|
477
506
|
if (this.UseAdvancedIDPagination)
|
|
478
507
|
{
|
|
479
508
|
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}` : ''})`);
|
|
@@ -688,105 +688,115 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
688
688
|
|
|
689
689
|
this.fable.log.info(`Found ${tmpDeletedCount} deleted records on server for ${this.EntitySchema.TableName}; syncing deletions...`);
|
|
690
690
|
|
|
691
|
-
// Generate paginated URLs for deleted records
|
|
692
691
|
let tmpDeleteCap = (this.MaxRecordsPerEntity > 0)
|
|
693
692
|
? Math.min(tmpDeletedCount, this.MaxRecordsPerEntity)
|
|
694
693
|
: tmpDeletedCount;
|
|
695
|
-
const tmpDeleteURLPartials = [];
|
|
696
|
-
for (let i = 0; i < tmpDeleteCap; i += this.PageSize)
|
|
697
|
-
{
|
|
698
|
-
tmpDeleteURLPartials.push(this._appendDeletedQueryString(`${this.EntitySchema.TableName}s/FilteredTo/FBV~Deleted~EQ~1~FSF~${this.DefaultIdentifier}~ASC~ASC/${i}/${this.PageSize}`));
|
|
699
|
-
}
|
|
700
694
|
|
|
701
|
-
|
|
702
|
-
|
|
695
|
+
let tmpOffset = 0;
|
|
696
|
+
let tmpProcessed = 0;
|
|
697
|
+
|
|
698
|
+
// Fetch deleted record pages one at a time rather than
|
|
699
|
+
// pre-generating all URL partials. With millions of deleted
|
|
700
|
+
// records this avoids allocating hundreds of thousands of
|
|
701
|
+
// URL strings and prevents stack overflow in the iterator.
|
|
702
|
+
const fFetchDeletedPage = () =>
|
|
703
|
+
{
|
|
704
|
+
if (tmpOffset >= tmpDeleteCap)
|
|
703
705
|
{
|
|
704
|
-
this.fable.
|
|
705
|
-
|
|
706
|
+
this.fable.log.info(`Delete sync complete for ${this.EntitySchema.TableName} (${tmpProcessed} of ${tmpDeletedCount} deleted records processed).`);
|
|
707
|
+
return fCallback();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
const tmpURL = this._appendDeletedQueryString(`${this.EntitySchema.TableName}s/FilteredTo/FBV~Deleted~EQ~1~FSF~${this.DefaultIdentifier}~ASC~ASC/${tmpOffset}/${this.PageSize}`);
|
|
711
|
+
tmpOffset += this.PageSize;
|
|
712
|
+
|
|
713
|
+
this.fable.MeadowCloneRestClient.getJSON(tmpURL,
|
|
714
|
+
(pDownloadError, pResponse, pBody) =>
|
|
715
|
+
{
|
|
716
|
+
if (pDownloadError || !pBody || !Array.isArray(pBody) || pBody.length < 1)
|
|
706
717
|
{
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
}
|
|
718
|
+
this.fable.log.info(`Delete sync complete for ${this.EntitySchema.TableName} (${tmpProcessed} of ${tmpDeletedCount} deleted records processed).`);
|
|
719
|
+
return fCallback();
|
|
720
|
+
}
|
|
711
721
|
|
|
712
|
-
|
|
713
|
-
|
|
722
|
+
this.fable.Utility.eachLimit(pBody, 5,
|
|
723
|
+
(pEntityRecord, fRecordComplete) =>
|
|
724
|
+
{
|
|
725
|
+
const tmpRecordID = pEntityRecord[this.DefaultIdentifier];
|
|
726
|
+
if (!tmpRecordID || tmpRecordID < 1)
|
|
714
727
|
{
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
{
|
|
718
|
-
return setImmediate(fRecordComplete);
|
|
719
|
-
}
|
|
728
|
+
return setImmediate(fRecordComplete);
|
|
729
|
+
}
|
|
720
730
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
731
|
+
// Read local record with delete tracking disabled so we can see all records
|
|
732
|
+
const tmpQuery = this.Meadow.query;
|
|
733
|
+
tmpQuery.addFilter(this.DefaultIdentifier, tmpRecordID);
|
|
734
|
+
tmpQuery.setDisableDeleteTracking(true);
|
|
725
735
|
|
|
726
|
-
|
|
727
|
-
|
|
736
|
+
this.Meadow.doRead(tmpQuery,
|
|
737
|
+
(pReadError, pQuery, pRecord) =>
|
|
738
|
+
{
|
|
739
|
+
if (pReadError || !pRecord)
|
|
728
740
|
{
|
|
729
|
-
|
|
730
|
-
{
|
|
731
|
-
// Record doesn't exist locally -- create it as deleted
|
|
732
|
-
const tmpRecordToCommit = this.marshalRecord(pEntityRecord);
|
|
733
|
-
|
|
734
|
-
const tmpCreateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
735
|
-
tmpCreateQuery.setDisableAutoIdentity(true);
|
|
736
|
-
tmpCreateQuery.setDisableAutoDateStamp(true);
|
|
737
|
-
tmpCreateQuery.setDisableAutoUserStamp(true);
|
|
738
|
-
tmpCreateQuery.setDisableDeleteTracking(true);
|
|
739
|
-
tmpCreateQuery.AllowIdentityInsert = true;
|
|
740
|
-
|
|
741
|
-
this.Meadow.doCreate(tmpCreateQuery,
|
|
742
|
-
(pCreateError) =>
|
|
743
|
-
{
|
|
744
|
-
if (pCreateError)
|
|
745
|
-
{
|
|
746
|
-
this.log.error(`Error creating deleted record ${this.EntitySchema.TableName} ID ${tmpRecordID}: ${pCreateError}`);
|
|
747
|
-
}
|
|
748
|
-
return setImmediate(fRecordComplete);
|
|
749
|
-
});
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
if (pRecord.Deleted == 1)
|
|
754
|
-
{
|
|
755
|
-
// Already marked deleted locally
|
|
756
|
-
return setImmediate(fRecordComplete);
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
// Record exists locally but is not deleted -- update it
|
|
741
|
+
// Record doesn't exist locally -- create it as deleted
|
|
760
742
|
const tmpRecordToCommit = this.marshalRecord(pEntityRecord);
|
|
761
743
|
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
744
|
+
const tmpCreateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
745
|
+
tmpCreateQuery.setDisableAutoIdentity(true);
|
|
746
|
+
tmpCreateQuery.setDisableAutoDateStamp(true);
|
|
747
|
+
tmpCreateQuery.setDisableAutoUserStamp(true);
|
|
748
|
+
tmpCreateQuery.setDisableDeleteTracking(true);
|
|
749
|
+
tmpCreateQuery.AllowIdentityInsert = true;
|
|
767
750
|
|
|
768
|
-
this.Meadow.
|
|
769
|
-
(
|
|
751
|
+
this.Meadow.doCreate(tmpCreateQuery,
|
|
752
|
+
(pCreateError) =>
|
|
770
753
|
{
|
|
771
|
-
if (
|
|
754
|
+
if (pCreateError)
|
|
772
755
|
{
|
|
773
|
-
this.log.error(`Error
|
|
756
|
+
this.log.error(`Error creating deleted record ${this.EntitySchema.TableName} ID ${tmpRecordID}: ${pCreateError}`);
|
|
774
757
|
}
|
|
758
|
+
tmpProcessed++;
|
|
775
759
|
return setImmediate(fRecordComplete);
|
|
776
760
|
});
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
if (pRecord.Deleted == 1)
|
|
765
|
+
{
|
|
766
|
+
// Already marked deleted locally
|
|
767
|
+
tmpProcessed++;
|
|
768
|
+
return setImmediate(fRecordComplete);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Record exists locally but is not deleted -- update it
|
|
772
|
+
const tmpRecordToCommit = this.marshalRecord(pEntityRecord);
|
|
773
|
+
|
|
774
|
+
const tmpUpdateQuery = this.Meadow.query.addRecord(tmpRecordToCommit);
|
|
775
|
+
tmpUpdateQuery.setDisableAutoIdentity(true);
|
|
776
|
+
tmpUpdateQuery.setDisableAutoDateStamp(true);
|
|
777
|
+
tmpUpdateQuery.setDisableAutoUserStamp(true);
|
|
778
|
+
tmpUpdateQuery.setDisableDeleteTracking(true);
|
|
779
|
+
|
|
780
|
+
this.Meadow.doUpdate(tmpUpdateQuery,
|
|
781
|
+
(pUpdateError) =>
|
|
782
|
+
{
|
|
783
|
+
if (pUpdateError)
|
|
784
|
+
{
|
|
785
|
+
this.log.error(`Error marking record as deleted ${this.EntitySchema.TableName} ID ${tmpRecordID}: ${pUpdateError}`);
|
|
786
|
+
}
|
|
787
|
+
tmpProcessed++;
|
|
788
|
+
return setImmediate(fRecordComplete);
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
},
|
|
792
|
+
(pRecordSyncError) =>
|
|
793
|
+
{
|
|
794
|
+
return setImmediate(fFetchDeletedPage);
|
|
795
|
+
});
|
|
796
|
+
});
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
fFetchDeletedPage();
|
|
790
800
|
});
|
|
791
801
|
}
|
|
792
802
|
|