meadow-integration 1.0.31 → 1.0.33

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.31",
3
+ "version": "1.0.33",
4
4
  "description": "Meadow Data Integration",
5
5
  "bin": {
6
6
  "mdwint": "source/cli/Meadow-Integration-CLI-Run.js"
@@ -43,15 +43,15 @@
43
43
  "fable": "^3.1.70",
44
44
  "fable-serviceproviderbase": "^3.0.19",
45
45
  "fast-xml-parser": "^4.4.1",
46
- "meadow": "^2.0.33",
47
- "meadow-connection-mssql": "^1.0.16",
48
- "meadow-connection-mysql": "^1.0.14",
46
+ "meadow": "^2.0.35",
47
+ "meadow-connection-mssql": "^1.0.19",
48
+ "meadow-connection-mysql": "^1.0.17",
49
49
  "orator": "^6.0.4",
50
50
  "orator-serviceserver-restify": "^2.0.10",
51
51
  "pict-section-flow": "^0.0.17",
52
52
  "pict-service-commandlineutility": "^1.0.19",
53
53
  "pict-sessionmanager": "^1.0.2",
54
- "pict-view": "^1.0.67",
54
+ "pict-view": "^1.0.68",
55
55
  "xlsx": "^0.18.5"
56
56
  }
57
57
  }
@@ -86,18 +86,32 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
86
86
  this.log.warn(`${this.EntitySchema.TableName}: createTable returned error: ${pCreateError}`);
87
87
  }
88
88
 
89
+ // Sync-entity init intentionally does not create indexes here.
90
+ // In the DataCloner flow there is no MeadowConnectionManager
91
+ // service registered, so the legacy createIndex path was dead
92
+ // code that just logged noise ("No connection manager
93
+ // available; skipping index creation for X") for every table.
94
+ // Indexes are created via the provider's own createIndices /
95
+ // generateCreateIndexStatements methods, invoked by the
96
+ // DataCloner's dedicated /indices/create endpoint after the
97
+ // initial sync is complete — that's the point where it makes
98
+ // sense to build indexes, since they're expensive on populated
99
+ // tables.
100
+ //
101
+ // Preserve the legacy MeadowConnectionManager path for the CLI
102
+ // Meadow-Integration-Command-DataClone.js flow (which does
103
+ // register that service), but do it silently when neither
104
+ // indexable column nor connection manager is available.
89
105
  const tmpGUIDColumn = this.EntitySchema.Columns.find((c) => c.DataType == 'GUID');
90
106
  const tmpDeletedColumn = this.EntitySchema.Columns.find((c) => c.Column == 'Deleted');
91
107
 
92
- if (!tmpGUIDColumn && !tmpDeletedColumn)
93
- {
94
- this.log.info(`No GUID or Deleted columns for ${this.EntitySchema.TableName}; skipping index creation`);
95
- return fCallback(pCreateError);
96
- }
108
+ let tmpCanCreateIndexes = (tmpGUIDColumn || tmpDeletedColumn)
109
+ && this.fable.MeadowConnectionManager
110
+ && this.fable.MeadowConnectionManager.ConnectionPool
111
+ && typeof(this.fable.MeadowConnectionManager.createIndex) === 'function';
97
112
 
98
- if (!this.fable.MeadowConnectionManager || !this.fable.MeadowConnectionManager.ConnectionPool)
113
+ if (!tmpCanCreateIndexes)
99
114
  {
100
- this.log.info(`No connection manager available; skipping index creation for ${this.EntitySchema.TableName}`);
101
115
  return fCallback(pCreateError);
102
116
  }
103
117
 
@@ -458,7 +472,13 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
458
472
  },
459
473
  (fStageComplete) =>
