retold-data-service 2.0.33 → 2.0.34
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/_cover.md +1 -1
- package/docs/_version.json +7 -0
- package/docs/css/docuserve.css +277 -23
- package/docs/endpoints.md +2 -2
- package/docs/index.html +2 -2
- package/docs/initialization.md +6 -6
- package/docs/retold-catalog.json +18 -18
- package/docs/retold-keyword-index.json +1 -1
- package/docs/schema-definition.md +6 -6
- package/package.json +3 -2
- package/source/services/data-cloner/DataCloner-Command-Headless.js +3 -1
- package/source/services/data-cloner/DataCloner-Command-Sync.js +30 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Sync.js +68 -5
- package/source/services/data-cloner/web/data-cloner.js +91 -11
- package/source/services/data-cloner/web/data-cloner.js.map +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
|
@@ -3315,7 +3315,7 @@
|
|
|
3315
3315
|
12: [function (require, module, exports) {
|
|
3316
3316
|
module.exports = {
|
|
3317
3317
|
"name": "pict-view",
|
|
3318
|
-
"version": "1.0.
|
|
3318
|
+
"version": "1.0.68",
|
|
3319
3319
|
"description": "Pict View Base Class",
|
|
3320
3320
|
"main": "source/Pict-View.js",
|
|
3321
3321
|
"scripts": {
|
|
@@ -3345,8 +3345,8 @@
|
|
|
3345
3345
|
"@eslint/js": "^9.39.1",
|
|
3346
3346
|
"browser-env": "^3.3.0",
|
|
3347
3347
|
"eslint": "^9.39.1",
|
|
3348
|
-
"pict": "^1.0.
|
|
3349
|
-
"quackage": "^1.0.
|
|
3348
|
+
"pict": "^1.0.363",
|
|
3349
|
+
"quackage": "^1.0.65",
|
|
3350
3350
|
"typescript": "^5.9.3"
|
|
3351
3351
|
},
|
|
3352
3352
|
"mocha": {
|
|
@@ -3361,7 +3361,7 @@
|
|
|
3361
3361
|
"watch-ignore": ["lib/vendor"]
|
|
3362
3362
|
},
|
|
3363
3363
|
"dependencies": {
|
|
3364
|
-
"fable": "^3.1.
|
|
3364
|
+
"fable": "^3.1.67",
|
|
3365
3365
|
"fable-serviceproviderbase": "^3.0.19"
|
|
3366
3366
|
}
|
|
3367
3367
|
};
|
|
@@ -4139,6 +4139,10 @@
|
|
|
4139
4139
|
// Execute the developer-overridable post-render behavior
|
|
4140
4140
|
tmpView.onAfterRender(tmpEvent.Data.Renderable);
|
|
4141
4141
|
}
|
|
4142
|
+
// Queue is drained and nested child renders have each cleaned up
|
|
4143
|
+
// their own transactions; remove this root render's entry from
|
|
4144
|
+
// the tracking map so it does not leak.
|
|
4145
|
+
this.pict.TransactionTracking.unregisterTransaction(pRenderable.TransactionHash);
|
|
4142
4146
|
}
|
|
4143
4147
|
return true;
|
|
4144
4148
|
}
|
|
@@ -4150,9 +4154,17 @@
|
|
|
4150
4154
|
* @param {Renderable} pRenderable - The renderable that was rendered.
|
|
4151
4155
|
*/
|
|
4152
4156
|
onAfterRenderAsync(fCallback, pRenderable) {
|
|
4157
|
+
// NOTE: this.onAfterRender(pRenderable) will itself clear the
|
|
4158
|
+
// transaction queue and unregister the transaction if this view is
|
|
4159
|
+
// the root renderable - see onAfterRender above. So by the time the
|
|
4160
|
+
// loop below runs, the queue is already empty and there is nothing
|
|
4161
|
+
// to drain. Keeping the async queue walk here defensively in case
|
|
4162
|
+
// future subclasses override onAfterRender in ways that skip the
|
|
4163
|
+
// drain, but the common path is now "sync drain, async no-op".
|
|
4153
4164
|
this.onAfterRender(pRenderable);
|
|
4154
4165
|
const tmpAnticipate = this.fable.newAnticipate();
|
|
4155
|
-
|
|
4166
|
+
const tmpIsRootRenderable = pRenderable && pRenderable.RootRenderableViewHash === this.Hash;
|
|
4167
|
+
if (tmpIsRootRenderable) {
|
|
4156
4168
|
const queue = this.pict.TransactionTracking.clearTransactionQueue(pRenderable.TransactionHash) || [];
|
|
4157
4169
|
for (const event of queue) {
|
|
4158
4170
|
/** @type {PictView} */
|
|
@@ -4169,7 +4181,18 @@
|
|
|
4169
4181
|
// Execute the developer-overridable post-render behavior
|
|
4170
4182
|
}
|
|
4171
4183
|
}
|
|
4172
|
-
return tmpAnticipate.wait(
|
|
4184
|
+
return tmpAnticipate.wait(pError => {
|
|
4185
|
+
// Nested virtual-assignment children have now settled their own
|
|
4186
|
+
// onAfterRenderAsync chains (and unregistered their own
|
|
4187
|
+
// transactions along the way). Ensure this root render's entry
|
|
4188
|
+
// is also gone - unregisterTransaction is a no-op if the sync
|
|
4189
|
+
// onAfterRender above already removed it, so this is safe to
|
|
4190
|
+
// call unconditionally on the root path.
|
|
4191
|
+
if (tmpIsRootRenderable && pRenderable && pRenderable.TransactionHash) {
|
|
4192
|
+
this.pict.TransactionTracking.unregisterTransaction(pRenderable.TransactionHash);
|
|
4193
|
+
}
|
|
4194
|
+
return fCallback(pError);
|
|
4195
|
+
});
|
|
4173
4196
|
}
|
|
4174
4197
|
|
|
4175
4198
|
/**
|
|
@@ -7513,6 +7536,21 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7513
7536
|
constructor(pFable, pOptions, pServiceHash) {
|
|
7514
7537
|
super(pFable, pOptions, pServiceHash);
|
|
7515
7538
|
}
|
|
7539
|
+
onSyncModeChanged() {
|
|
7540
|
+
let tmpMode = document.querySelector('input[name="syncMode"]:checked').value;
|
|
7541
|
+
|
|
7542
|
+
// Hide all mode-specific option panels
|
|
7543
|
+
let tmpPanels = document.querySelectorAll('[id^="syncModeOptions-"]');
|
|
7544
|
+
for (let i = 0; i < tmpPanels.length; i++) {
|
|
7545
|
+
tmpPanels[i].style.display = 'none';
|
|
7546
|
+
}
|
|
7547
|
+
|
|
7548
|
+
// Show the panel for the selected mode (if one exists)
|
|
7549
|
+
let tmpPanel = document.getElementById('syncModeOptions-' + tmpMode);
|
|
7550
|
+
if (tmpPanel) {
|
|
7551
|
+
tmpPanel.style.display = 'block';
|
|
7552
|
+
}
|
|
7553
|
+
}
|
|
7516
7554
|
startSync() {
|
|
7517
7555
|
let tmpSelectedTables = this.pict.views['DataCloner-Schema'].getSelectedTables();
|
|
7518
7556
|
let tmpPageSize = parseInt(document.getElementById('pageSize').value, 10) || 100;
|
|
@@ -7541,6 +7579,16 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7541
7579
|
if (tmpMaxRecords > 0) tmpPostBody.MaxRecordsPerEntity = tmpMaxRecords;
|
|
7542
7580
|
if (tmpLogToFile) tmpPostBody.LogToFile = true;
|
|
7543
7581
|
if (tmpAdvancedIDPagination) tmpPostBody.UseAdvancedIDPagination = true;
|
|
7582
|
+
|
|
7583
|
+
// Strategy-specific options
|
|
7584
|
+
if (tmpSyncMode === 'OngoingEventualConsistency') {
|
|
7585
|
+
let tmpBackSyncTimeLimit = parseInt(document.getElementById('backSyncTimeLimit').value, 10);
|
|
7586
|
+
if (tmpBackSyncTimeLimit > 0) tmpPostBody.BackSyncTimeLimit = tmpBackSyncTimeLimit;
|
|
7587
|
+
}
|
|
7588
|
+
if (tmpSyncMode === 'TrueUp') {
|
|
7589
|
+
let tmpTrueUpPageSize = parseInt(document.getElementById('trueUpPageSize').value, 10);
|
|
7590
|
+
if (tmpTrueUpPageSize > 0) tmpPostBody.TrueUpPageSize = tmpTrueUpPageSize;
|
|
7591
|
+
}
|
|
7544
7592
|
this.pict.providers.DataCloner.api('POST', '/clone/sync/start', tmpPostBody).then(function (pData) {
|
|
7545
7593
|
if (pData.Success) {
|
|
7546
7594
|
let tmpMsg = pData.SyncMode + ' sync started for ' + pData.Tables.length + ' tables.';
|
|
@@ -7914,16 +7962,48 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7914
7962
|
|
|
7915
7963
|
<div style="margin-bottom:10px">
|
|
7916
7964
|
<label style="margin-bottom:6px">Sync Mode</label>
|
|
7917
|
-
<div style="display:flex; gap:
|
|
7965
|
+
<div style="display:flex; gap:12px 20px; align-items:center; flex-wrap:wrap">
|
|
7918
7966
|
<label style="font-weight:normal; margin:0; cursor:pointer">
|
|
7919
|
-
<input type="radio" name="syncMode" id="syncModeInitial" value="Initial" checked> Initial
|
|
7920
|
-
<span style="color:#888; font-size:0.85em">(full clone
|
|
7967
|
+
<input type="radio" name="syncMode" id="syncModeInitial" value="Initial" checked onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Initial
|
|
7968
|
+
<span style="color:#888; font-size:0.85em">(full clone)</span>
|
|
7921
7969
|
</label>
|
|
7922
7970
|
<label style="font-weight:normal; margin:0; cursor:pointer">
|
|
7923
|
-
<input type="radio" name="syncMode" id="syncModeOngoing" value="Ongoing"> Ongoing
|
|
7924
|
-
<span style="color:#888; font-size:0.85em">(delta
|
|
7971
|
+
<input type="radio" name="syncMode" id="syncModeOngoing" value="Ongoing" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Ongoing
|
|
7972
|
+
<span style="color:#888; font-size:0.85em">(delta sync)</span>
|
|
7925
7973
|
</label>
|
|
7974
|
+
<label style="font-weight:normal; margin:0; cursor:pointer">
|
|
7975
|
+
<input type="radio" name="syncMode" id="syncModeOngoingEventualConsistency" value="OngoingEventualConsistency" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Eventual
|
|
7976
|
+
<span style="color:#888; font-size:0.85em">(time-budgeted back-sync)</span>
|
|
7977
|
+
</label>
|
|
7978
|
+
<label style="font-weight:normal; margin:0; cursor:pointer">
|
|
7979
|
+
<input type="radio" name="syncMode" id="syncModeTrueUp" value="TrueUp" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> True-Up
|
|
7980
|
+
<span style="color:#888; font-size:0.85em">(linear walk, one-time)</span>
|
|
7981
|
+
</label>
|
|
7982
|
+
<label style="font-weight:normal; margin:0; cursor:pointer">
|
|
7983
|
+
<input type="radio" name="syncMode" id="syncModeComparisonOnly" value="ComparisonOnly" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Compare
|
|
7984
|
+
<span style="color:#888; font-size:0.85em">(diff report, no sync)</span>
|
|
7985
|
+
</label>
|
|
7986
|
+
</div>
|
|
7987
|
+
</div>
|
|
7988
|
+
|
|
7989
|
+
<div id="syncModeOptions-OngoingEventualConsistency" style="display:none; margin-bottom:10px">
|
|
7990
|
+
<div style="display:flex; gap:8px; align-items:flex-end">
|
|
7991
|
+
<div style="flex:0 0 220px">
|
|
7992
|
+
<label for="backSyncTimeLimit">Back-Sync Time Budget (ms)</label>
|
|
7993
|
+
<input type="number" id="backSyncTimeLimit" value="30000" min="1000" max="600000" style="margin-bottom:0">
|
|
7994
|
+
</div>
|
|
7995
|
+
</div>
|
|
7996
|
+
<div style="font-size:0.8em; color:#888; padding-left:4px">Milliseconds devoted to backwards bisection per entity before pulling new records (default: 30000)</div>
|
|
7997
|
+
</div>
|
|
7998
|
+
|
|
7999
|
+
<div id="syncModeOptions-TrueUp" style="display:none; margin-bottom:10px">
|
|
8000
|
+
<div style="display:flex; gap:8px; align-items:flex-end">
|
|
8001
|
+
<div style="flex:0 0 220px">
|
|
8002
|
+
<label for="trueUpPageSize">True-Up Page Size</label>
|
|
8003
|
+
<input type="number" id="trueUpPageSize" value="500" min="10" max="10000" style="margin-bottom:0">
|
|
8004
|
+
</div>
|
|
7926
8005
|
</div>
|
|
8006
|
+
<div style="font-size:0.8em; color:#888; padding-left:4px">Records per page for the linear keyset walk (default: 500)</div>
|
|
7927
8007
|
</div>
|
|
7928
8008
|
|
|
7929
8009
|
<div class="checkbox-row">
|