fix(api): fetch relay swaps first, and never idle while the queue has work
After launch the Ref fetch loop slept ten seconds between batches of twenty, oldest first: 1,574 relay swaps — real 1Click trades through the pool — waited behind thousands of an arbitrage bot's direct calls, which the re-read had queued and which mostly fail, draining at about six a minute. The page's pool swaps and price chart ran hours behind. The queue now serves the relay's entries first, then the least-retried, newest first, and loops straight on while batches (now fifty) come back full; FastNEAR's pacing is the only limit, about a hundred a minute. Refs #37, #39 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015pkwBsR54NRmZyU4QVhvfj
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n select tx_hash, signer, near_height, trader, attempts from ref_pending\n where chain = $1 and near_height <= $2\n order by near_height limit $3\n ",
|
||||
"query": "\n select tx_hash, signer, near_height, trader, attempts from ref_pending\n where chain = $1 and near_height <= $2\n -- The relay's first: each is a solver's swap through the pool, near\n -- certain, where a direct call is as often a bot's failed attempt.\n -- Then the least-retried, newest first, so the page stays current\n -- and a backlog fills in behind it rather than ahead of it.\n order by (signer = 'intents.near') desc, attempts, near_height desc\n limit $3\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -44,5 +44,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3de8c1993770595fd108c10eeba83f0c0107e0aa24dfd440ac3841320efb6615"
|
||||
"hash": "27db80d44ed3461395ff90a0fc77e443354f720243e45d1a6c62ed466b49696f"
|
||||
}
|
||||
@@ -42,7 +42,10 @@ pub const READS: &str = "Ref DCL pools holding the asset — liquidity and limit
|
||||
/// enough for the pool's receipt, which runs a block or two after the relay's.
|
||||
const FETCH_AFTER_BLOCKS: u64 = 20;
|
||||
|
||||
/// How often the queue is worked.
|
||||
/// Queued transactions taken per pass.
|
||||
const FETCH_BATCH: i64 = 50;
|
||||
|
||||
/// How often the queue is worked when it is empty.
|
||||
const FETCH_INTERVAL: Duration = Duration::from_secs(10);
|
||||
|
||||
/// Attempts before a queued transaction is given up on.
|
||||
@@ -100,8 +103,14 @@ async fn fetch(chain: Arc<ChainRuntime>, store: Store, near: NearClient, config:
|
||||
let Some(asset_contract) = config.token_contract().map(str::to_owned) else {
|
||||
return;
|
||||
};
|
||||
let mut backlog = false;
|
||||
loop {
|
||||
tokio::time::sleep(FETCH_INTERVAL).await;
|
||||
// Straight on while the last batch was full: the wait is for an empty
|
||||
// queue, never for one with work in it. After launch it slept ten
|
||||
// seconds between batches of twenty while 1,574 relay swaps waited.
|
||||
if !backlog {
|
||||
tokio::time::sleep(FETCH_INTERVAL).await;
|
||||
}
|
||||
let tip = match near.heights().await {
|
||||
Ok((tip, _)) => tip,
|
||||
Err(e) => {
|
||||
@@ -110,10 +119,13 @@ async fn fetch(chain: Arc<ChainRuntime>, store: Store, near: NearClient, config:
|
||||
}
|
||||
};
|
||||
let due = match store
|
||||
.due_ref_pending(&id, tip.saturating_sub(FETCH_AFTER_BLOCKS), 20)
|
||||
.due_ref_pending(&id, tip.saturating_sub(FETCH_AFTER_BLOCKS), FETCH_BATCH)
|
||||
.await
|
||||
{
|
||||
Ok(d) => d,
|
||||
Ok(d) => {
|
||||
backlog = d.len() as i64 == FETCH_BATCH;
|
||||
d
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(chain = %id, error = %e, "ref queue unreadable");
|
||||
continue;
|
||||
|
||||
@@ -3334,7 +3334,12 @@ impl Store {
|
||||
r#"
|
||||
select tx_hash, signer, near_height, trader, attempts from ref_pending
|
||||
where chain = $1 and near_height <= $2
|
||||
order by near_height limit $3
|
||||
-- The relay's first: each is a solver's swap through the pool, near
|
||||
-- certain, where a direct call is as often a bot's failed attempt.
|
||||
-- Then the least-retried, newest first, so the page stays current
|
||||
-- and a backlog fills in behind it rather than ahead of it.
|
||||
order by (signer = 'intents.near') desc, attempts, near_height desc
|
||||
limit $3
|
||||
"#,
|
||||
chain.as_str(),
|
||||
height as i64,
|
||||
|
||||
Reference in New Issue
Block a user