Skip to content

Commit cd0c1cd

Browse files
authored
feat(tap-agent): use limit to truncate receipts (#194)
Signed-off-by: Gustavo Inacio <[email protected]>
1 parent 3a70fa2 commit cd0c1cd

File tree

3 files changed

+87
-37
lines changed

3 files changed

+87
-37
lines changed

.sqlx/query-411dd183aa723df6c4cf186f070510ae45af8ab1fd9eb795bb4eb27ab43a2ca1.json

Lines changed: 0 additions & 26 deletions
This file was deleted.

.sqlx/query-a1b0c7034cfd7c70154bf71977549a223428e96d7c8af1f3ed68632ead2af548.json renamed to .sqlx/query-b66975fd6a9a26ece9e9baf14975620f674d9ce80715128bb383a5a022d8a77f.json

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tap-agent/src/tap/context/receipt.rs

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use alloy_primitives::hex::ToHex;
1111
use bigdecimal::{num_bigint::ToBigInt, ToPrimitive};
1212
use sqlx::{postgres::types::PgRange, types::BigDecimal};
1313
use tap_core::{
14-
manager::adapters::{ReceiptDelete, ReceiptRead},
14+
manager::adapters::{safe_truncate_receipts, ReceiptDelete, ReceiptRead},
1515
receipt::{Checking, Receipt, ReceiptWithState, SignedReceipt},
1616
};
1717
use thegraph::types::Address;
@@ -79,29 +79,33 @@ impl ReceiptRead for TapAgentContext {
7979
async fn retrieve_receipts_in_timestamp_range<R: RangeBounds<u64> + Send>(
8080
&self,
8181
timestamp_range_ns: R,
82-
// TODO: Make use of this limit in this function
83-
_receipts_limit: Option<u64>,
82+
receipts_limit: Option<u64>,
8483
) -> Result<Vec<ReceiptWithState<Checking>>, Self::AdapterError> {
8584
let signers = signers_trimmed(&self.escrow_accounts, self.sender)
8685
.await
8786
.map_err(|e| AdapterError::ReceiptRead {
8887
error: format!("{:?}.", e),
8988
})?;
9089

90+
let receipts_limit = receipts_limit.map_or(1000, |limit| limit);
91+
9192
let records = sqlx::query!(
9293
r#"
9394
SELECT id, signature, allocation_id, timestamp_ns, nonce, value
9495
FROM scalar_tap_receipts
9596
WHERE allocation_id = $1 AND signer_address IN (SELECT unnest($2::text[]))
96-
AND $3::numrange @> timestamp_ns
97+
AND $3::numrange @> timestamp_ns
98+
ORDER BY timestamp_ns ASC
99+
LIMIT $4
97100
"#,
98101
self.allocation_id.encode_hex::<String>(),
99102
&signers,
100-
rangebounds_to_pgrange(timestamp_range_ns)
103+
rangebounds_to_pgrange(timestamp_range_ns),
104+
(receipts_limit + 1) as i64,
101105
)
102106
.fetch_all(&self.pgpool)
103107
.await?;
104-
records
108+
let mut receipts = records
105109
.into_iter()
106110
.map(|record| {
107111
let signature = record.signature.as_slice().try_into()
@@ -148,7 +152,11 @@ impl ReceiptRead for TapAgentContext {
148152
Ok(ReceiptWithState::new(signed_receipt))
149153

150154
})
151-
.collect()
155+
.collect::<Result<Vec<ReceiptWithState<Checking>>, AdapterError>>()?;
156+
157+
safe_truncate_receipts(&mut receipts, receipts_limit);
158+
159+
Ok(receipts)
152160
}
153161
}
154162

@@ -275,7 +283,6 @@ mod test {
275283

276284
// Retrieving receipts in timestamp range from the database, convert to json Value
277285
let recovered_received_receipt_vec = storage_adapter
278-
// TODO: Make use of the receipt limit if it makes sense here
279286
.retrieve_receipts_in_timestamp_range(range, None)
280287
.await?
281288
.into_iter()
@@ -424,6 +431,74 @@ mod test {
424431
Ok(())
425432
}
426433

434+
#[sqlx::test(migrations = "../migrations")]
435+
async fn retrieve_receipts_with_limit(pgpool: PgPool) {
436+
let escrow_accounts = Eventual::from_value(EscrowAccounts::new(
437+
HashMap::from([(SENDER.1, 1000.into())]),
438+
HashMap::from([(SENDER.1, vec![SIGNER.1])]),
439+
));
440+
441+
let storage_adapter = TapAgentContext::new(
442+
pgpool.clone(),
443+
*ALLOCATION_ID_0,
444+
SENDER.1,
445+
escrow_accounts.clone(),
446+
EscrowAdapter::mock(),
447+
);
448+
449+
// Creating 100 receipts with timestamps 42 to 141
450+
for i in 0..100 {
451+
let receipt = create_received_receipt(
452+
&ALLOCATION_ID_0,
453+
&SIGNER.0,
454+
i + 684,
455+
i + 42,
456+
(i + 124).into(),
457+
);
458+
store_receipt(&pgpool, receipt.signed_receipt())
459+
.await
460+
.unwrap();
461+
}
462+
463+
let recovered_received_receipt_vec = storage_adapter
464+
.retrieve_receipts_in_timestamp_range(0..141, Some(10))
465+
.await
466+
.unwrap();
467+
assert_eq!(recovered_received_receipt_vec.len(), 10);
468+
469+
let recovered_received_receipt_vec = storage_adapter
470+
.retrieve_receipts_in_timestamp_range(0..141, Some(50))
471+
.await
472+
.unwrap();
473+
assert_eq!(recovered_received_receipt_vec.len(), 50);
474+
475+
// add a copy in the same timestamp
476+
for i in 0..100 {
477+
let receipt = create_received_receipt(
478+
&ALLOCATION_ID_0,
479+
&SIGNER.0,
480+
i + 684,
481+
i + 43,
482+
(i + 124).into(),
483+
);
484+
store_receipt(&pgpool, receipt.signed_receipt())
485+
.await
486+
.unwrap();
487+
}
488+
489+
let recovered_received_receipt_vec = storage_adapter
490+
.retrieve_receipts_in_timestamp_range(0..141, Some(10))
491+
.await
492+
.unwrap();
493+
assert_eq!(recovered_received_receipt_vec.len(), 9);
494+
495+
let recovered_received_receipt_vec = storage_adapter
496+
.retrieve_receipts_in_timestamp_range(0..141, Some(50))
497+
.await
498+
.unwrap();
499+
assert_eq!(recovered_received_receipt_vec.len(), 49);
500+
}
501+
427502
#[sqlx::test(migrations = "../migrations")]
428503
async fn retrieve_receipts_in_timestamp_range(pgpool: PgPool) {
429504
let escrow_accounts = Eventual::from_value(EscrowAccounts::new(

0 commit comments

Comments
 (0)