dexbot 1.1.14 → 1.2.0
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/README.md +1 -0
- package/dist/market_adapter/market_adapter.js +1 -1
- package/dist/market_adapter/market_adapter.js.map +1 -1
- package/dist/modules/bitshares-native/lru_cache.d.ts +20 -0
- package/dist/modules/bitshares-native/lru_cache.d.ts.map +1 -0
- package/dist/modules/bitshares-native/lru_cache.js +45 -0
- package/dist/modules/bitshares-native/lru_cache.js.map +1 -0
- package/dist/modules/bitshares-native/resolvers.d.ts +2 -18
- package/dist/modules/bitshares-native/resolvers.d.ts.map +1 -1
- package/dist/modules/bitshares-native/resolvers.js +2 -41
- package/dist/modules/bitshares-native/resolvers.js.map +1 -1
- package/dist/modules/bitshares-native/serial/chain_constants.d.ts +1 -0
- package/dist/modules/bitshares-native/serial/chain_constants.d.ts.map +1 -1
- package/dist/modules/bitshares-native/serial/chain_constants.js +3 -0
- package/dist/modules/bitshares-native/serial/chain_constants.js.map +1 -1
- package/dist/modules/bitshares-native/signing_client.d.ts.map +1 -1
- package/dist/modules/bitshares-native/signing_client.js +12 -1
- package/dist/modules/bitshares-native/signing_client.js.map +1 -1
- package/dist/modules/bitshares-native/subscriptions.d.ts.map +1 -1
- package/dist/modules/bitshares-native/subscriptions.js +42 -3
- package/dist/modules/bitshares-native/subscriptions.js.map +1 -1
- package/dist/modules/bitshares-native/transport.d.ts.map +1 -1
- package/dist/modules/bitshares-native/transport.js +77 -27
- package/dist/modules/bitshares-native/transport.js.map +1 -1
- package/dist/modules/bitshares-native/tx/builder.d.ts.map +1 -1
- package/dist/modules/bitshares-native/tx/builder.js +26 -16
- package/dist/modules/bitshares-native/tx/builder.js.map +1 -1
- package/dist/modules/bitshares-native/tx/tx_cache.d.ts +17 -0
- package/dist/modules/bitshares-native/tx/tx_cache.d.ts.map +1 -0
- package/dist/modules/bitshares-native/tx/tx_cache.js +62 -0
- package/dist/modules/bitshares-native/tx/tx_cache.js.map +1 -0
- package/dist/modules/bot_settings.d.ts.map +1 -1
- package/dist/modules/bot_settings.js +2 -1
- package/dist/modules/bot_settings.js.map +1 -1
- package/dist/modules/chain_orders.d.ts +4 -1
- package/dist/modules/chain_orders.d.ts.map +1 -1
- package/dist/modules/chain_orders.js +30 -1
- package/dist/modules/chain_orders.js.map +1 -1
- package/dist/modules/config.d.ts +6 -0
- package/dist/modules/config.d.ts.map +1 -1
- package/dist/modules/config.js +11 -0
- package/dist/modules/config.js.map +1 -1
- package/dist/modules/constants.d.ts +14 -1
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +64 -6
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credit_runtime.d.ts.map +1 -1
- package/dist/modules/credit_runtime.js +40 -29
- package/dist/modules/credit_runtime.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +6 -12
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +117 -75
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts +1 -5
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +19 -48
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/launcher/child_env.d.ts.map +1 -1
- package/dist/modules/launcher/child_env.js +1 -0
- package/dist/modules/launcher/child_env.js.map +1 -1
- package/dist/modules/launcher/launch_modes.d.ts +2 -0
- package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
- package/dist/modules/launcher/launch_modes.js +7 -6
- package/dist/modules/launcher/launch_modes.js.map +1 -1
- package/dist/modules/order/accounting.d.ts.map +1 -1
- package/dist/modules/order/accounting.js +40 -12
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/async_lock.d.ts +12 -4
- package/dist/modules/order/async_lock.d.ts.map +1 -1
- package/dist/modules/order/async_lock.js +27 -5
- package/dist/modules/order/async_lock.js.map +1 -1
- package/dist/modules/order/grid.d.ts +434 -475
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +1612 -1592
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile.d.ts +3 -73
- package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile.js +11 -843
- package/dist/modules/order/grid_reconcile.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts +8 -0
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -0
- package/dist/modules/order/grid_reconcile_internal.js +771 -0
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -0
- package/dist/modules/order/logger.d.ts +1 -1
- package/dist/modules/order/logger.d.ts.map +1 -1
- package/dist/modules/order/logger.js +26 -2
- package/dist/modules/order/logger.js.map +1 -1
- package/dist/modules/order/manager.d.ts +40 -3
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +91 -12
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/runner.js +2 -2
- package/dist/modules/order/runner.js.map +1 -1
- package/dist/modules/order/strategy.js +3 -3
- package/dist/modules/order/strategy.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +72 -29
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts +17 -0
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +39 -18
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/system.js +4 -4
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/order/utils/validate.d.ts.map +1 -1
- package/dist/modules/order/utils/validate.js +6 -8
- package/dist/modules/order/utils/validate.js.map +1 -1
- package/dist/scripts/print_grid.js +3 -3
- package/dist/scripts/print_grid.js.map +1 -1
- package/dist/scripts/test-credit-renewal.js +1 -1
- package/dist/scripts/test-credit-renewal.js.map +1 -1
- package/dist/unlock.d.ts.map +1 -1
- package/dist/unlock.js +26 -12
- package/dist/unlock.js.map +1 -1
- package/package.json +1 -1
|
@@ -319,7 +319,7 @@ declare class DEXBot {
|
|
|
319
319
|
* @returns {string|null} Fallback key or null
|
|
320
320
|
*/
|
|
321
321
|
_buildOrphanFillFallbackKey(fill: any): any;
|
|
322
|
-
_isNewFillKey(fillKey: any, processedFillKeys: any, label?: string): boolean;
|
|
322
|
+
_isNewFillKey(fillKey: any, processedFillKeys: any, label?: string, orderId?: string): boolean;
|
|
323
323
|
/**
|
|
324
324
|
* Apply replay-safe fill accounting using a provided fill key.
|
|
325
325
|
* @param {Object} fill - Fill event object
|
|
@@ -648,10 +648,7 @@ declare class DEXBot {
|
|
|
648
648
|
* @param {Array<Object>} opContexts - Original opContexts from the failed batch
|
|
649
649
|
* @returns {Promise<Object>} Result object compatible with batch return shape
|
|
650
650
|
*/
|
|
651
|
-
_reconcileAfterUncertainBroadcast(err: any, opContexts: any, options?:
|
|
652
|
-
fillLockAlreadyHeld?: boolean;
|
|
653
|
-
[key: string]: any;
|
|
654
|
-
}): Promise<any>;
|
|
651
|
+
_reconcileAfterUncertainBroadcast(err: any, opContexts: any, options?: Record<string, any>): Promise<any>;
|
|
655
652
|
_reconcileAfterUncertainBroadcastImpl(err: any, opContexts: any, options: any): Promise<{
|
|
656
653
|
executed: boolean;
|
|
657
654
|
hadRotation: boolean;
|
|
@@ -939,13 +936,13 @@ declare class DEXBot {
|
|
|
939
936
|
* @private
|
|
940
937
|
*/
|
|
941
938
|
_runStartupSequence(): Promise<void>;
|
|
939
|
+
_runCreditOnlyStartup(): Promise<void>;
|
|
942
940
|
/**
|
|
943
941
|
* Perform periodic grid checks: fund thresholds, spread condition, grid health.
|
|
944
942
|
* Called by the periodic blockchain fetch interval to check if grid needs updates.
|
|
945
943
|
*
|
|
946
944
|
* IMPORTANT: This method MUST only be called from within _fillProcessingLock.acquire()
|
|
947
|
-
* (specifically from _setupBlockchainFetchInterval).
|
|
948
|
-
* to avoid deadlock with _consumeFillQueue which uses the same lock ordering.
|
|
945
|
+
* (specifically from _setupBlockchainFetchInterval).
|
|
949
946
|
*
|
|
950
947
|
* @private
|
|
951
948
|
*/
|
|
@@ -1008,7 +1005,6 @@ declare class DEXBot {
|
|
|
1008
1005
|
_stopCreditWatchdogInterval(): void;
|
|
1009
1006
|
requestGridReset(reason?: string, options?: {
|
|
1010
1007
|
refreshCenterPrice?: boolean;
|
|
1011
|
-
fillLockAlreadyHeld?: boolean;
|
|
1012
1008
|
[key: string]: any;
|
|
1013
1009
|
}): Promise<any>;
|
|
1014
1010
|
_wireStructuralGridResyncRequest(): void;
|
|
@@ -1053,14 +1049,13 @@ declare class DEXBot {
|
|
|
1053
1049
|
* Cancel dust partial orders immediately — no maps, no timers, no delay.
|
|
1054
1050
|
* Each dust order is cancelled on chain and its slot rotated through the
|
|
1055
1051
|
* synthetic-fill pipeline.
|
|
1056
|
-
* @param {{ buy: Array, sell: Array
|
|
1052
|
+
* @param {{ buy: Array, sell: Array }} options
|
|
1057
1053
|
* @returns {Promise<{cancelledCount: number, batchResult: {aborted: boolean}|null}>}
|
|
1058
1054
|
* @private
|
|
1059
1055
|
*/
|
|
1060
|
-
_cancelDustOrders({ buy: buyDust, sell: sellDust
|
|
1056
|
+
_cancelDustOrders({ buy: buyDust, sell: sellDust }?: {
|
|
1061
1057
|
buy?: any[];
|
|
1062
1058
|
sell?: any[];
|
|
1063
|
-
fillLockAlreadyHeld?: boolean;
|
|
1064
1059
|
}): Promise<any>;
|
|
1065
1060
|
/**
|
|
1066
1061
|
* Set up the periodic dust health check interval.
|
|
@@ -1086,7 +1081,6 @@ declare class DEXBot {
|
|
|
1086
1081
|
*
|
|
1087
1082
|
* LOCK ORDERING:
|
|
1088
1083
|
* - Canonical order: _fillProcessingLock → _divergenceLock
|
|
1089
|
-
* - This function handles lock acquisition based on fillLockAlreadyHeld parameter
|
|
1090
1084
|
* - When called from post-fill context, fill lock is already held
|
|
1091
1085
|
* - When called from periodic context, both locks must be acquired
|
|
1092
1086
|
* - Matches the order used in _consumeFillQueue to prevent deadlocks
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dexbot_class.d.ts","sourceRoot":"","sources":["../../modules/dexbot_class.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dexbot_class.d.ts","sourceRoot":"","sources":["../../modules/dexbot_class.ts"],"names":[],"mappings":"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"}
|
|
@@ -248,25 +248,28 @@ class DEXBot {
|
|
|
248
248
|
*/
|
|
249
249
|
_validateStartupConfig(config) {
|
|
250
250
|
const errors = [];
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
251
|
+
// Skip trading field validation in credit-only mode
|
|
252
|
+
if (!config.creditOnly) {
|
|
253
|
+
// Validate startPrice is numeric or valid string mode
|
|
254
|
+
const startPrice = config.startPrice;
|
|
255
|
+
const validPriceModes = ['pool', 'book'];
|
|
256
|
+
const isPriceNumeric = typeof startPrice === 'number' && Number.isFinite(startPrice) && startPrice > 0;
|
|
257
|
+
const isPriceMode = typeof startPrice === 'string' && validPriceModes.includes(startPrice.toLowerCase());
|
|
258
|
+
if (!isPriceNumeric && !isPriceMode) {
|
|
259
|
+
errors.push(`startPrice must be a positive number or valid mode (${validPriceModes.join('/')}), got: ${startPrice}`);
|
|
260
|
+
}
|
|
261
|
+
// Validate assetA and assetB are present
|
|
262
|
+
if (!config.assetA || typeof config.assetA !== 'string') {
|
|
263
|
+
errors.push(`assetA must be a non-empty string, got: ${config.assetA}`);
|
|
264
|
+
}
|
|
265
|
+
if (!config.assetB || typeof config.assetB !== 'string') {
|
|
266
|
+
errors.push(`assetB must be a non-empty string, got: ${config.assetB}`);
|
|
267
|
+
}
|
|
268
|
+
// Validate incrementPercent
|
|
269
|
+
const increment = config.incrementPercent;
|
|
270
|
+
if (!Number.isFinite(increment) || increment <= 0 || increment > 100) {
|
|
271
|
+
errors.push(`incrementPercent must be between 0 and 100, got: ${increment}`);
|
|
272
|
+
}
|
|
270
273
|
}
|
|
271
274
|
// Throw all validation errors at once
|
|
272
275
|
if (errors.length > 0) {
|
|
@@ -375,7 +378,7 @@ class DEXBot {
|
|
|
375
378
|
this.manager.logger.log(`Triggering state recovery sync (${reason})...`, 'info');
|
|
376
379
|
await this.manager.fetchAccountTotals(this.accountId);
|
|
377
380
|
const openOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
378
|
-
await this.manager.syncFromOpenOrders(openOrders, { skipAccounting: true
|
|
381
|
+
await this.manager.syncFromOpenOrders(openOrders, { skipAccounting: true });
|
|
379
382
|
if (typeof this.manager.persistGrid === 'function') {
|
|
380
383
|
await this.manager.persistGrid();
|
|
381
384
|
}
|
|
@@ -587,8 +590,6 @@ class DEXBot {
|
|
|
587
590
|
if (chainOpenOrders.length > 0 && this.manager?.syncFromOpenOrders) {
|
|
588
591
|
await this.manager.syncFromOpenOrders(chainOpenOrders, {
|
|
589
592
|
skipAccounting: true,
|
|
590
|
-
fillLockAlreadyHeld: true,
|
|
591
|
-
protectCommittedOrders: true
|
|
592
593
|
});
|
|
593
594
|
}
|
|
594
595
|
// 5. Persist the reconciled state
|
|
@@ -819,13 +820,14 @@ class DEXBot {
|
|
|
819
820
|
_buildOrphanFillFallbackKey(fill) {
|
|
820
821
|
return DexbotFillRuntime.buildOrphanFillFallbackKey(this, fill);
|
|
821
822
|
}
|
|
822
|
-
_isNewFillKey(fillKey, processedFillKeys, label = '') {
|
|
823
|
+
_isNewFillKey(fillKey, processedFillKeys, label = '', orderId = '') {
|
|
823
824
|
const now = Date.now();
|
|
824
825
|
if (this._recentlyQueuedFills.has(fillKey)) {
|
|
825
826
|
const lastProcessed = this._recentlyQueuedFills.get(fillKey);
|
|
826
827
|
if (now - lastProcessed < this._fillDedupeWindowMs) {
|
|
827
828
|
if (label) {
|
|
828
|
-
|
|
829
|
+
const idSuffix = orderId ? ` for ${orderId}` : '';
|
|
830
|
+
this.manager?.logger?.log?.(`${label} Skipping duplicate fill${idSuffix} (processed ${now - lastProcessed}ms ago)`, 'debug');
|
|
829
831
|
}
|
|
830
832
|
return false;
|
|
831
833
|
}
|
|
@@ -953,7 +955,7 @@ class DEXBot {
|
|
|
953
955
|
const chainOpenOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
954
956
|
if (this._shuttingDown)
|
|
955
957
|
return;
|
|
956
|
-
const syncResult = await this.manager.synchronizeWithChain(chainOpenOrders, 'readOpenOrders'
|
|
958
|
+
const syncResult = await this.manager.synchronizeWithChain(chainOpenOrders, 'readOpenOrders');
|
|
957
959
|
if (this._shuttingDown)
|
|
958
960
|
return;
|
|
959
961
|
if (syncResult?.filledOrders?.length > 0) {
|
|
@@ -970,7 +972,6 @@ class DEXBot {
|
|
|
970
972
|
await this._cancelDustOrders({
|
|
971
973
|
buy: reconnectHealth.buyDustOrders,
|
|
972
974
|
sell: reconnectHealth.sellDustOrders,
|
|
973
|
-
fillLockAlreadyHeld: true,
|
|
974
975
|
});
|
|
975
976
|
}
|
|
976
977
|
catch (_dustErr) {
|
|
@@ -1050,7 +1051,7 @@ class DEXBot {
|
|
|
1050
1051
|
if (!orphanFillKey) {
|
|
1051
1052
|
orphanFillKey = this._buildOrphanFillFallbackKey(fill);
|
|
1052
1053
|
}
|
|
1053
|
-
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[POST-RESET]')) {
|
|
1054
|
+
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[POST-RESET]', fillOp.order_id)) {
|
|
1054
1055
|
continue;
|
|
1055
1056
|
}
|
|
1056
1057
|
this._log(`[POST-RESET] Processing funds for unknown order ${fillOp.order_id} (not in grid but crediting proceeds)`, 'warn');
|
|
@@ -1066,7 +1067,7 @@ class DEXBot {
|
|
|
1066
1067
|
}
|
|
1067
1068
|
this._log(`[POST-RESET] Processing fill for ${gridOrder.type} order ${gridOrder.id} at price ${gridOrder.price}`);
|
|
1068
1069
|
const trackedFillKey = buildFillKey(fill);
|
|
1069
|
-
if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[POST-RESET]')) {
|
|
1070
|
+
if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[POST-RESET]', fillOp.order_id)) {
|
|
1070
1071
|
continue;
|
|
1071
1072
|
}
|
|
1072
1073
|
const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
|
|
@@ -1092,7 +1093,7 @@ class DEXBot {
|
|
|
1092
1093
|
if (requiresOpenOrdersSync) {
|
|
1093
1094
|
this._log('[POST-RESET] Falling back to open-orders sync for fill(s) missing replay-safe history identifiers', 'warn');
|
|
1094
1095
|
const postResetChainOpenOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
1095
|
-
const syncResult = await this.manager.syncFromOpenOrders(postResetChainOpenOrders
|
|
1096
|
+
const syncResult = await this.manager.syncFromOpenOrders(postResetChainOpenOrders);
|
|
1096
1097
|
if (syncResult.filledOrders?.length > 0) {
|
|
1097
1098
|
await this._processFillsWithBatching(syncResult.filledOrders, new Set(), '[POST-RESET] open-orders fallback');
|
|
1098
1099
|
}
|
|
@@ -1123,7 +1124,6 @@ class DEXBot {
|
|
|
1123
1124
|
await this._cancelDustOrders({
|
|
1124
1125
|
buy: postResetHealth.buyDustOrders,
|
|
1125
1126
|
sell: postResetHealth.sellDustOrders,
|
|
1126
|
-
fillLockAlreadyHeld: true,
|
|
1127
1127
|
});
|
|
1128
1128
|
}
|
|
1129
1129
|
catch (_dustErr) {
|
|
@@ -1219,7 +1219,7 @@ class DEXBot {
|
|
|
1219
1219
|
if (Array.isArray(chainOpenOrders) && chainOpenOrders.length > 0) {
|
|
1220
1220
|
this._log('Generating new grid and syncing with existing on-chain orders...');
|
|
1221
1221
|
await Grid.initializeGrid(this.manager);
|
|
1222
|
-
await this.manager.syncFromOpenOrders(chainOpenOrders, { skipAccounting: true
|
|
1222
|
+
await this.manager.syncFromOpenOrders(chainOpenOrders, { skipAccounting: true });
|
|
1223
1223
|
const rebalanceResult = await reconcileGridOrders({
|
|
1224
1224
|
manager: this.manager,
|
|
1225
1225
|
config: this.config,
|
|
@@ -1227,7 +1227,6 @@ class DEXBot {
|
|
|
1227
1227
|
privateKey: this.privateKey,
|
|
1228
1228
|
chainOrders,
|
|
1229
1229
|
chainOpenOrders,
|
|
1230
|
-
fillLockAlreadyHeld: true,
|
|
1231
1230
|
});
|
|
1232
1231
|
await this._executeBatchIfNeeded(rebalanceResult, 'startup reconcile (regenerated grid)');
|
|
1233
1232
|
}
|
|
@@ -1241,7 +1240,7 @@ class DEXBot {
|
|
|
1241
1240
|
this._log('Found active session. Loading and syncing existing grid.');
|
|
1242
1241
|
await Grid.loadGrid(this.manager, persistedGrid, persistedBoundaryIdx);
|
|
1243
1242
|
let startupChainOpenOrders = chainOpenOrders;
|
|
1244
|
-
const syncResult = await this.manager.syncFromOpenOrders(startupChainOpenOrders, { skipAccounting: true
|
|
1243
|
+
const syncResult = await this.manager.syncFromOpenOrders(startupChainOpenOrders, { skipAccounting: true });
|
|
1245
1244
|
// Process price corrections queued during startup sync.
|
|
1246
1245
|
// These are not picked up by _consumeFillQueue until a fill
|
|
1247
1246
|
// arrives, which may never come for an idle market.
|
|
@@ -1255,7 +1254,7 @@ class DEXBot {
|
|
|
1255
1254
|
// Refresh open orders so startup reconcile works with post-batch chain reality
|
|
1256
1255
|
// and avoids reconciling against a stale pre-batch snapshot.
|
|
1257
1256
|
startupChainOpenOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
1258
|
-
await this.manager.synchronizeWithChain(startupChainOpenOrders, 'readOpenOrders'
|
|
1257
|
+
await this.manager.synchronizeWithChain(startupChainOpenOrders, 'readOpenOrders');
|
|
1259
1258
|
}
|
|
1260
1259
|
}
|
|
1261
1260
|
const rebalanceResult = await reconcileGridOrders({
|
|
@@ -1265,7 +1264,6 @@ class DEXBot {
|
|
|
1265
1264
|
privateKey: this.privateKey,
|
|
1266
1265
|
chainOrders,
|
|
1267
1266
|
chainOpenOrders: startupChainOpenOrders,
|
|
1268
|
-
fillLockAlreadyHeld: true,
|
|
1269
1267
|
});
|
|
1270
1268
|
await this._executeBatchIfNeeded(rebalanceResult, 'startup reconcile (loaded grid)');
|
|
1271
1269
|
// Dust state is no longer persisted — cancelled immediately on detection.
|
|
@@ -1284,13 +1282,12 @@ class DEXBot {
|
|
|
1284
1282
|
// Perform initial grid maintenance (thresholds, divergence, spread, health)
|
|
1285
1283
|
// Consolidated into shared logic to ensure consistent behavior at boot and runtime.
|
|
1286
1284
|
// CRITICAL: Pass lockAlreadyHeld since we're inside _fillProcessingLock.acquire()
|
|
1287
|
-
await this._runGridMaintenance('startup'
|
|
1285
|
+
await this._runGridMaintenance('startup');
|
|
1288
1286
|
// Cancel any dust from a previous bot lifetime immediately.
|
|
1289
1287
|
const startupHealth = await this.manager.checkGridHealth(this.updateOrdersOnChainPlan.bind(this));
|
|
1290
1288
|
await this._cancelDustOrders({
|
|
1291
1289
|
buy: startupHealth.buyDustOrders,
|
|
1292
1290
|
sell: startupHealth.sellDustOrders,
|
|
1293
|
-
fillLockAlreadyHeld: true,
|
|
1294
1291
|
});
|
|
1295
1292
|
this._log('Bootstrap phase complete - fill processing resumed', 'info');
|
|
1296
1293
|
}
|
|
@@ -1302,7 +1299,7 @@ class DEXBot {
|
|
|
1302
1299
|
await this._setupTriggerFileDetection();
|
|
1303
1300
|
await this._setupCreditRuntime();
|
|
1304
1301
|
await this._refreshAndSyncCreditRuntime();
|
|
1305
|
-
await this._runCreditRuntimeMaintenance('startup'
|
|
1302
|
+
await this._runCreditRuntimeMaintenance('startup');
|
|
1306
1303
|
this._setupBlockchainFetchInterval();
|
|
1307
1304
|
this._setupCreditWatchdogInterval();
|
|
1308
1305
|
this._setupCredentialDaemonWatchdogInterval();
|
|
@@ -1346,14 +1343,14 @@ class DEXBot {
|
|
|
1346
1343
|
}
|
|
1347
1344
|
try {
|
|
1348
1345
|
let openOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
1349
|
-
const syncResult = await this.manager.synchronizeWithChain(openOrders, 'readOpenOrders'
|
|
1346
|
+
const syncResult = await this.manager.synchronizeWithChain(openOrders, 'readOpenOrders');
|
|
1350
1347
|
let aborted = false;
|
|
1351
1348
|
if (syncResult?.filledOrders?.length > 0) {
|
|
1352
1349
|
this._log(`[SYNC-CHAIN] ${syncResult.filledOrders.length} filled order(s) found during ${tag}`, 'info');
|
|
1353
1350
|
const batchResult = await this._processFillsWithBatching(syncResult.filledOrders, new Set(), `${tag} sync-fill`);
|
|
1354
1351
|
if (!batchResult?.aborted) {
|
|
1355
1352
|
openOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
1356
|
-
await this.manager.synchronizeWithChain(openOrders, 'readOpenOrders'
|
|
1353
|
+
await this.manager.synchronizeWithChain(openOrders, 'readOpenOrders');
|
|
1357
1354
|
}
|
|
1358
1355
|
else {
|
|
1359
1356
|
aborted = true;
|
|
@@ -1601,7 +1598,7 @@ class DEXBot {
|
|
|
1601
1598
|
if (!orphanFillKey) {
|
|
1602
1599
|
orphanFillKey = this._buildOrphanFillFallbackKey(fill);
|
|
1603
1600
|
}
|
|
1604
|
-
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[ORPHAN-FILL]')) {
|
|
1601
|
+
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[ORPHAN-FILL]', fillOp.order_id)) {
|
|
1605
1602
|
continue;
|
|
1606
1603
|
}
|
|
1607
1604
|
this.manager.logger.log(`[ORPHAN-FILL] Processing funds for unknown order ${fillOp.order_id} (not in grid but crediting proceeds)`, 'warn');
|
|
@@ -1631,7 +1628,7 @@ class DEXBot {
|
|
|
1631
1628
|
requiresOpenOrdersSync = true;
|
|
1632
1629
|
continue;
|
|
1633
1630
|
}
|
|
1634
|
-
if (!this._isNewFillKey(fillKey, processedFillKeys, '[FILL]')) {
|
|
1631
|
+
if (!this._isNewFillKey(fillKey, processedFillKeys, '[FILL]', fillOp.order_id)) {
|
|
1635
1632
|
continue;
|
|
1636
1633
|
}
|
|
1637
1634
|
validFills.push(fill);
|
|
@@ -1694,7 +1691,7 @@ class DEXBot {
|
|
|
1694
1691
|
}
|
|
1695
1692
|
this.manager.logger.log(`Syncing ${fillsToSync.length} fill(s) (open orders mode)`, 'info');
|
|
1696
1693
|
const chainOpenOrders = await chainOrders.readOpenOrders(this.account);
|
|
1697
|
-
const resultOpenOrders = await this.manager.syncFromOpenOrders(chainOpenOrders
|
|
1694
|
+
const resultOpenOrders = await this.manager.syncFromOpenOrders(chainOpenOrders);
|
|
1698
1695
|
// Dust is handled by post-fill detection below.
|
|
1699
1696
|
if (resultOpenOrders.filledOrders)
|
|
1700
1697
|
resolvedOrders.push(...resultOpenOrders.filledOrders);
|
|
@@ -1827,7 +1824,6 @@ class DEXBot {
|
|
|
1827
1824
|
const dustCancelResult = await this._cancelDustOrders({
|
|
1828
1825
|
buy: healthResult.buyDustOrders,
|
|
1829
1826
|
sell: healthResult.sellDustOrders,
|
|
1830
|
-
fillLockAlreadyHeld: true,
|
|
1831
1827
|
});
|
|
1832
1828
|
if (dustCancelResult?.batchResult?.aborted) {
|
|
1833
1829
|
abortedFillCycle = true;
|
|
@@ -1841,7 +1837,7 @@ class DEXBot {
|
|
|
1841
1837
|
// After: Grid maintenance waits for isPipelineEmpty() before structural changes
|
|
1842
1838
|
// Run only when the cycle contains at least one full fill.
|
|
1843
1839
|
if (shouldRunPostFillChecks && !abortedFillCycle) {
|
|
1844
|
-
await this._runGridMaintenance('post-fill'
|
|
1840
|
+
await this._runGridMaintenance('post-fill');
|
|
1845
1841
|
}
|
|
1846
1842
|
}
|
|
1847
1843
|
else if (pendingFillKeysForCurrentCycle.size > 0) {
|
|
@@ -1966,7 +1962,7 @@ class DEXBot {
|
|
|
1966
1962
|
if (!orphanFillKey) {
|
|
1967
1963
|
orphanFillKey = this._buildOrphanFillFallbackKey(fill);
|
|
1968
1964
|
}
|
|
1969
|
-
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[BOOTSTRAP]')) {
|
|
1965
|
+
if (orphanFillKey && !this._isNewFillKey(orphanFillKey, processedFillKeys, '[BOOTSTRAP]', fillOp.order_id)) {
|
|
1970
1966
|
continue;
|
|
1971
1967
|
}
|
|
1972
1968
|
this.manager.logger.log(`[BOOTSTRAP] Processing funds for unknown order ${fillOp.order_id} (not in grid but crediting proceeds)`, 'warn');
|
|
@@ -1979,7 +1975,7 @@ class DEXBot {
|
|
|
1979
1975
|
continue;
|
|
1980
1976
|
}
|
|
1981
1977
|
const trackedFillKey = buildFillKey(fill);
|
|
1982
|
-
if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[BOOTSTRAP]')) {
|
|
1978
|
+
if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[BOOTSTRAP]', fillOp.order_id)) {
|
|
1983
1979
|
continue;
|
|
1984
1980
|
}
|
|
1985
1981
|
const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
|
|
@@ -2000,7 +1996,7 @@ class DEXBot {
|
|
|
2000
1996
|
if (requiresOpenOrdersSync) {
|
|
2001
1997
|
this._log('[BOOTSTRAP] Falling back to open-orders sync for fill(s) missing replay-safe history identifiers', 'warn');
|
|
2002
1998
|
const bootstrapChainOpenOrders = await chainOrders.readOpenOrders(this.accountId);
|
|
2003
|
-
const syncResult = await this.manager.syncFromOpenOrders(bootstrapChainOpenOrders
|
|
1999
|
+
const syncResult = await this.manager.syncFromOpenOrders(bootstrapChainOpenOrders);
|
|
2004
2000
|
if (syncResult.filledOrders?.length > 0) {
|
|
2005
2001
|
const queuedOrderIds = new Set(validFills.map(fill => fill?.gridOrder?.orderId).filter(Boolean));
|
|
2006
2002
|
for (const filledOrder of syncResult.filledOrders) {
|
|
@@ -2238,8 +2234,6 @@ class DEXBot {
|
|
|
2238
2234
|
const openOrders = await chainOrders.readOpenOrders(accountRef);
|
|
2239
2235
|
const recoveryResult = await this.manager.syncFromOpenOrders(openOrders, {
|
|
2240
2236
|
skipAccounting: false,
|
|
2241
|
-
fillLockAlreadyHeld: true,
|
|
2242
|
-
protectCommittedOrders: true
|
|
2243
2237
|
});
|
|
2244
2238
|
this._preserveMissingCreateBlockersAfterRecovery(preRecoveryMissingCreateBlockers, recoveryResult);
|
|
2245
2239
|
// Persist any master grid mutations from the recovery sync. The
|
|
@@ -2583,13 +2577,10 @@ class DEXBot {
|
|
|
2583
2577
|
* @returns {Promise<Object>} Result object compatible with batch return shape
|
|
2584
2578
|
*/
|
|
2585
2579
|
async _reconcileAfterUncertainBroadcast(err, opContexts, options = {}) {
|
|
2586
|
-
if (
|
|
2587
|
-
this.manager
|
|
2588
|
-
|
|
2589
|
-
return this.manager._fillProcessingLock.acquire(
|
|
2590
|
-
...options,
|
|
2591
|
-
fillLockAlreadyHeld: true
|
|
2592
|
-
})));
|
|
2580
|
+
if (this.manager?._fillProcessingLock &&
|
|
2581
|
+
typeof this.manager._fillProcessingLock.acquire === 'function' &&
|
|
2582
|
+
!this.manager._fillProcessingLock.isReentrant()) {
|
|
2583
|
+
return this.manager._fillProcessingLock.acquire(() => this._reconcileAfterUncertainBroadcast(err, opContexts, options));
|
|
2593
2584
|
}
|
|
2594
2585
|
return this._reconcileAfterUncertainBroadcastImpl(err, opContexts, options);
|
|
2595
2586
|
}
|
|
@@ -2702,8 +2693,6 @@ class DEXBot {
|
|
|
2702
2693
|
try {
|
|
2703
2694
|
await this.manager.syncFromOpenOrders(latestSnapshot, {
|
|
2704
2695
|
skipAccounting: true,
|
|
2705
|
-
fillLockAlreadyHeld: true,
|
|
2706
|
-
protectCommittedOrders: true
|
|
2707
2696
|
});
|
|
2708
2697
|
hadRotation = true;
|
|
2709
2698
|
}
|
|
@@ -2758,9 +2747,52 @@ class DEXBot {
|
|
|
2758
2747
|
catch (orphanErr) {
|
|
2759
2748
|
this.manager.logger.log(`[COW][UNCERTAIN] Auto-cancel pass failed: ${orphanErr?.message || orphanErr}`, 'warn');
|
|
2760
2749
|
}
|
|
2750
|
+
// Boundary shift recovery: the COW batch that should have committed the
|
|
2751
|
+
// boundary shift from this fill cycle failed before commit. Every planned
|
|
2752
|
+
// CREATE in the batch represents a fill whose opposite-side boundary step
|
|
2753
|
+
// was lost — regardless of whether the individual CREATE was later adopted
|
|
2754
|
+
// on chain (adopted) or not (discarded). Manually adjust manager.boundaryIdx
|
|
2755
|
+
// so the next COW cycle (triggered by the next fill or periodic maintenance)
|
|
2756
|
+
// generates replacement opposite-side orders using the correct boundary.
|
|
2757
|
+
//
|
|
2758
|
+
// NOTE: Direct mutation of manager.boundaryIdx outside a COW commit
|
|
2759
|
+
// violates the invariant stated in grid.ts:1217-1220 (boundary must only
|
|
2760
|
+
// be updated atomically inside _commitWorkingGrid). This is intentional
|
|
2761
|
+
// here because the COW commit already failed — the invariant was already
|
|
2762
|
+
// broken by the broadcast uncertainty, and the adjustment only restores
|
|
2763
|
+
// the state to what the successful commit would have produced.
|
|
2764
|
+
if (hadRotation && this.manager && pending.length > 0) {
|
|
2765
|
+
let boundaryShift = 0;
|
|
2766
|
+
for (const entry of pending) {
|
|
2767
|
+
const orderType = entry.orderType || entry.order?.type;
|
|
2768
|
+
if (orderType === ORDER_TYPES.SELL) {
|
|
2769
|
+
boundaryShift--; // SELL CREATE → fill was BUY → boundary LEFT
|
|
2770
|
+
}
|
|
2771
|
+
else if (orderType === ORDER_TYPES.BUY) {
|
|
2772
|
+
boundaryShift++; // BUY CREATE → fill was SELL → boundary RIGHT
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
if (boundaryShift !== 0) {
|
|
2776
|
+
const oldIdx = this.manager.boundaryIdx;
|
|
2777
|
+
if (typeof oldIdx === 'number') {
|
|
2778
|
+
const maxIdx = Math.max(0, (this.manager.orders?.size || 1) - 1);
|
|
2779
|
+
const newIdx = Math.max(0, Math.min(maxIdx, oldIdx + boundaryShift));
|
|
2780
|
+
if (newIdx !== oldIdx) {
|
|
2781
|
+
this.manager.boundaryIdx = newIdx;
|
|
2782
|
+
this.manager.logger.log(`[COW][UNCERTAIN] Boundary adjusted by ${boundaryShift} ` +
|
|
2783
|
+
`(${adopted.length} adopted / ${discarded.length} discarded CREATE(s)): ` +
|
|
2784
|
+
`${oldIdx} → ${newIdx}. Next COW cycle will generate replacement opposite-side orders.`, 'warn');
|
|
2785
|
+
if (typeof this.manager._markGridDirty === 'function') {
|
|
2786
|
+
this.manager._markGridDirty(`boundary adjustment after ${pending.length} planned CREATE(s)`);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2761
2792
|
// Persist master grid mutations from the reconciliation sync and any
|
|
2762
2793
|
// orphan auto-cancellation that ran above. These apply outside the COW
|
|
2763
|
-
// broadcast path and would otherwise be in-memory only.
|
|
2794
|
+
// broadcast path and would otherwise be in-memory only. The boundary
|
|
2795
|
+
// adjustment above is also persisted here.
|
|
2764
2796
|
if (typeof this.manager?.persistGrid === 'function') {
|
|
2765
2797
|
await this.manager.persistGrid();
|
|
2766
2798
|
}
|
|
@@ -2898,8 +2930,6 @@ class DEXBot {
|
|
|
2898
2930
|
if (freshChain.length > 0 && this.manager?.syncFromOpenOrders) {
|
|
2899
2931
|
await this.manager.syncFromOpenOrders(freshChain, {
|
|
2900
2932
|
skipAccounting: true,
|
|
2901
|
-
fillLockAlreadyHeld: true,
|
|
2902
|
-
protectCommittedOrders: true
|
|
2903
2933
|
});
|
|
2904
2934
|
}
|
|
2905
2935
|
}
|
|
@@ -3316,7 +3346,7 @@ class DEXBot {
|
|
|
3316
3346
|
this._resumeGridPersistenceAfterCredentialRecovery('credential recovery started');
|
|
3317
3347
|
const runRecovery = async () => {
|
|
3318
3348
|
await this._triggerStateRecoverySync('credential daemon restored');
|
|
3319
|
-
await this._runGridMaintenance('credential-recovery'
|
|
3349
|
+
await this._runGridMaintenance('credential-recovery');
|
|
3320
3350
|
};
|
|
3321
3351
|
if (this.manager?._fillProcessingLock) {
|
|
3322
3352
|
await this.manager._fillProcessingLock.acquire(runRecovery);
|
|
@@ -3773,7 +3803,7 @@ class DEXBot {
|
|
|
3773
3803
|
batchId: this._currentBatchId || null,
|
|
3774
3804
|
payload: null,
|
|
3775
3805
|
timeoutMs: null
|
|
3776
|
-
}), []
|
|
3806
|
+
}), []);
|
|
3777
3807
|
}
|
|
3778
3808
|
catch (recoverErr) {
|
|
3779
3809
|
this.manager.logger.log(`[COW] Recovery from pending broadcasts failed: ${recoverErr?.message || recoverErr}`, 'error');
|
|
@@ -4133,7 +4163,7 @@ class DEXBot {
|
|
|
4133
4163
|
// throwing would re-enter the catch loop on the next attempt and
|
|
4134
4164
|
// potentially double-publish.
|
|
4135
4165
|
if (err instanceof BroadcastUncertainError) {
|
|
4136
|
-
return await this._reconcileAfterUncertainBroadcast(err, opContexts
|
|
4166
|
+
return await this._reconcileAfterUncertainBroadcast(err, opContexts);
|
|
4137
4167
|
}
|
|
4138
4168
|
// Handle hard abort
|
|
4139
4169
|
const hardAbortResult = await this._handleBatchHardAbort(err, 'COW batch processing', operations.length);
|
|
@@ -4439,6 +4469,10 @@ class DEXBot {
|
|
|
4439
4469
|
*/
|
|
4440
4470
|
async _runStartupSequence() {
|
|
4441
4471
|
try {
|
|
4472
|
+
if (this.config.creditOnly) {
|
|
4473
|
+
await this._runCreditOnlyStartup();
|
|
4474
|
+
return;
|
|
4475
|
+
}
|
|
4442
4476
|
const startupState = await this._initializeStartupState();
|
|
4443
4477
|
await this._finishStartupSequence(startupState);
|
|
4444
4478
|
}
|
|
@@ -4448,13 +4482,20 @@ class DEXBot {
|
|
|
4448
4482
|
throw err;
|
|
4449
4483
|
}
|
|
4450
4484
|
}
|
|
4485
|
+
async _runCreditOnlyStartup() {
|
|
4486
|
+
await this._setupCreditRuntime();
|
|
4487
|
+
await this._refreshAndSyncCreditRuntime();
|
|
4488
|
+
await this._runCreditRuntimeMaintenance('startup');
|
|
4489
|
+
this._setupCreditWatchdogInterval();
|
|
4490
|
+
this._setupCredentialDaemonWatchdogInterval();
|
|
4491
|
+
this._log('DEXBot started (credit-only mode)');
|
|
4492
|
+
}
|
|
4451
4493
|
/**
|
|
4452
4494
|
* Perform periodic grid checks: fund thresholds, spread condition, grid health.
|
|
4453
4495
|
* Called by the periodic blockchain fetch interval to check if grid needs updates.
|
|
4454
4496
|
*
|
|
4455
4497
|
* IMPORTANT: This method MUST only be called from within _fillProcessingLock.acquire()
|
|
4456
|
-
* (specifically from _setupBlockchainFetchInterval).
|
|
4457
|
-
* to avoid deadlock with _consumeFillQueue which uses the same lock ordering.
|
|
4498
|
+
* (specifically from _setupBlockchainFetchInterval).
|
|
4458
4499
|
*
|
|
4459
4500
|
* @private
|
|
4460
4501
|
*/
|
|
@@ -4601,14 +4642,17 @@ class DEXBot {
|
|
|
4601
4642
|
return { skipped: true, reason: 'grid resync unavailable' };
|
|
4602
4643
|
}
|
|
4603
4644
|
const message = reason ? `[CR-RESET] ${reason}` : '[CR-RESET] grid reset requested';
|
|
4604
|
-
// Manual/programmatic resets should advance the persisted center baseline
|
|
4605
|
-
// before rebuilding the grid, unless a caller explicitly disables it.
|
|
4606
4645
|
this._log(`${message}; rebuilding grid from fresh on-chain state`, 'info');
|
|
4607
4646
|
const resetOptions = {
|
|
4608
4647
|
...options,
|
|
4609
4648
|
refreshCenterPrice: options.refreshCenterPrice !== false,
|
|
4610
4649
|
};
|
|
4611
|
-
if (
|
|
4650
|
+
// Skip acquire if no lock exists (no fill processing to serialize against)
|
|
4651
|
+
// or if the caller already holds the lock (re-entrant). In the latter case
|
|
4652
|
+
// the lock's isReentrant() check prevents queueing and runs inline.
|
|
4653
|
+
// Otherwise, wait on the queue — this is the intended path for callers
|
|
4654
|
+
// outside the fill-processing context that need exclusive access.
|
|
4655
|
+
if (!this.manager._fillProcessingLock || this.manager._fillProcessingLock.isReentrant()) {
|
|
4612
4656
|
return this._performGridResync(resetOptions);
|
|
4613
4657
|
}
|
|
4614
4658
|
return this.manager._fillProcessingLock.acquire(async () => this._performGridResync(resetOptions));
|
|
@@ -4720,12 +4764,12 @@ class DEXBot {
|
|
|
4720
4764
|
* Cancel dust partial orders immediately — no maps, no timers, no delay.
|
|
4721
4765
|
* Each dust order is cancelled on chain and its slot rotated through the
|
|
4722
4766
|
* synthetic-fill pipeline.
|
|
4723
|
-
* @param {{ buy: Array, sell: Array
|
|
4767
|
+
* @param {{ buy: Array, sell: Array }} options
|
|
4724
4768
|
* @returns {Promise<{cancelledCount: number, batchResult: {aborted: boolean}|null}>}
|
|
4725
4769
|
* @private
|
|
4726
4770
|
*/
|
|
4727
|
-
async _cancelDustOrders({ buy: buyDust = [], sell: sellDust = []
|
|
4728
|
-
return DexbotMaintenanceRuntime.cancelDustOrders(this, { buy: buyDust, sell: sellDust
|
|
4771
|
+
async _cancelDustOrders({ buy: buyDust = [], sell: sellDust = [] } = {}) {
|
|
4772
|
+
return DexbotMaintenanceRuntime.cancelDustOrders(this, { buy: buyDust, sell: sellDust });
|
|
4729
4773
|
}
|
|
4730
4774
|
/**
|
|
4731
4775
|
* Set up the periodic dust health check interval.
|
|
@@ -4750,7 +4794,6 @@ class DEXBot {
|
|
|
4750
4794
|
await this._cancelDustOrders({
|
|
4751
4795
|
buy: health.buyDustOrders,
|
|
4752
4796
|
sell: health.sellDustOrders,
|
|
4753
|
-
fillLockAlreadyHeld: true,
|
|
4754
4797
|
});
|
|
4755
4798
|
});
|
|
4756
4799
|
}
|
|
@@ -4776,7 +4819,6 @@ class DEXBot {
|
|
|
4776
4819
|
*
|
|
4777
4820
|
* LOCK ORDERING:
|
|
4778
4821
|
* - Canonical order: _fillProcessingLock → _divergenceLock
|
|
4779
|
-
* - This function handles lock acquisition based on fillLockAlreadyHeld parameter
|
|
4780
4822
|
* - When called from post-fill context, fill lock is already held
|
|
4781
4823
|
* - When called from periodic context, both locks must be acquired
|
|
4782
4824
|
* - Matches the order used in _consumeFillQueue to prevent deadlocks
|