460
474
  {
461
- tmpSyncState.EstimatedRecordCount = tmpSyncState.Server.RecordCount - tmpSyncState.Local.RecordCount;
475
+ // The raw diff can be negative when local has more records
476
+ // than the server (e.g. records were deleted server-side but
477
+ // the local copy still has them). Clamp the estimate to 0
478
+ // so progress trackers and downstream reports never show a
479
+ // negative total.
480
+ let tmpRawEstimate = tmpSyncState.Server.RecordCount - tmpSyncState.Local.RecordCount;
481
+ tmpSyncState.EstimatedRecordCount = Math.max(0, tmpRawEstimate);
462
482
 
463
483
  // Apply MaxRecordsPerEntity cap if configured
464
484
  tmpSyncState.RecordCap = (this.MaxRecordsPerEntity > 0)
@@ -474,6 +494,29 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
474
494
  this.operation.createProgressTracker(tmpSyncState.EstimatedRecordCount, `FullSync-${this.EntitySchema.TableName}`);
475
495
  this.operation.printProgressTrackerStatus(`FullSync-${this.EntitySchema.TableName}`);
476
496
 
497
+ // Fast path: if there is nothing new to pull (estimate is
498
+ // zero or negative), skip the download phase entirely.
499
+ // Running the paginated loop would otherwise make one or
500
+ // more requests just to receive an empty response and then
501
+ // short-circuit with an "Error: Records depleted!" log —
502
+ // noisy and a waste of round-trips. Zero out RecordCap
503
+ // as well so the advanced-ID-pagination loop
504
+ // (which gates on RecordCap, not URLPartials) also skips.
505
+ if (tmpSyncState.EstimatedRecordCount <= 0)
506
+ {
507
+ tmpSyncState.URLPartials = [];
508
+ tmpSyncState.RecordCap = 0;
509
+ if (tmpRawEstimate < 0)
510
+ {
511
+ 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.`);
512
+ }
513
+ else
514
+ {
515
+ this.fable.log.info(`${this.EntitySchema.TableName}: record counts match (${tmpSyncState.Server.RecordCount}); nothing to download.`);
516
+ }
517
+ return fStageComplete();
518
+ }
519
+
477
520
  if (this.UseAdvancedIDPagination)
478
521
  {
479
522
  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}` : ''})`);
@@ -80,19 +80,23 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
80
80
  {
81
81
  return this.Meadow.provider.getProvider().createTable(this.EntitySchema, (pCreateError) =>
82
82
  {
83
-
83
+ // Sync-entity init intentionally does not create indexes here
84
+ // in the DataCloner flow. See the comment in
85
+ // Meadow-Service-Sync-Entity-Initial.js for the rationale —
86
+ // indexes go through the provider's createIndices path
87
+ // (triggered by DataCloner's /indices/create endpoint) rather
88
+ // than via MeadowConnectionManager, which isn't registered in
89
+ // the DataCloner service container.
84
90
  const tmpGUIDColumn = this.EntitySchema.Columns.find((c) => c.DataType == 'GUID');
85
91
  const tmpDeletedColumn = this.EntitySchema.Columns.find((c) => c.Column == 'Deleted');
86
92
 
87
- if (!tmpGUIDColumn && !tmpDeletedColumn)
88
- {
89
- this.log.info(`No GUID or Deleted columns for ${this.EntitySchema.TableName}; skipping index creation`);
90
- return fCallback(pCreateError);
91
- }
93
+ let tmpCanCreateIndexes = (tmpGUIDColumn || tmpDeletedColumn)
94
+ && this.fable.MeadowConnectionManager
95
+ && this.fable.MeadowConnectionManager.ConnectionPool
96
+ && typeof(this.fable.MeadowConnectionManager.createIndex) === 'function';
92
97
 
93
- if (!this.fable.MeadowConnectionManager || !this.fable.MeadowConnectionManager.ConnectionPool)
98
+ if (!tmpCanCreateIndexes)
94
99
  {
95
- this.log.info(`No connection manager available; skipping index creation for ${this.EntitySchema.TableName}`);
96
100
  return fCallback(pCreateError);
97
101
  }
98
102