meadow-integration 1.0.10 → 1.0.11
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
|
@@ -45,6 +45,8 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
45
45
|
this.Meadow = false;
|
|
46
46
|
|
|
47
47
|
this.operation = new libMeadowOperation(this.fable);
|
|
48
|
+
|
|
49
|
+
this.skipSync = false;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
initialize(fCallback)
|
|
@@ -72,6 +74,33 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
72
74
|
|
|
73
75
|
return tmpProvider.createTable(this.EntitySchema, (pCreateError) =>
|
|
74
76
|
{
|
|
77
|
+
let fValidateAndCallback = (pPriorError) =>
|
|
78
|
+
{
|
|
79
|
+
// Validate local table schema with a lightweight read
|
|
80
|
+
const tmpValidationQuery = this.Meadow.query;
|
|
81
|
+
tmpValidationQuery.setCap(1);
|
|
82
|
+
tmpValidationQuery.setDisableDeleteTracking(true);
|
|
83
|
+
this.Meadow.doRead(tmpValidationQuery,
|
|
84
|
+
(pReadError) =>
|
|
85
|
+
{
|
|
86
|
+
if (pReadError)
|
|
87
|
+
{
|
|
88
|
+
let tmpErrorStr = (typeof(pReadError) === 'string') ? pReadError : JSON.stringify(pReadError);
|
|
89
|
+
// Only skip sync for schema-specific errors (invalid column/object name)
|
|
90
|
+
// Generic provider errors (e.g. prepared statement failures) should not block sync
|
|
91
|
+
if (tmpErrorStr.indexOf('Invalid column') > -1 || tmpErrorStr.indexOf('Invalid object') > -1 || tmpErrorStr.indexOf('no such column') > -1 || tmpErrorStr.indexOf('no such table') > -1)
|
|
92
|
+
{
|
|
93
|
+
this.log.warn(`${this.EntitySchema.TableName}: local table schema validation failed (${pReadError}); this entity will be skipped during sync.`);
|
|
94
|
+
this.skipSync = true;
|
|
95
|
+
}
|
|
96
|
+
else
|
|
97
|
+
{
|
|
98
|
+
this.log.warn(`${this.EntitySchema.TableName}: validation read returned error (${pReadError}); sync will proceed.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return fCallback(pPriorError);
|
|
102
|
+
});
|
|
103
|
+
};
|
|
75
104
|
if (pCreateError)
|
|
76
105
|
{
|
|
77
106
|
this.log.warn(`${this.EntitySchema.TableName}: createTable returned error: ${pCreateError}`);
|
|
@@ -83,13 +112,13 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
83
112
|
if (!tmpGUIDColumn && !tmpDeletedColumn)
|
|
84
113
|
{
|
|
85
114
|
this.log.info(`No GUID or Deleted columns for ${this.EntitySchema.TableName}; skipping index creation`);
|
|
86
|
-
return
|
|
115
|
+
return fValidateAndCallback(pCreateError);
|
|
87
116
|
}
|
|
88
117
|
|
|
89
118
|
if (!this.fable.MeadowConnectionManager || !this.fable.MeadowConnectionManager.ConnectionPool)
|
|
90
119
|
{
|
|
91
120
|
this.log.info(`No connection manager available; skipping index creation for ${this.EntitySchema.TableName}`);
|
|
92
|
-
return
|
|
121
|
+
return fValidateAndCallback(pCreateError);
|
|
93
122
|
}
|
|
94
123
|
|
|
95
124
|
let tmpAnticipate = this.fable.newAnticipate();
|
|
@@ -115,7 +144,7 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
115
144
|
{
|
|
116
145
|
this.log.warn(`${this.EntitySchema.TableName}: Index creation error: ${pIndexError}`);
|
|
117
146
|
}
|
|
118
|
-
return
|
|
147
|
+
return fValidateAndCallback(pIndexError || pCreateError);
|
|
119
148
|
});
|
|
120
149
|
});
|
|
121
150
|
}
|
|
@@ -301,6 +330,12 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
301
330
|
|
|
302
331
|
sync(fCallback)
|
|
303
332
|
{
|
|
333
|
+
if (this.skipSync)
|
|
334
|
+
{
|
|
335
|
+
this.log.warn(`Skipping sync for ${this.EntitySchema.TableName} -- local table schema does not match expected schema.`);
|
|
336
|
+
return fCallback();
|
|
337
|
+
}
|
|
338
|
+
|
|
304
339
|
this.operation.createTimeStamp('EntityInitialSync');
|
|
305
340
|
|
|
306
341
|
this.log.info(`Syncing ${this.EntitySchema.TableName} (PageSize: ${this.PageSize}, SyncDeletedRecords: ${this.SyncDeletedRecords})`);
|
|
@@ -377,7 +412,8 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
377
412
|
{
|
|
378
413
|
if (pError)
|
|
379
414
|
{
|
|
380
|
-
|
|
415
|
+
this.fable.log.warn(`Could not get server max entity ID for ${this.EntitySchema.TableName} (${pError}); continuing sync.`);
|
|
416
|
+
return fStageComplete();
|
|
381
417
|
}
|
|
382
418
|
if (pBody && pBody.hasOwnProperty(this.DefaultIdentifier))
|
|
383
419
|
{
|
|
@@ -394,7 +430,9 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
394
430
|
{
|
|
395
431
|
if (pError)
|
|
396
432
|
{
|
|
397
|
-
|
|
433
|
+
this.fable.log.warn(`Could not get server count for ${this.EntitySchema.TableName} (${pError}); estimating from max ID.`);
|
|
434
|
+
tmpSyncState.Server.RecordCount = tmpSyncState.Server.MaxIDEntity > 0 ? tmpSyncState.Server.MaxIDEntity : 0;
|
|
435
|
+
return fStageComplete();
|
|
398
436
|
}
|
|
399
437
|
if (pBody && pBody.hasOwnProperty('Count'))
|
|
400
438
|
{
|
|
@@ -451,7 +489,7 @@ class MeadowSyncEntityInitial extends libFableServiceProviderBase
|
|
|
451
489
|
this.fable.log.error(`${this.EntitySchema.TableName}: page ${tmpPageIndex} download error: ${pDownloadError}`);
|
|
452
490
|
return fDownloadComplete();
|
|
453
491
|
}
|
|
454
|
-
if (pBody && pBody.length > 0)
|
|
492
|
+
if (pBody && Array.isArray(pBody) && pBody.length > 0)
|
|
455
493
|
{
|
|
456
494
|
this.fable.Utility.eachLimit(pBody, 5,
|
|
457
495
|
(pEntityRecord, fEntitySyncComplete) =>
|
|
@@ -45,6 +45,8 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
45
45
|
this.Meadow = false;
|
|
46
46
|
|
|
47
47
|
this.operation = new libMeadowOperation(this.fable);
|
|
48
|
+
|
|
49
|
+
this.skipSync = false;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
initialize(fCallback)
|
|
@@ -60,19 +62,46 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
60
62
|
{
|
|
61
63
|
return this.Meadow.provider.getProvider().createTable(this.EntitySchema, (pCreateError) =>
|
|
62
64
|
{
|
|
65
|
+
let fValidateAndCallback = (pPriorError) =>
|
|
66
|
+
{
|
|
67
|
+
// Validate local table schema with a lightweight read
|
|
68
|
+
const tmpValidationQuery = this.Meadow.query;
|
|
69
|
+
tmpValidationQuery.setCap(1);
|
|
70
|
+
tmpValidationQuery.setDisableDeleteTracking(true);
|
|
71
|
+
this.Meadow.doRead(tmpValidationQuery,
|
|
72
|
+
(pReadError) =>
|
|
73
|
+
{
|
|
74
|
+
if (pReadError)
|
|
75
|
+
{
|
|
76
|
+
let tmpErrorStr = (typeof(pReadError) === 'string') ? pReadError : JSON.stringify(pReadError);
|
|
77
|
+
// Only skip sync for schema-specific errors (invalid column/object name)
|
|
78
|
+
// Generic provider errors (e.g. prepared statement failures) should not block sync
|
|
79
|
+
if (tmpErrorStr.indexOf('Invalid column') > -1 || tmpErrorStr.indexOf('Invalid object') > -1 || tmpErrorStr.indexOf('no such column') > -1 || tmpErrorStr.indexOf('no such table') > -1)
|
|
80
|
+
{
|
|
81
|
+
this.log.warn(`${this.EntitySchema.TableName}: local table schema validation failed (${pReadError}); this entity will be skipped during sync.`);
|
|
82
|
+
this.skipSync = true;
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
{
|
|
86
|
+
this.log.warn(`${this.EntitySchema.TableName}: validation read returned error (${pReadError}); sync will proceed.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return fCallback(pPriorError);
|
|
90
|
+
});
|
|
91
|
+
};
|
|
63
92
|
const tmpGUIDColumn = this.EntitySchema.Columns.find((c) => c.DataType == 'GUID');
|
|
64
93
|
const tmpDeletedColumn = this.EntitySchema.Columns.find((c) => c.Column == 'Deleted');
|
|
65
94
|
|
|
66
95
|
if (!tmpGUIDColumn && !tmpDeletedColumn)
|
|
67
96
|
{
|
|
68
97
|
this.log.info(`No GUID or Deleted columns for ${this.EntitySchema.TableName}; skipping index creation`);
|
|
69
|
-
return
|
|
98
|
+
return fValidateAndCallback(pCreateError);
|
|
70
99
|
}
|
|
71
100
|
|
|
72
101
|
if (!this.fable.MeadowConnectionManager || !this.fable.MeadowConnectionManager.ConnectionPool)
|
|
73
102
|
{
|
|
74
103
|
this.log.info(`No connection manager available; skipping index creation for ${this.EntitySchema.TableName}`);
|
|
75
|
-
return
|
|
104
|
+
return fValidateAndCallback(pCreateError);
|
|
76
105
|
}
|
|
77
106
|
|
|
78
107
|
let tmpAnticipate = this.fable.newAnticipate();
|
|
@@ -92,7 +121,7 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
92
121
|
return this.fable.MeadowConnectionManager.createIndex(this.EntitySchema, tmpDeletedColumn, false, fNext);
|
|
93
122
|
});
|
|
94
123
|
}
|
|
95
|
-
tmpAnticipate.wait(
|
|
124
|
+
tmpAnticipate.wait((pIndexError) => { return fValidateAndCallback(pCreateError); });
|
|
96
125
|
});
|
|
97
126
|
}
|
|
98
127
|
return fCallback();
|
|
@@ -288,7 +317,7 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
288
317
|
this.fable.log.error(`Error getting URL Partial [${tmpURLPartial}]: ${pDownloadError}`, { Error: pDownloadError });
|
|
289
318
|
return fNext();
|
|
290
319
|
}
|
|
291
|
-
if (pBody && pBody.length > 0)
|
|
320
|
+
if (pBody && Array.isArray(pBody) && pBody.length > 0)
|
|
292
321
|
{
|
|
293
322
|
for (let i = 0; i < pBody.length; i++)
|
|
294
323
|
{
|
|
@@ -420,6 +449,12 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
420
449
|
|
|
421
450
|
sync(fCallback)
|
|
422
451
|
{
|
|
452
|
+
if (this.skipSync)
|
|
453
|
+
{
|
|
454
|
+
this.log.warn(`Skipping sync for ${this.EntitySchema.TableName} -- local table schema does not match expected schema.`);
|
|
455
|
+
return fCallback();
|
|
456
|
+
}
|
|
457
|
+
|
|
423
458
|
this.operation.createTimeStamp('EntityOngoingSync');
|
|
424
459
|
|
|
425
460
|
let tmpAnticipate = this.fable.newAnticipate();
|
|
@@ -551,8 +586,8 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
551
586
|
{
|
|
552
587
|
if (pError)
|
|
553
588
|
{
|
|
554
|
-
this.fable.log.
|
|
555
|
-
return fStageComplete(
|
|
589
|
+
this.fable.log.warn(`Could not get server max entity ID for ${this.EntitySchema.TableName} (${pError}); continuing sync.`);
|
|
590
|
+
return fStageComplete();
|
|
556
591
|
}
|
|
557
592
|
if (pBody && pBody.hasOwnProperty(this.DefaultIdentifier))
|
|
558
593
|
{
|
|
@@ -574,8 +609,8 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
574
609
|
{
|
|
575
610
|
if (pError)
|
|
576
611
|
{
|
|
577
|
-
this.fable.log.
|
|
578
|
-
return fStageComplete(
|
|
612
|
+
this.fable.log.warn(`Could not get server max UpdateDate for ${this.EntitySchema.TableName} (${pError}); will sync by ID only.`);
|
|
613
|
+
return fStageComplete();
|
|
579
614
|
}
|
|
580
615
|
if (pBody && pBody.hasOwnProperty(this.DefaultIdentifier))
|
|
581
616
|
{
|
|
@@ -597,8 +632,9 @@ class MeadowSyncEntityOngoing extends libFableServiceProviderBase
|
|
|
597
632
|
{
|
|
598
633
|
if (pError)
|
|
599
634
|
{
|
|
600
|
-
this.fable.log.
|
|
601
|
-
|
|
635
|
+
this.fable.log.warn(`Could not get server count for ${this.EntitySchema.TableName} (${pError}); estimating from max ID.`);
|
|
636
|
+
tmpSyncState.Server.RecordCount = tmpSyncState.Server.MaxIDEntity > 0 ? tmpSyncState.Server.MaxIDEntity : 0;
|
|
637
|
+
return fStageComplete();
|
|
602
638
|
}
|
|
603
639
|
if (pBody && pBody.hasOwnProperty('Count'))
|
|
604
640
|
{
|