Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
428 changes: 428 additions & 0 deletions crates/sui-graphql-e2e-tests/tests/pruning/transactions.exp

Large diffs are not rendered by default.

331 changes: 331 additions & 0 deletions crates/sui-graphql-e2e-tests/tests/pruning/transactions.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# init --protocol-version 51 --addresses Test=0x0 --accounts A --simulator --epochs-to-keep 2

//# publish
module Test::M1 {
use sui::coin::Coin;

public struct Object has key, store {
id: UID,
value: u64,
}

fun foo<T: key, T2: drop>(_p1: u64, value1: T, _value2: &Coin<T2>, _p2: u64): T {
value1
}

public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) {
transfer::public_transfer(
Object { id: object::new(ctx), value },
recipient
)
}
}

//# run Test::M1::create --sender A --args 0 @A

//# create-checkpoint

//# advance-epoch

//# run Test::M1::create --sender A --args 1 @A

//# create-checkpoint

//# advance-epoch

//# run Test::M1::create --sender A --args 2 @A

//# create-checkpoint

//# advance-epoch

//# run Test::M1::create --sender A --args 3 @A

//# create-checkpoint

//# run-graphql --wait-for-checkpoint-pruned 4
# The smallest unpruned epoch is 2, starting with checkpoint sequence number 5
# When a range is not specified, transactions queries should return results starting from the smallest unpruned tx
{
epoch {
epochId
}
checkpoints {
nodes {
epoch {
epochId
}
sequenceNumber
}
}
unfiltered: transactionBlocks {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
transactionBlocks(filter: { signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --wait-for-checkpoint-pruned 4
# In the absence of an upper bound, graphql sets the upper bound to `checkpoint_viewed_at`'s max tx + 1 (right-open interval)
{
transactionBlocks(filter: { afterCheckpoint: 5 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --wait-for-checkpoint-pruned 4
# In the absence of a lower bound, graphql sets the lower bound to the smallest unpruned checkpoint's min tx
{
transactionBlocks(filter: { beforeCheckpoint: 7 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}



//# run-graphql --wait-for-checkpoint-pruned 4
# If the caller tries to fetch data outside of the unpruned range, they should receive an error
{
transactionBlocks(filter: { atCheckpoint: 0 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --wait-for-checkpoint-pruned 4
# Empty response if caller tries to fetch data beyond the available upper bound
{
transactionBlocks(filter: { atCheckpoint: 10 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}


//# run-graphql
# Mirror from the back
{
transactionBlocks(last: 10 filter: { signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql
# Mirror from the back
{
transactionBlocks(last: 10 filter: { afterCheckpoint: 5 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql
# Mirror from the back
{
transactionBlocks(last: 10 filter: { beforeCheckpoint: 7 signAddress: "@{A}" }) {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --cursors {"c":7,"t":6,"i":false}
# The first tx after pruning has seq num 6.
# When viewed at checkpoint 7, there are two more txs that follow it.
{
transactionBlocks(after: "@{cursor_0}") {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --cursors {"c":7,"t":0,"i":false}
# Data is pruned and no longer available
{
transactionBlocks(after: "@{cursor_0}") {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --cursors {"c":7,"t":0,"i":true}
# Data is pruned and no longer available
{
transactionBlocks(after: "@{cursor_0}") {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}

//# run-graphql --cursors {"c":7,"t":0,"i":true}
# Data is pruned and no longer available
{
transactionBlocks(scanLimit: 10000 after: "@{cursor_0}") {
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
nodes {
digest
effects {
checkpoint {
sequenceNumber
}
}
}
}
}
9 changes: 9 additions & 0 deletions crates/sui-graphql-e2e-tests/tests/stable/prune.exp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ task 11, lines 45-55:
//# run-graphql --wait-for-checkpoint-pruned 4
Response: {
"data": {
"epoch": {
"epochId": 3
},
"checkpoints": {
"nodes": [
{
Expand All @@ -65,6 +68,12 @@ Response: {
"epochId": 2
},
"sequenceNumber": 6
},
{
"epoch": {
"epochId": 3
},
"sequenceNumber": 7
}
]
}
Expand Down
3 changes: 3 additions & 0 deletions crates/sui-graphql-e2e-tests/tests/stable/prune.move
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ module Test::M1 {

//# run-graphql --wait-for-checkpoint-pruned 4
{
epoch {
epochId
}
checkpoints {
nodes {
epoch {
Expand Down
8 changes: 5 additions & 3 deletions crates/sui-graphql-rpc/src/server/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ async fn health_check(
.unwrap_or_else(|| DEFAULT_MAX_CHECKPOINT_LAG);

let checkpoint_timestamp =
Duration::from_millis(watermark_lock.read().await.checkpoint_timestamp_ms);
Duration::from_millis(watermark_lock.read().await.hi_cp_timestamp_ms);

let now_millis = Utc::now().timestamp_millis();

Expand Down Expand Up @@ -730,9 +730,11 @@ pub mod tests {
let pg_conn_pool = PgManager::new(reader);
let cancellation_token = CancellationToken::new();
let watermark = Watermark {
checkpoint: 1,
checkpoint_timestamp_ms: 1,
hi_cp: 1,
hi_cp_timestamp_ms: 1,
epoch: 0,
lo_cp: 0,
lo_tx: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we record hi_tx as well? It would seem to be symmetric and we do need to use that for the transaction queries.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we care about the transaction upperbound for whatever the checkpoint upperbound is, so it doesn't really help to track hi_tx here.

};
let state = AppState::new(
connection_config.clone(),
Expand Down
Loading
Loading