meadow-integration 1.0.17 → 1.0.19
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/docs/README.md +1 -0
- package/docs/_sidebar.md +6 -1
- package/docs/comprehension-push/configuration.md +308 -0
- package/docs/integration-adapter.md +164 -15
- package/examples/example-comprehension-push.meadow.config.json +23 -0
- package/package.json +1 -1
- package/source/Meadow-Integration.js +7 -1
- package/source/Meadow-Service-Integration-Adapter.js +678 -245
- package/source/Meadow-Service-Integration-GUIDMap.js +19 -2
- package/source/cli/commands/Meadow-Integration-Command-ComprehensionPush.js +210 -38
- package/source/services/clone/Meadow-Service-RestClient.js +46 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-Initial.js +3 -2
- package/test/Meadow-Integration-ComprehensionPush_test.js +580 -0
|
@@ -65,7 +65,16 @@ class MeadowGUIDMap extends libFableServiceProviderBase
|
|
|
65
65
|
return (this._GUIDMap[pEntity].hasOwnProperty(pGUID)) ? this._GUIDMap[pEntity][pGUID] : false;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Get an ID from a GUID, loading from the server if not already cached.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} pEntity - The entity name
|
|
72
|
+
* @param {string} pGUID - The GUID to look up
|
|
73
|
+
* @param {function} fCallback - Callback (pError, pID)
|
|
74
|
+
* @param {object} [pClient] - Optional REST client to use for the server lookup
|
|
75
|
+
* (defaults to this.fable.MeadowRestClient or this.fable.MeadowCloneRestClient)
|
|
76
|
+
*/
|
|
77
|
+
getIDFromGUIDAsync(pEntity, pGUID, fCallback, pClient)
|
|
69
78
|
{
|
|
70
79
|
if (!this._GUIDMap.hasOwnProperty(pEntity))
|
|
71
80
|
{
|
|
@@ -79,8 +88,16 @@ class MeadowGUIDMap extends libFableServiceProviderBase
|
|
|
79
88
|
}
|
|
80
89
|
else
|
|
81
90
|
{
|
|
91
|
+
// Resolve the REST client to use for the server lookup
|
|
92
|
+
let tmpClient = pClient || this.fable.MeadowRestClient || this.fable.MeadowCloneRestClient;
|
|
93
|
+
|
|
94
|
+
if (!tmpClient || typeof(tmpClient.getEntityByGUID) !== 'function')
|
|
95
|
+
{
|
|
96
|
+
return fCallback(new Error(`No REST client with getEntityByGUID available for GUID lookup of [${pEntity}].[${pGUID}].`), false);
|
|
97
|
+
}
|
|
98
|
+
|
|
82
99
|
// Try to load it from the server
|
|
83
|
-
|
|
100
|
+
tmpClient.getEntityByGUID(pEntity, pGUID,
|
|
84
101
|
(pError, pBody) =>
|
|
85
102
|
{
|
|
86
103
|
if (pError)
|
|
@@ -3,6 +3,8 @@ const libCLICommandLineCommand = require('pict-service-commandlineutility').Serv
|
|
|
3
3
|
const libPath = require('path');
|
|
4
4
|
|
|
5
5
|
const libIntegrationAdapter = require('../../Meadow-Service-Integration-Adapter.js');
|
|
6
|
+
const libMeadowCloneRestClient = require('../../services/clone/Meadow-Service-RestClient.js');
|
|
7
|
+
const libSessionManagerSetup = require('../../Meadow-Integration-SessionManagerSetup.js');
|
|
6
8
|
|
|
7
9
|
class PushComprehensionsViaIntegration extends libCLICommandLineCommand
|
|
8
10
|
{
|
|
@@ -15,17 +17,52 @@ class PushComprehensionsViaIntegration extends libCLICommandLineCommand
|
|
|
15
17
|
this.options.Aliases.push('load');
|
|
16
18
|
this.options.Aliases.push('push');
|
|
17
19
|
|
|
18
|
-
|
|
19
20
|
this.options.CommandArguments.push({ Name: '<comprehension_file>', Description: 'The comprehension file path.' });
|
|
20
21
|
|
|
21
|
-
this.options.CommandOptions.push({ Name: '-p, --prefix [guid_prefix]', Description: 'GUID Prefix for the comprehension push.'});
|
|
22
|
-
this.options.CommandOptions.push({ Name: '-e, --entityguidprefix [entity_guid_prefix]', Description: 'GUID Prefix for each entity.'});
|
|
22
|
+
this.options.CommandOptions.push({ Name: '-p, --prefix [guid_prefix]', Description: 'GUID Prefix for the comprehension push.' });
|
|
23
|
+
this.options.CommandOptions.push({ Name: '-e, --entityguidprefix [entity_guid_prefix]', Description: 'GUID Prefix for each entity.' });
|
|
24
|
+
|
|
25
|
+
this.options.CommandOptions.push({ Name: '-a, --api_server [api_server]', Description: 'The API server URL.' });
|
|
26
|
+
this.options.CommandOptions.push({ Name: '-u, --api_username [api_username]', Description: 'The API username to authenticate with.' });
|
|
27
|
+
this.options.CommandOptions.push({ Name: '-w, --api_password [api_password]', Description: 'The API password to authenticate with.' });
|
|
28
|
+
|
|
29
|
+
this.options.CommandOptions.push({ Name: '--bulkupsert [bulk_upsert]', Description: 'Enable bulk upsert mode (true/false). Default: true.', DefaultValue: 'true' });
|
|
30
|
+
this.options.CommandOptions.push({ Name: '--batchsize [batch_size]', Description: 'Bulk upsert batch size. Default: 100.', DefaultValue: '100' });
|
|
31
|
+
this.options.CommandOptions.push({ Name: '--progressinterval [progress_interval]', Description: 'Per-entity progress log interval (records). Default: 100.', DefaultValue: '100' });
|
|
32
|
+
this.options.CommandOptions.push({ Name: '--metaprogressinterval [meta_progress_interval]', Description: 'Meta (cross-entity) progress log interval. Default: 0 (disabled).', DefaultValue: '0' });
|
|
33
|
+
this.options.CommandOptions.push({ Name: '--allowguidtruncation', Description: 'Allow automatic GUID prefix truncation when GUIDs exceed max length.' });
|
|
34
|
+
this.options.CommandOptions.push({ Name: '--logfile [logfile_path]', Description: 'Path to write log output.' });
|
|
23
35
|
|
|
24
36
|
this.addCommand();
|
|
25
37
|
|
|
26
38
|
this.comprehension = {};
|
|
27
39
|
}
|
|
28
40
|
|
|
41
|
+
_resolveConfig()
|
|
42
|
+
{
|
|
43
|
+
const tmpConfig = JSON.parse(JSON.stringify(this.fable.ProgramConfiguration));
|
|
44
|
+
|
|
45
|
+
// Apply command-line overrides for Source (API)
|
|
46
|
+
if (!tmpConfig.Source)
|
|
47
|
+
{
|
|
48
|
+
tmpConfig.Source = {};
|
|
49
|
+
}
|
|
50
|
+
if (this.CommandOptions.api_server)
|
|
51
|
+
{
|
|
52
|
+
tmpConfig.Source.ServerURL = this.CommandOptions.api_server;
|
|
53
|
+
}
|
|
54
|
+
if (this.CommandOptions.api_username)
|
|
55
|
+
{
|
|
56
|
+
tmpConfig.Source.UserID = this.CommandOptions.api_username;
|
|
57
|
+
}
|
|
58
|
+
if (this.CommandOptions.api_password)
|
|
59
|
+
{
|
|
60
|
+
tmpConfig.Source.Password = this.CommandOptions.api_password;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return tmpConfig;
|
|
64
|
+
}
|
|
65
|
+
|
|
29
66
|
runAdapter(pAnticipate, pAdapter, pDataMap, fMarshalRecord)
|
|
30
67
|
{
|
|
31
68
|
let tmpAdapter = this.fable.servicesMap.IntegrationAdapter[pAdapter];
|
|
@@ -76,56 +113,191 @@ class PushComprehensionsViaIntegration extends libCLICommandLineCommand
|
|
|
76
113
|
pushComprehension(fCallback)
|
|
77
114
|
{
|
|
78
115
|
let tmpComprehensionPath = this.ArgumentString;
|
|
116
|
+
let tmpConfig = this._resolveConfig();
|
|
79
117
|
|
|
80
|
-
let tmpAnticipate = this.fable.newAnticipate();
|
|
81
118
|
this.fable.log.info(`Pushing comprehension file [${tmpComprehensionPath}] to the Meadow Endpoints APIs.`);
|
|
82
119
|
|
|
120
|
+
// --- Setup REST client ---
|
|
121
|
+
this.fable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
|
|
122
|
+
|
|
123
|
+
let tmpRestClientOptions = {};
|
|
124
|
+
if (tmpConfig.Source && tmpConfig.Source.ServerURL)
|
|
125
|
+
{
|
|
126
|
+
tmpRestClientOptions.ServerURL = tmpConfig.Source.ServerURL;
|
|
127
|
+
}
|
|
128
|
+
if (tmpConfig.Source && tmpConfig.Source.UserID)
|
|
129
|
+
{
|
|
130
|
+
tmpRestClientOptions.UserID = tmpConfig.Source.UserID;
|
|
131
|
+
}
|
|
132
|
+
if (tmpConfig.Source && tmpConfig.Source.Password)
|
|
133
|
+
{
|
|
134
|
+
tmpRestClientOptions.Password = tmpConfig.Source.Password;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.fable.serviceManager.instantiateServiceProvider('MeadowCloneRestClient', tmpRestClientOptions);
|
|
138
|
+
|
|
139
|
+
// --- Initialize SessionManager if configured ---
|
|
140
|
+
let tmpSessionManager = libSessionManagerSetup.initializeSessionManager(this.fable, tmpConfig.SessionManager);
|
|
141
|
+
if (tmpSessionManager)
|
|
142
|
+
{
|
|
143
|
+
libSessionManagerSetup.connectSessionManagerToRestClient(this.fable, this.fable.MeadowCloneRestClient.restClient);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// --- Setup Integration Adapter service type ---
|
|
83
147
|
this.fable.log.info(`Initializing and configuring data integration adapters...`);
|
|
84
148
|
this.fable.serviceManager.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
85
149
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
150
|
+
// --- Resolve adapter options from CLI flags + config ---
|
|
151
|
+
let tmpBulkUpsertEnabled = (this.CommandOptions.bulkupsert !== 'false');
|
|
152
|
+
let tmpBatchSize = parseInt(this.CommandOptions.batchsize) || 100;
|
|
153
|
+
let tmpProgressInterval = parseInt(this.CommandOptions.progressinterval) || 100;
|
|
154
|
+
let tmpMetaProgressInterval = parseInt(this.CommandOptions.metaprogressinterval) || 0;
|
|
155
|
+
let tmpAllowGUIDTruncation = !!this.CommandOptions.allowguidtruncation;
|
|
156
|
+
|
|
157
|
+
// Build shared adapter options
|
|
158
|
+
let tmpAdapterOptions = {
|
|
159
|
+
SimpleMarshal: true,
|
|
160
|
+
ForceMarshal: true,
|
|
161
|
+
BulkUpsertBatchSize: tmpBatchSize,
|
|
162
|
+
RecordThresholdForBulkUpsert: tmpBulkUpsertEnabled ? 1000 : Infinity,
|
|
163
|
+
ProgressLogInterval: tmpProgressInterval,
|
|
164
|
+
AllowGUIDTruncation: tmpAllowGUIDTruncation
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
this.fable.Utility.waterfall(
|
|
168
|
+
[
|
|
169
|
+
(fStageComplete) =>
|
|
90
170
|
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
171
|
+
// Authenticate SessionManager sessions (if configured)
|
|
172
|
+
if (tmpSessionManager)
|
|
173
|
+
{
|
|
174
|
+
this.log.info('Authenticating SessionManager sessions...');
|
|
175
|
+
libSessionManagerSetup.authenticateSessions(this.fable,
|
|
176
|
+
(pError) =>
|
|
177
|
+
{
|
|
178
|
+
if (pError)
|
|
179
|
+
{
|
|
180
|
+
this.log.error('Error authenticating SessionManager sessions.', pError);
|
|
181
|
+
}
|
|
182
|
+
return fStageComplete();
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else
|
|
186
|
+
{
|
|
187
|
+
return fStageComplete();
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
(fStageComplete) =>
|
|
97
191
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
192
|
+
// Authenticate with the API server using built-in credentials
|
|
193
|
+
if (tmpConfig.Source && tmpConfig.Source.UserID && tmpConfig.Source.Password)
|
|
194
|
+
{
|
|
195
|
+
this.log.info('Authenticating with API server...');
|
|
196
|
+
this.fable.MeadowCloneRestClient.authenticate(
|
|
197
|
+
(pError, pResponse) =>
|
|
198
|
+
{
|
|
199
|
+
if (pError)
|
|
200
|
+
{
|
|
201
|
+
this.log.error('Error authenticating with API server.', pError);
|
|
202
|
+
}
|
|
203
|
+
else
|
|
204
|
+
{
|
|
205
|
+
this.log.info(`Authenticated with API server as [${tmpConfig.Source.UserID}] at [${tmpConfig.Source.ServerURL}]`);
|
|
206
|
+
}
|
|
207
|
+
return fStageComplete();
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else
|
|
211
|
+
{
|
|
212
|
+
this.log.info('No Source credentials configured; skipping built-in authentication.');
|
|
213
|
+
return fStageComplete();
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
(fStageComplete) =>
|
|
217
|
+
{
|
|
218
|
+
// Load comprehension file
|
|
219
|
+
try
|
|
220
|
+
{
|
|
221
|
+
this.fable.log.info(`Loading Comprehension File...`);
|
|
222
|
+
tmpComprehensionPath = libPath.resolve(tmpComprehensionPath);
|
|
223
|
+
this.comprehension = require(tmpComprehensionPath);
|
|
224
|
+
return fStageComplete();
|
|
225
|
+
}
|
|
226
|
+
catch (pError)
|
|
227
|
+
{
|
|
228
|
+
this.fable.log.error(`Error loading comprehension file [${tmpComprehensionPath}]: ${pError}`, pError);
|
|
229
|
+
return fStageComplete(pError);
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
(fStageComplete) =>
|
|
233
|
+
{
|
|
234
|
+
this.fable.log.info(`Wiring up Integration Adapters...`);
|
|
107
235
|
|
|
108
|
-
|
|
236
|
+
let tmpIntegrationAdapterSet = Object.keys(this.comprehension);
|
|
109
237
|
|
|
110
|
-
|
|
111
|
-
|
|
238
|
+
// Count total records for meta progress tracking
|
|
239
|
+
let tmpTotalRecords = 0;
|
|
112
240
|
for (let i = 0; i < tmpIntegrationAdapterSet.length; i++)
|
|
113
241
|
{
|
|
114
242
|
let tmpAdapterKey = tmpIntegrationAdapterSet[i];
|
|
115
|
-
|
|
116
|
-
|
|
243
|
+
if (this.comprehension[tmpAdapterKey] && typeof(this.comprehension[tmpAdapterKey]) === 'object')
|
|
244
|
+
{
|
|
245
|
+
tmpTotalRecords += Object.keys(this.comprehension[tmpAdapterKey]).length;
|
|
246
|
+
}
|
|
117
247
|
}
|
|
118
|
-
}
|
|
119
|
-
catch (pError)
|
|
120
|
-
{
|
|
121
|
-
this.fable.log.error(`Error wiring up integration adapters: ${pError}`, pError);
|
|
122
|
-
return fCallback(pError);
|
|
123
|
-
}
|
|
124
248
|
|
|
125
|
-
|
|
126
|
-
|
|
249
|
+
// Start meta progress tracker if interval is configured
|
|
250
|
+
let tmpMetaProgressHash = false;
|
|
251
|
+
if (tmpMetaProgressInterval > 0 && tmpTotalRecords > 0)
|
|
252
|
+
{
|
|
253
|
+
this.fable.instantiateServiceProviderIfNotExists('ProgressTrackerSet');
|
|
254
|
+
tmpMetaProgressHash = this.fable.getUUID();
|
|
255
|
+
this.fable.ProgressTrackerSet.createProgressTracker(tmpMetaProgressHash, tmpTotalRecords);
|
|
256
|
+
this.fable.ProgressTrackerSet.startProgressTracker(tmpMetaProgressHash);
|
|
257
|
+
this.fable.log.info(`Meta progress: ${tmpTotalRecords} total records across ${tmpIntegrationAdapterSet.length} entities.`);
|
|
258
|
+
}
|
|
127
259
|
|
|
128
|
-
|
|
260
|
+
let tmpAnticipate = this.fable.newAnticipate();
|
|
261
|
+
|
|
262
|
+
try
|
|
263
|
+
{
|
|
264
|
+
for (let i = 0; i < tmpIntegrationAdapterSet.length; i++)
|
|
265
|
+
{
|
|
266
|
+
let tmpAdapterKey = tmpIntegrationAdapterSet[i];
|
|
267
|
+
let tmpAdapter = libIntegrationAdapter.getAdapter(this.fable, tmpAdapterKey, this.getCapitalLettersAsString(tmpAdapterKey), tmpAdapterOptions);
|
|
268
|
+
|
|
269
|
+
// Inject the REST client
|
|
270
|
+
tmpAdapter.setRestClient(this.fable.MeadowCloneRestClient);
|
|
271
|
+
|
|
272
|
+
// Wire up meta progress tracking
|
|
273
|
+
if (tmpMetaProgressHash)
|
|
274
|
+
{
|
|
275
|
+
tmpAdapter.MetaProgressTrackerHash = tmpMetaProgressHash;
|
|
276
|
+
tmpAdapter.MetaProgressTrackerLogInterval = tmpMetaProgressInterval;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.runAdapter(tmpAnticipate, tmpAdapterKey, this.comprehension[tmpAdapterKey]);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (pError)
|
|
283
|
+
{
|
|
284
|
+
this.fable.log.error(`Error wiring up integration adapters: ${pError}`, pError);
|
|
285
|
+
return fStageComplete(pError);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
tmpAnticipate.wait(
|
|
289
|
+
(pError) =>
|
|
290
|
+
{
|
|
291
|
+
// End meta progress tracker
|
|
292
|
+
if (tmpMetaProgressHash)
|
|
293
|
+
{
|
|
294
|
+
this.fable.ProgressTrackerSet.endProgressTracker(tmpMetaProgressHash);
|
|
295
|
+
this.fable.ProgressTrackerSet.logProgressTrackerStatus(tmpMetaProgressHash);
|
|
296
|
+
}
|
|
297
|
+
return fStageComplete(pError);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
],
|
|
129
301
|
(pError) =>
|
|
130
302
|
{
|
|
131
303
|
if (pError)
|
|
@@ -140,7 +312,7 @@ class PushComprehensionsViaIntegration extends libCLICommandLineCommand
|
|
|
140
312
|
|
|
141
313
|
onRunAsync(fCallback)
|
|
142
314
|
{
|
|
143
|
-
return this.pushComprehension((pError)=>
|
|
315
|
+
return this.pushComprehension((pError) =>
|
|
144
316
|
{
|
|
145
317
|
return fCallback(pError);
|
|
146
318
|
});
|
|
@@ -155,6 +155,52 @@ class MeadowCloneRestClient extends libFableServiceProviderBase
|
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
upsertEntities(pEntity, pRecordArray, fCallback)
|
|
159
|
+
{
|
|
160
|
+
let tmpRequestOptions = (
|
|
161
|
+
{
|
|
162
|
+
url: `${this.serverURL}${pEntity}s/Upserts`,
|
|
163
|
+
body: pRecordArray,
|
|
164
|
+
});
|
|
165
|
+
tmpRequestOptions = this._prepareRequestOptions(tmpRequestOptions);
|
|
166
|
+
|
|
167
|
+
this.restClient.putJSON(tmpRequestOptions,
|
|
168
|
+
(pError, pResponse, pBody) =>
|
|
169
|
+
{
|
|
170
|
+
if (pError)
|
|
171
|
+
{
|
|
172
|
+
this.log.error(`Error bulk upserting ${pEntity} records: ${pError.message}`);
|
|
173
|
+
}
|
|
174
|
+
return fCallback(pError, pBody);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
getEntityByGUID(pEntity, pGUID, fCallback)
|
|
179
|
+
{
|
|
180
|
+
// Meadow's "ReadBy" endpoint uses the plural entity name with pagination:
|
|
181
|
+
// GET /{Entity}s/By/GUID{Entity}/{Value}/{Start}/{Cap}
|
|
182
|
+
let tmpRequestOptions = (
|
|
183
|
+
{
|
|
184
|
+
url: `${this.serverURL}${pEntity}s/By/GUID${pEntity}/${pGUID}/0/1`,
|
|
185
|
+
});
|
|
186
|
+
tmpRequestOptions = this._prepareRequestOptions(tmpRequestOptions);
|
|
187
|
+
|
|
188
|
+
return this.restClient.getJSON(tmpRequestOptions,
|
|
189
|
+
(pError, pResponse, pBody) =>
|
|
190
|
+
{
|
|
191
|
+
if (pError)
|
|
192
|
+
{
|
|
193
|
+
this.log.error(`Error getting ${pEntity} by GUID [${pGUID}]: ${pError.message}`);
|
|
194
|
+
}
|
|
195
|
+
// The /By/ endpoint returns an array; extract the first record for convenience.
|
|
196
|
+
if (Array.isArray(pBody) && pBody.length > 0)
|
|
197
|
+
{
|
|
198
|
+
return fCallback(pError, pBody[0]);
|
|
199
|
+
}
|
|
200
|
+
return fCallback(pError, pBody);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
158
204
|
deleteEntity(pEntity, pIDRecord, fCallback)
|
|
159
205
|
{
|
|
160
206
|
let tmpRequestOptions = (
|
|
@@ -448,9 +448,10 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
448
448
|
tmpSyncState.EstimatedRecordCount = tmpSyncState.Server.RecordCount - tmpSyncState.Local.RecordCount;
|
|
449
449
|
|
|
450
450
|
// Apply MaxRecordsPerEntity cap if configured
|
|
451
|
-
|
|
451
|
+
tmpSyncState.RecordCap = (this.MaxRecordsPerEntity > 0)
|
|
452
452
|
? Math.min(tmpSyncState.Server.RecordCount, this.MaxRecordsPerEntity)
|
|
453
453
|
: tmpSyncState.Server.RecordCount;
|
|
454
|
+
let tmpRecordCap = tmpSyncState.RecordCap;
|
|
454
455
|
|
|
455
456
|
if (this.MaxRecordsPerEntity > 0 && tmpSyncState.EstimatedRecordCount > this.MaxRecordsPerEntity)
|
|
456
457
|
{
|
|
@@ -617,7 +618,7 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
617
618
|
|
|
618
619
|
const fFetchPage = () =>
|
|
619
620
|
{
|
|
620
|
-
if (tmpTotalFetched >=
|
|
621
|
+
if (tmpTotalFetched >= tmpSyncState.RecordCap)
|
|
621
622
|
{
|
|
622
623
|
return fSyncComplete();
|
|
623
624
|
}
|