retold-data-service 2.0.36 → 2.0.38

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": "retold-data-service",
3
- "version": "2.0.36",
3
+ "version": "2.0.38",
4
4
  "description": "Serve up a whole model!",
5
5
  "main": "source/Retold-Data-Service.js",
6
6
  "bin": {
@@ -68,12 +68,12 @@
68
68
  },
69
69
  "dependencies": {
70
70
  "bibliograph": "^0.1.4",
71
- "fable": "^3.1.68",
71
+ "fable": "^3.1.70",
72
72
  "fable-serviceproviderbase": "^3.0.19",
73
73
  "meadow": "^2.0.33",
74
74
  "meadow-connection-mysql": "^1.0.14",
75
75
  "meadow-endpoints": "^4.0.15",
76
- "meadow-integration": "^1.0.28",
76
+ "meadow-integration": "^1.0.30",
77
77
  "meadow-migrationmanager": "^0.0.9",
78
78
  "orator": "^6.0.4",
79
79
  "orator-http-proxy": "^1.0.5",
@@ -84,8 +84,10 @@ class RetoldDataServiceDataCloner extends libFableServiceProviderBase
84
84
  ThroughputTimer: null
85
85
  });
86
86
 
87
- // Create an isolated Pict instance for remote session management
88
- this._Pict = new libPict(
87
+ // Create an isolated Pict instance for remote session management.
88
+ // Forward REST client connection settings from the parent fable so
89
+ // the session RestClient inherits keep-alive and timeout configuration.
90
+ let tmpPictSettings = (
89
91
  {
90
92
  Product: 'DataClonerSession',
91
93
  TraceLog: true,
@@ -96,6 +98,19 @@ class RetoldDataServiceDataCloner extends libFableServiceProviderBase
96
98
  }
97
99
  ]
98
100
  });
101
+ if (this.fable.settings.RestClientKeepAlive)
102
+ {
103
+ tmpPictSettings.RestClientKeepAlive = this.fable.settings.RestClientKeepAlive;
104
+ }
105
+ if (this.fable.settings.RestClientRequestTimeout)
106
+ {
107
+ tmpPictSettings.RestClientRequestTimeout = this.fable.settings.RestClientRequestTimeout;
108
+ }
109
+ if (this.fable.settings.RestClientMaxRequestTimeout)
110
+ {
111
+ tmpPictSettings.RestClientMaxRequestTimeout = this.fable.settings.RestClientMaxRequestTimeout;
112
+ }
113
+ this._Pict = new libPict(tmpPictSettings);
99
114
 
100
115
  this._Pict.serviceManager.addServiceType('SessionManager', libPictSessionManager);
101
116
  this._Pict.serviceManager.instantiateServiceProvider('SessionManager');
@@ -1003,12 +1018,19 @@ class RetoldDataServiceDataCloner extends libFableServiceProviderBase
1003
1018
  let tmpTracker = tmpSyncEntity.operation.progressTrackers[`FullSync-${tmpTableName}`];
1004
1019
  if (tmpTracker)
1005
1020
  {
1006
- tmpProgress.Total = tmpTracker.TotalCount || 0;
1021
+ // Clamp both to >= 0: Total can be estimated from
1022
+ // Server.RecordCount - Local.RecordCount, which is
1023
+ // negative when local has extra records (e.g. after
1024
+ // server-side deletes). A negative total in the
1025
+ // progress report is nonsensical.
1026
+ tmpProgress.Total = Math.max(tmpTracker.TotalCount || 0, 0);
1007
1027
  tmpProgress.Synced = Math.max(tmpTracker.CurrentCount || 0, 0);
1008
1028
  }
1009
1029
  }
1010
1030
 
1011
1031
  // Read per-record breakdown from the sync entity
1032
+ let tmpEntityErrors = 0;
1033
+ let tmpEntitySkipped = 0;
1012
1034
  if (tmpSyncEntity && tmpSyncEntity.syncResults)
1013
1035
  {
1014
1036
  let tmpResults = tmpSyncEntity.syncResults;
@@ -1018,12 +1040,12 @@ class RetoldDataServiceDataCloner extends libFableServiceProviderBase
1018
1040
  tmpProgress.Deleted = tmpResults.Deleted || 0;
1019
1041
  tmpProgress.ServerTotal = tmpResults.ServerRecordCount || 0;
1020
1042
  tmpProgress.LocalCountBefore = tmpResults.LocalRecordCount || 0;
1043
+ tmpEntityErrors = tmpResults.Errors || 0;
1044
+ tmpEntitySkipped = tmpResults.Skipped || 0;
1021
1045
  }
1022
1046
 
1023
1047
  let tmpRESTErrors = this._cloneState.SyncRESTErrors[tmpTableName] || 0;
1024
- tmpProgress.Errors = tmpRESTErrors;
1025
-
1026
- let tmpMissing = tmpProgress.Total - tmpProgress.Synced;
1048
+ tmpProgress.Errors = tmpRESTErrors + tmpEntityErrors;
1027
1049
 
1028
1050
  if (pError)
1029
1051
  {
@@ -1033,25 +1055,35 @@ class RetoldDataServiceDataCloner extends libFableServiceProviderBase
1033
1055
  this.logSyncEvent('TableError', `Sync [${tmpTableName}] — error: ${pError}`,
1034
1056
  { Table: tmpTableName, Total: tmpProgress.Total, Synced: tmpProgress.Synced, Error: `${pError}` });
1035
1057
  }
1036
- else if (tmpRESTErrors > 0)
1037
- {
1038
- tmpProgress.Status = 'Error';
1039
- tmpProgress.ErrorMessage = `${tmpRESTErrors} REST error(s) during sync`;
1040
- this.fable.log.warn(`Data Cloner: Sync [${tmpTableName}] — completed with ${tmpRESTErrors} REST error(s). ${tmpProgress.Synced}/${tmpProgress.Total} records synced.`);
1041
- this.logSyncEvent('TableError', `Sync [${tmpTableName}] — ${tmpRESTErrors} REST error(s).`,
1042
- { Table: tmpTableName, Total: tmpProgress.Total, Synced: tmpProgress.Synced, RESTErrors: tmpRESTErrors });
1043
- }
1044
- else if (tmpProgress.Total > 0 && tmpMissing > 0)
1058
+ else if (tmpRESTErrors > 0 || tmpEntityErrors > 0)
1045
1059
  {
1046
- tmpProgress.Status = 'Partial';
1047
- tmpProgress.Skipped = tmpMissing;
1048
- this.fable.log.warn(`Data Cloner: Sync [${tmpTableName}] — partial. ${tmpProgress.Synced}/${tmpProgress.Total} records synced, ${tmpMissing} skipped (GUID conflicts or other errors).`);
1049
- this.logSyncEvent('TablePartial', `Sync [${tmpTableName}] partial. ${tmpMissing} skipped.`,
1050
- { Table: tmpTableName, Total: tmpProgress.Total, Synced: tmpProgress.Synced, Skipped: tmpMissing });
1060
+ // Only treat the sync as Partial/Error when the sync
1061
+ // entity actually reported errors (REST fetch errors or
1062
+ // per-record commit errors). A count-mismatch between
1063
+ // estimated Total and actual Synced is not itself an
1064
+ // error pre-count estimates can be stale (records
1065
+ // were updated rather than added, local already has
1066
+ // records past the server's max ID, etc.), and the
1067
+ // sync code correctly downloads nothing in those
1068
+ // cases. Reporting "N skipped" for pure estimate
1069
+ // drift is noisy and misleading.
1070
+ let tmpPartialMessage = (tmpRESTErrors > 0 && tmpEntityErrors > 0)
1071
+ ? `${tmpRESTErrors} REST error(s) and ${tmpEntityErrors} record error(s) during sync`
1072
+ : (tmpRESTErrors > 0)
1073
+ ? `${tmpRESTErrors} REST error(s) during sync`
1074
+ : `${tmpEntityErrors} record error(s) during sync`;
1075
+ tmpProgress.Status = (tmpRESTErrors > 0) ? 'Error' : 'Partial';
1076
+ tmpProgress.ErrorMessage = tmpPartialMessage;
1077
+ tmpProgress.Skipped = tmpEntitySkipped;
1078
+ this.fable.log.warn(`Data Cloner: Sync [${tmpTableName}] — ${tmpPartialMessage}. ${tmpProgress.Synced}/${tmpProgress.Total} records synced.`);
1079
+ this.logSyncEvent(tmpProgress.Status === 'Error' ? 'TableError' : 'TablePartial',
1080
+ `Sync [${tmpTableName}] — ${tmpPartialMessage}.`,
1081
+ { Table: tmpTableName, Total: tmpProgress.Total, Synced: tmpProgress.Synced, RESTErrors: tmpRESTErrors, RecordErrors: tmpEntityErrors });
1051
1082
  }
1052
1083
  else
1053
1084
  {
1054
1085
  tmpProgress.Status = 'Complete';
1086
+ tmpProgress.Skipped = tmpEntitySkipped;
1055
1087
  this.fable.log.info(`Data Cloner: Sync [${tmpTableName}] — complete. ${tmpProgress.Synced}/${tmpProgress.Total} records synced.`);
1056
1088
  this.logSyncEvent('TableComplete', `Sync [${tmpTableName}] — complete. ${tmpProgress.Synced}/${tmpProgress.Total} records.`,
1057
1089
  { Table: tmpTableName, Total: tmpProgress.Total, Synced: tmpProgress.Synced });