diff --git a/crates/sui-graphql-e2e-tests/tests/available_range/available_range.exp b/crates/sui-graphql-e2e-tests/tests/available_range/available_range.exp index f5e7f1369bf4e..a6d0ac388073a 100644 --- a/crates/sui-graphql-e2e-tests/tests/available_range/available_range.exp +++ b/crates/sui-graphql-e2e-tests/tests/available_range/available_range.exp @@ -1,6 +1,6 @@ -processed 5 tasks +processed 17 tasks -task 1, lines 6-28: +task 1, lines 8-30: //# run-graphql Response: { "data": { @@ -25,35 +25,105 @@ Response: { } } -task 2, line 30: +task 3, line 34: //# create-checkpoint Checkpoint created: 1 -task 3, line 33: +task 4, lines 36-46: +//# run-graphql +Response: { + "data": { + "availableRange": { + "first": { + "sequenceNumber": 0 + }, + "last": { + "sequenceNumber": 1 + } + } + } +} + +task 6, line 50: //# create-checkpoint Checkpoint created: 2 -task 4, lines 36-58: +task 7, lines 52-62: //# run-graphql Response: { "data": { "availableRange": { "first": { - "digest": "ZQawQqeikA4pRqKnkcuHuMnGZuKJTSt3V3EVmMjG56k", "sequenceNumber": 0 }, "last": { - "digest": "5GTvEftM57hVrNtNapMU73cE5Wj6mYFuzd9K644n1Zqs", "sequenceNumber": 2 } + } + } +} + +task 9, line 66: +//# create-checkpoint +Checkpoint created: 3 + +task 10, lines 68-78: +//# run-graphql +Response: { + "data": { + "availableRange": { + "first": { + "sequenceNumber": 1 + }, + "last": { + "sequenceNumber": 3 + } + } + } +} + +task 12, line 82: +//# create-checkpoint +Checkpoint created: 4 + +task 13, lines 84-94: +//# run-graphql +Response: { + "data": { + "availableRange": { + "first": { + "sequenceNumber": 2 + }, + "last": { + "sequenceNumber": 4 + } + } + } +} + +task 15, line 98: +//# create-checkpoint +Checkpoint created: 5 + +task 16, lines 100-120: +//# run-graphql +Response: { + "data": { + "availableRange": { + "first": { + "sequenceNumber": 3 + }, + "last": { + "sequenceNumber": 5 + } }, "first": { "digest": "ZQawQqeikA4pRqKnkcuHuMnGZuKJTSt3V3EVmMjG56k", "sequenceNumber": 0 }, "last": { - "digest": "5GTvEftM57hVrNtNapMU73cE5Wj6mYFuzd9K644n1Zqs", - "sequenceNumber": 2 + "digest": "9C7jQMv4YDXtBQFVawbAJTtQf7JefT3XPNUNoWSot5T2", + "sequenceNumber": 5 } } } diff --git a/crates/sui-graphql-e2e-tests/tests/available_range/available_range.move b/crates/sui-graphql-e2e-tests/tests/available_range/available_range.move index d6855d560f766..403803d613c32 100644 --- a/crates/sui-graphql-e2e-tests/tests/available_range/available_range.move +++ b/crates/sui-graphql-e2e-tests/tests/available_range/available_range.move @@ -1,7 +1,9 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -//# init --protocol-version 51 --simulator +// Test that available range is correctly updated per objects_snapshot catching up + +//# init --protocol-version 51 --simulator --objects-snapshot-min-checkpoint-lag 2 //# run-graphql { @@ -27,21 +29,81 @@ } } +//# advance-clock --duration-ns 1 + //# create-checkpoint +//# run-graphql +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } +} + +//# advance-clock --duration-ns 1 //# create-checkpoint +//# run-graphql +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } +} + +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# run-graphql +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } +} + +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# run-graphql +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } +} + +//# advance-clock --duration-ns 1 + +//# create-checkpoint //# run-graphql { availableRange { first { - digest sequenceNumber } last { - digest sequenceNumber } } diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/balances.exp b/crates/sui-graphql-e2e-tests/tests/consistency/balances.exp index e4529876bfe9b..87df39c8a51c6 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/balances.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/balances.exp @@ -1,4 +1,4 @@ -processed 34 tasks +processed 42 tasks init: A: object(0,0), B: object(0,1) @@ -166,10 +166,6 @@ Response: { } } -task 19, line 147: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 3 -Objects snapshot updated to [0 to 3) - task 20, line 149: //# create-checkpoint Checkpoint created: 8 @@ -282,18 +278,26 @@ Response: { } } -task 24, line 220: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 -Objects snapshot updated to [0 to 4) - task 25, line 222: //# create-checkpoint Checkpoint created: 9 -task 26, lines 224-245: +task 27, line 226: +//# create-checkpoint +Checkpoint created: 10 + +task 28, lines 228-257: //# run-graphql --cursors {"c":2,"t":1,"i":false} Response: { "data": { + "availableRange": { + "first": { + "sequenceNumber": 3 + }, + "last": { + "sequenceNumber": 10 + } + }, "transactionBlocks": { "nodes": [ { @@ -307,7 +311,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 9, + "line": 17, "column": 9 } ], @@ -325,7 +329,7 @@ Response: { ] } -task 27, lines 247-268: +task 29, lines 259-280: //# run-graphql --cursors {"c":3,"t":1,"i":false} Response: { "data": { @@ -361,7 +365,7 @@ Response: { } } -task 28, lines 270-291: +task 30, lines 282-303: //# run-graphql --cursors {"c":4,"t":1,"i":false} Response: { "data": { @@ -397,18 +401,34 @@ Response: { } } -task 29, line 294: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 6 -Objects snapshot updated to [0 to 6) +task 32, line 307: +//# create-checkpoint +Checkpoint created: 11 -task 30, line 296: +task 34, line 311: //# create-checkpoint -Checkpoint created: 10 +Checkpoint created: 12 -task 31, lines 298-319: +task 36, line 315: +//# create-checkpoint +Checkpoint created: 13 + +task 38, line 319: +//# create-checkpoint +Checkpoint created: 14 + +task 39, lines 321-350: //# run-graphql --cursors {"c":2,"t":1,"i":false} Response: { "data": { + "availableRange": { + "first": { + "sequenceNumber": 7 + }, + "last": { + "sequenceNumber": 14 + } + }, "transactionBlocks": { "nodes": [ { @@ -422,7 +442,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 9, + "line": 17, "column": 9 } ], @@ -440,10 +460,18 @@ Response: { ] } -task 32, lines 321-342: +task 40, lines 352-381: //# run-graphql --cursors {"c":3,"t":1,"i":false} Response: { "data": { + "availableRange": { + "first": { + "sequenceNumber": 7 + }, + "last": { + "sequenceNumber": 14 + } + }, "transactionBlocks": { "nodes": [ { @@ -457,7 +485,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 9, + "line": 17, "column": 9 } ], @@ -475,10 +503,18 @@ Response: { ] } -task 33, lines 344-365: +task 41, lines 383-412: //# run-graphql --cursors {"c":4,"t":1,"i":false} Response: { "data": { + "availableRange": { + "first": { + "sequenceNumber": 7 + }, + "last": { + "sequenceNumber": 14 + } + }, "transactionBlocks": { "nodes": [ { @@ -492,7 +528,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 9, + "line": 17, "column": 9 } ], diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/balances.move b/crates/sui-graphql-e2e-tests/tests/consistency/balances.move index 48bb049a865ab..2f524ac0e7d3c 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/balances.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/balances.move @@ -14,7 +14,7 @@ // snapshot@[0, 4), first two transaction blocks are out of available range. // snapshot@[0, 6), all transaction blocks are out of available range. -//# init --protocol-version 51 --addresses P0=0x0 --accounts A B --simulator +//# init --protocol-version 51 --addresses P0=0x0 --accounts A B --simulator --objects-snapshot-min-checkpoint-lag 7 //# publish --sender A module P0::fake { @@ -144,7 +144,7 @@ module P0::fake { } } -//# force-object-snapshot-catchup --start-cp 0 --end-cp 3 +//# advance-clock --duration-ns 1 //# create-checkpoint @@ -217,13 +217,25 @@ module P0::fake { } } -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# advance-clock --duration-ns 1 //# create-checkpoint //# run-graphql --cursors {"c":2,"t":1,"i":false} # Outside available range { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { nodes { sender { @@ -290,14 +302,33 @@ module P0::fake { } } +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# advance-clock --duration-ns 1 + +//# create-checkpoint -//# force-object-snapshot-catchup --start-cp 0 --end-cp 6 +//# advance-clock --duration-ns 1 //# create-checkpoint //# run-graphql --cursors {"c":2,"t":1,"i":false} # Outside available range { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { nodes { sender { @@ -321,6 +352,14 @@ module P0::fake { //# run-graphql --cursors {"c":3,"t":1,"i":false} # Outside available range { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { nodes { sender { @@ -344,6 +383,14 @@ module P0::fake { //# run-graphql --cursors {"c":4,"t":1,"i":false} # Outside available range { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) { nodes { sender { diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/coins.exp b/crates/sui-graphql-e2e-tests/tests/consistency/coins.exp index 93d37879a2a4e..b01587ebc8faf 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/coins.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/coins.exp @@ -1,4 +1,4 @@ -processed 21 tasks +processed 15 tasks init: A: object(0,0), B: object(0,1) @@ -14,818 +14,306 @@ task 2, line 41: //# create-checkpoint Checkpoint created: 1 -task 3, lines 43-45: -//# programmable --sender A --inputs object(1,5) 100000 object(1,1) -//> 0: sui::coin::mint(Input(0), Input(1)); -//> MergeCoins(Input(2), [Result(0)]); -mutated: object(0,0), object(1,1), object(1,5) -unchanged_shared: 0x0000000000000000000000000000000000000000000000000000000000000403 -gas summary: computation_cost: 1000000, storage_cost: 4012800, storage_rebate: 3972672, non_refundable_storage_fee: 40128 - -task 4, line 47: -//# create-checkpoint -Checkpoint created: 2 - -task 5, lines 49-90: +task 3, lines 43-67: //# run-graphql Response: { "data": { - "queryCoinsAtLatest": { - "edges": [ + "availableRange": { + "first": { + "sequenceNumber": 0 + }, + "last": { + "sequenceNumber": 1 + } + }, + "coins": { + "nodes": [ { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AgAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "contents": { + "json": { + "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", + "balance": { + "value": "300" } } } }, { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAgAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "contents": { + "json": { + "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", + "balance": { + "value": "200" } } } }, { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AgAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - }, - "addressCoins": { - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" } }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AgAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } + "contents": { + "json": { + "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", + "balance": { + "value": "100" } } } - ] - } + } + ] } } } -task 6, lines 92-133: -//# run-graphql --cursors @{obj_1_3,1} +task 4, line 69: +//# transfer-object 1,1 --sender A --recipient B +mutated: object(0,0), object(1,1) +unchanged_shared: 0x0000000000000000000000000000000000000000000000000000000000000403 +gas summary: computation_cost: 1000000, storage_cost: 2310400, storage_rebate: 2287296, non_refundable_storage_fee: 23104 + +task 5, lines 71-73: +//# transfer-object 1,1 --sender B --recipient A +mutated: object(0,1), object(1,1) +unchanged_shared: 0x0000000000000000000000000000000000000000000000000000000000000403 +gas summary: computation_cost: 1000000, storage_cost: 2310400, storage_rebate: 1309176, non_refundable_storage_fee: 13224 + +task 6, line 75: +//# create-checkpoint +Checkpoint created: 2 + +task 7, lines 77-101: +//# run-graphql Response: { "data": { - "queryCoinsAtChkpt1": { - "edges": [ + "availableRange": { + "first": { + "sequenceNumber": 1 + }, + "last": { + "sequenceNumber": 2 + } + }, + "coins": { + "nodes": [ { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "contents": { + "json": { + "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", + "balance": { + "value": "300" } } } }, { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "contents": { + "json": { + "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", + "balance": { + "value": "200" } } } - } - ] - }, - "queryAddressCoinsAtChkpt1": { - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } + }, + { + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" } }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } + "contents": { + "json": { + "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", + "balance": { + "value": "100" } } } - ] - } + } + ] } } } -task 7, line 135: +task 8, line 103: //# transfer-object 1,2 --sender A --recipient B mutated: object(0,0), object(1,2) unchanged_shared: 0x0000000000000000000000000000000000000000000000000000000000000403 gas summary: computation_cost: 1000000, storage_cost: 2310400, storage_rebate: 2287296, non_refundable_storage_fee: 23104 -task 8, line 137: +task 9, line 105: //# transfer-object 1,3 --sender A --recipient B mutated: object(0,0), object(1,3) unchanged_shared: 0x0000000000000000000000000000000000000000000000000000000000000403 gas summary: computation_cost: 1000000, storage_cost: 2310400, storage_rebate: 2287296, non_refundable_storage_fee: 23104 -task 9, line 139: +task 10, line 107: //# create-checkpoint Checkpoint created: 3 -task 10, lines 141-194: +task 11, lines 109-135: //# run-graphql Response: { "data": { - "queryCoins": { - "edges": [ + "availableRange": { + "first": { + "sequenceNumber": 2 + }, + "last": { + "sequenceNumber": 3 + } + }, + "coins": { + "nodes": [ { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AwAAAAAAAAA=", - "node": { + "owner": { "owner": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "contents": { + "json": { + "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", + "balance": { + "value": "300" } } } }, { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAwAAAAAAAAA=", - "node": { + "owner": { "owner": { - "owner": { - "address": "0xa7b032703878aa74c3126935789fd1d4d7e111d5911b09247d6963061c312b5a", - "coins": { - "edges": [ - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } + "address": "0xa7b032703878aa74c3126935789fd1d4d7e111d5911b09247d6963061c312b5a" + } + }, + "contents": { + "json": { + "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", + "balance": { + "value": "200" } } } }, { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AwAAAAAAAAA=", - "node": { + "owner": { "owner": { - "owner": { - "address": "0xa7b032703878aa74c3126935789fd1d4d7e111d5911b09247d6963061c312b5a", - "coins": { - "edges": [ - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - }, - "addressCoinsA": { - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "100300" - } - } - } - } - } - ] - } - }, - "addressCoinsB": { - "coins": { - "edges": [ - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } + "address": "0xa7b032703878aa74c3126935789fd1d4d7e111d5911b09247d6963061c312b5a" } }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AwAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } + "contents": { + "json": { + "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", + "balance": { + "value": "100" } } } - ] - } + } + ] } } } -task 12, line 198: -//# create-checkpoint -Checkpoint created: 4 - -task 14, line 202: -//# create-checkpoint -Checkpoint created: 5 - -task 16, line 206: -//# create-checkpoint -Checkpoint created: 6 - -task 17, lines 208-249: -//# run-graphql --cursors @{obj_1_3,1} +task 12, lines 137-163: +//# run-graphql --cursors @{obj_1_1,2} Response: { "data": { - "queryCoinsAtChkpt1BeforeSnapshotCatchup": { - "edges": [ + "availableRange": { + "first": { + "sequenceNumber": 2 + }, + "last": { + "sequenceNumber": 3 + } + }, + "coins": { + "nodes": [ { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" + } + }, + "address": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", + "contents": { + "json": { + "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", + "balance": { + "value": "200" } } } }, { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "consistentStateForEachCoin": { - "owner": { - "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e", - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } - } - }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - }, - { - "cursor": "INvVgLVfu65ukifQh30BNot195gE45+jwKQekLi2+XX5AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", - "balance": { - "value": "100" - } - } - } - } - } - ] - } - } - }, - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } - } - } - } - ] - }, - "queryAddressCoinsAtChkpt1BeforeSnapshotCatchup": { - "coins": { - "edges": [ - { - "cursor": "IInOO25b7OLrzHU3/p2iQ4vqVRlcuGr7fd9alLifbc72AQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0x89ce3b6e5bece2ebcc7537fe9da2438bea55195cb86afb7ddf5a94b89f6dcef6", - "balance": { - "value": "300" - } - } - } + "owner": { + "owner": { + "address": "0xfccc9a421bbb13c1a66a1aa98f0ad75029ede94857779c6915b44f94068b921e" } }, - { - "cursor": "INs4hFLNnqflqu5eGW8MOzUCEfYiGoqxYWNks0dajqpyAQAAAAAAAAA=", - "node": { - "contents": { - "json": { - "id": "0xdb388452cd9ea7e5aaee5e196f0c3b350211f6221a8ab1616364b3475a8eaa72", - "balance": { - "value": "200" - } - } + "address": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", + "contents": { + "json": { + "id": "0xdbd580b55fbbae6e9227d0877d01368b75f79804e39fa3c0a41e90b8b6f975f9", + "balance": { + "value": "100" } } } - ] - } + } + ] } } } -task 18, line 251: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 -Objects snapshot updated to [0 to 4) - -task 19, line 253: -//# create-checkpoint -Checkpoint created: 7 +task 13, lines 165-191: +//# run-graphql --cursors @{obj_1_1,1} +Response: { + "data": null, + "errors": [ + { + "message": "Requested data is outside the available range", + "locations": [ + { + "line": 11, + "column": 3 + } + ], + "path": [ + "coins" + ], + "extensions": { + "code": "BAD_USER_INPUT" + } + } + ] +} -task 20, lines 255-284: -//# run-graphql --cursors @{obj_1_3,1} +task 14, lines 193-219: +//# run-graphql --cursors @{obj_1_1,0} Response: { "data": null, "errors": [ @@ -833,12 +321,12 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 2, + "line": 11, "column": 3 } ], "path": [ - "queryCoinsAtChkpt1AfterSnapshotCatchup" + "coins" ], "extensions": { "code": "BAD_USER_INPUT" diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/coins.move b/crates/sui-graphql-e2e-tests/tests/consistency/coins.move index 98db3d246f714..e5eac83ae47b5 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/coins.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/coins.move @@ -1,13 +1,13 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -// chkpt 1 | chkpt 2 | chkpt 3 | chkpt 4 | chkpt 5 | snapshot [0, 4) -// ----------------------------------------------------------------- -// coin1@A | coin1@B | coin1@B | coin1@B | coin1@B | coin1@B -// coin2@A | coin2@B | coin2@B | coin2@B | coin2@B | coin2@B -// coin3@A | coin3@A | coin3@A | coin3@A | coin3@A | coin3@A +// chkpt 1 | chkpt 2 | chkpt 3 | +// ----------------------------- +// coin1@A | coin1@A | coin1@B | +// coin2@A | coin2@A | coin2@B | +// coin3@A | coin3@A | coin3@A | -//# init --protocol-version 51 --addresses P0=0x0 --accounts A B --simulator +//# init --protocol-version 51 --addresses P0=0x0 --accounts A B --simulator --objects-snapshot-min-checkpoint-lag 1 //# publish --sender A module P0::fake { @@ -40,94 +40,62 @@ module P0::fake { //# create-checkpoint -//# programmable --sender A --inputs object(1,5) 100000 object(1,1) -//> 0: sui::coin::mint(Input(0), Input(1)); -//> MergeCoins(Input(2), [Result(0)]); - -//# create-checkpoint - //# run-graphql { - queryCoinsAtLatest: coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - consistentStateForEachCoin: owner { - ... on AddressOwner { - owner { - address - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json - } - } - } - } - } - } - } - contents { - json - } - } + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber } } - addressCoins: address(address: "@{A}") { - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json + coins(type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } } + contents { + json + } } } } -//# run-graphql --cursors @{obj_1_3,1} +//# transfer-object 1,1 --sender A --recipient B + +//# transfer-object 1,1 --sender B --recipient A + +// The above are done so there are object changes to trigger the objects snapshot processor + +//# create-checkpoint + +//# run-graphql { - queryCoinsAtChkpt1: coins(type: "@{P0}::fake::FAKE", before: "@{cursor_0}") { - edges { - cursor - node { - consistentStateForEachCoin: owner { - ... on AddressOwner { - owner { - address - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json - } - } - } - } - } - } - } - contents { - json - } - } + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber } } - queryAddressCoinsAtChkpt1: address(address: "@{A}") { - coins(type: "@{P0}::fake::FAKE", before: "@{cursor_0}") { - edges { - cursor - node { - contents { - json + coins(type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } } + contents { + json + } } } } @@ -139,145 +107,112 @@ module P0::fake { //# create-checkpoint //# run-graphql +# First coin owner should be different from the last two, +# and last two coin owners should be the same { - queryCoins: coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - owner { - ... on AddressOwner { - owner { - address - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json - } - } - } - } - } - } - } - contents { - json - } - } + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber } } - addressCoinsA: address(address: "@{A}") { - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json + coins(type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } } + contents { + json + } } } - addressCoinsB: address(address: "@{B}") { - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json +} + +//# run-graphql --cursors @{obj_1_1,2} +# There should be two coins, and the coin owners should be the same as the owner of the first coin in the previous query +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } + coins(after: "@{cursor_0}" type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } } + address + contents { + json + } } } } -//# advance-clock --duration-ns 1 - -//# create-checkpoint - -//# advance-clock --duration-ns 1 - -//# create-checkpoint - -//# advance-clock --duration-ns 1 - -//# create-checkpoint - -//# run-graphql --cursors @{obj_1_3,1} +//# run-graphql --cursors @{obj_1_1,1} +# Outside of available range { - queryCoinsAtChkpt1BeforeSnapshotCatchup: coins(type: "@{P0}::fake::FAKE", before: "@{cursor_0}") { - edges { - cursor - node { - consistentStateForEachCoin: owner { - ... on AddressOwner { - owner { - address - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json - } - } - } - } - } - } - } - contents { - json - } - } + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber } } - queryAddressCoinsAtChkpt1BeforeSnapshotCatchup: address(address: "@{A}") { - coins(type: "@{P0}::fake::FAKE", before: "@{cursor_0}") { - edges { - cursor - node { - contents { - json + coins(after: "@{cursor_0}" type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } } + address + contents { + json + } } } } -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 - -//# create-checkpoint - -//# run-graphql --cursors @{obj_1_3,1} +//# run-graphql --cursors @{obj_1_1,0} +# Outside of available range { - queryCoinsAtChkpt1AfterSnapshotCatchup: coins(type: "@{P0}::fake::FAKE", before: "@{cursor_0}") { - edges { - cursor - node { - consistentStateForEachCoin: owner { - ... on AddressOwner { - owner { - address - coins(type: "@{P0}::fake::FAKE") { - edges { - cursor - node { - contents { - json - } - } - } - } - } + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } + coins(after: "@{cursor_0}" type: "@{P0}::fake::FAKE") { + nodes { + owner { + ... on AddressOwner { + owner { + address } } - contents { - json - } + } + address + contents { + json } } } diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.exp b/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.exp index 51b7b407d25ad..f02cf8c9f0004 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.exp @@ -1,4 +1,4 @@ -processed 35 tasks +processed 37 tasks init: A: object(0,0) @@ -987,23 +987,31 @@ task 30, line 439: //# create-checkpoint Checkpoint created: 6 -task 31, line 441: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 5 -Objects snapshot updated to [0 to 5) - task 32, line 443: //# create-checkpoint Checkpoint created: 7 -task 33, lines 445-495: +task 34, line 447: +//# create-checkpoint +Checkpoint created: 8 + +task 35, lines 449-507: //# run-graphql --cursors @{obj_5_0,2} @{obj_5_0,4} Response: { "data": { + "availableRange": { + "first": { + "sequenceNumber": 4 + }, + "last": { + "sequenceNumber": 8 + } + }, "parent_version_4_outside_consistent_range": { "dynamicFields": { "edges": [ { - "cursor": "ICcYjAeDlWXNcui8GLsj8FTtebUvmAuwomLTvboe4VlTBwAAAAAAAAA=", + "cursor": "ICcYjAeDlWXNcui8GLsj8FTtebUvmAuwomLTvboe4VlTCAAAAAAAAAA=", "node": { "name": { "bcs": "pAEAAAAAAAA=", @@ -1029,7 +1037,7 @@ Response: { "dynamicFields": { "edges": [ { - "cursor": "ICcYjAeDlWXNcui8GLsj8FTtebUvmAuwomLTvboe4VlTBwAAAAAAAAA=", + "cursor": "ICcYjAeDlWXNcui8GLsj8FTtebUvmAuwomLTvboe4VlTCAAAAAAAAAA=", "node": { "name": { "bcs": "pAEAAAAAAAA=", @@ -1048,7 +1056,7 @@ Response: { } }, { - "cursor": "IFshQaGmiN295CGbfzbLNJ8dM9rQd4ZFHYMKPA41oWdOBwAAAAAAAAA=", + "cursor": "IFshQaGmiN295CGbfzbLNJ8dM9rQd4ZFHYMKPA41oWdOCAAAAAAAAAA=", "node": { "name": { "bcs": "A2RmNg==", @@ -1062,7 +1070,7 @@ Response: { } }, { - "cursor": "IIRmgnmPueemYOYD96Wne4t7x4ZFBek0fbBlni8FlY5HBwAAAAAAAAA=", + "cursor": "IIRmgnmPueemYOYD96Wne4t7x4ZFBek0fbBlni8FlY5HCAAAAAAAAAA=", "node": { "name": { "bcs": "A2RmNA==", @@ -1076,7 +1084,7 @@ Response: { } }, { - "cursor": "IOFWPka97OJZ2Ia9l1R0ER1fhI5P/jltrvGJbm/ekNWABwAAAAAAAAA=", + "cursor": "IOFWPka97OJZ2Ia9l1R0ER1fhI5P/jltrvGJbm/ekNWACAAAAAAAAAA=", "node": { "name": { "bcs": "A2RmNQ==", @@ -1146,7 +1154,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 34, + "line": 42, "column": 5 } ], @@ -1161,7 +1169,7 @@ Response: { ] } -task 34, lines 497-528: +task 36, lines 509-540: //# run-graphql Response: { "data": { diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.move b/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.move index 15bbf6e153580..367247a2ba154 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/dynamic_fields/dynamic_fields.move @@ -7,7 +7,7 @@ // chkpt3: add df4, 5, 6 parent @ version 5, child @ version 4 // chkpt4: remove df1, df2, df3 parent @ version 6, child @ version 4 -//# init --protocol-version 51 --addresses Test=0x0 --accounts A --simulator +//# init --protocol-version 51 --addresses Test=0x0 --accounts A --simulator --objects-snapshot-min-checkpoint-lag 4 //# publish module Test::M1 { @@ -438,7 +438,11 @@ fragment DynamicFieldSelect on DynamicField { //# create-checkpoint -//# force-object-snapshot-catchup --start-cp 0 --end-cp 5 +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# advance-clock --duration-ns 1 //# create-checkpoint @@ -472,6 +476,14 @@ fragment DynamicFieldsSelect on DynamicFieldConnection { } { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } parent_version_4_outside_consistent_range: object(address: "@{obj_2_1}", version: 4) { dynamicFields { ...DynamicFieldsSelect diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.exp b/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.exp index 5c5af6023700e..4cfc609655cfe 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.exp @@ -1,25 +1,25 @@ -processed 20 tasks +processed 33 tasks init: A: object(0,0) -task 1, lines 19-56: +task 1, lines 17-54: //# publish created: object(1,0) mutated: object(0,1) gas summary: computation_cost: 1000000, storage_cost: 7014800, storage_rebate: 0, non_refundable_storage_fee: 0 -task 2, line 58: +task 2, line 56: //# run Test::M1::create --args 0 @A created: object(2,0) mutated: object(0,1) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 3, line 60: +task 3, line 58: //# create-checkpoint Checkpoint created: 1 -task 4, lines 62-75: +task 4, lines 60-73: //# run-graphql Response: { "data": { @@ -38,16 +38,16 @@ Response: { } } -task 5, line 77: +task 5, line 75: //# run Test::M1::update --sender A --args object(2,0) 1 mutated: object(0,0), object(2,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 1301652, non_refundable_storage_fee: 13148 -task 6, line 79: +task 6, line 77: //# create-checkpoint Checkpoint created: 2 -task 7, lines 81-107: +task 7, lines 79-105: //# run-graphql Response: { "data": { @@ -78,18 +78,18 @@ Response: { } } -task 8, line 109: +task 8, line 107: //# run Test::M1::wrap --sender A --args object(2,0) created: object(8,0) mutated: object(0,0) wrapped: object(2,0) gas summary: computation_cost: 1000000, storage_cost: 2553600, storage_rebate: 2279772, non_refundable_storage_fee: 23028 -task 9, line 111: +task 9, line 109: //# create-checkpoint Checkpoint created: 3 -task 10, lines 113-139: +task 10, lines 111-137: //# run-graphql Response: { "data": { @@ -113,18 +113,18 @@ Response: { } } -task 11, line 141: +task 11, line 139: //# run Test::M1::unwrap --sender A --args object(8,0) mutated: object(0,0) unwrapped: object(2,0) deleted: object(8,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 2528064, non_refundable_storage_fee: 25536 -task 12, line 143: +task 12, line 141: //# create-checkpoint Checkpoint created: 4 -task 13, lines 145-183: +task 13, lines 143-181: //# run-graphql Response: { "data": { @@ -160,17 +160,17 @@ Response: { } } -task 14, line 185: +task 14, line 183: //# run Test::M1::delete --sender A --args object(2,0) mutated: object(0,0) deleted: object(2,0) gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 2279772, non_refundable_storage_fee: 23028 -task 15, line 187: +task 15, line 185: //# create-checkpoint Checkpoint created: 5 -task 16, lines 189-215: +task 16, lines 187-213: //# run-graphql Response: { "data": { @@ -187,19 +187,83 @@ Response: { } } -task 17, line 217: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 5 -Objects snapshot updated to [0 to 5) +task 17, line 215: +//# run Test::M1::create --args 0 @A +created: object(17,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 18, line 219: +task 18, line 217: //# create-checkpoint Checkpoint created: 6 -task 19, lines 221-260: +task 19, line 219: +//# run Test::M1::create --args 0 @A +created: object(19,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 20, line 221: +//# create-checkpoint +Checkpoint created: 7 + +task 21, line 223: +//# run Test::M1::create --args 0 @A +created: object(21,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 22, line 225: +//# create-checkpoint +Checkpoint created: 8 + +task 23, line 227: +//# run Test::M1::create --args 0 @A +created: object(23,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 24, line 229: +//# create-checkpoint +Checkpoint created: 9 + +task 25, line 231: +//# run Test::M1::create --args 0 @A +created: object(25,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 26, line 233: +//# create-checkpoint +Checkpoint created: 10 + +task 27, line 235: +//# run Test::M1::create --args 0 @A +created: object(27,0) +mutated: object(0,1) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 28, line 237: +//# create-checkpoint +Checkpoint created: 11 + +task 30, line 241: +//# create-checkpoint +Checkpoint created: 12 + +task 31, lines 243-290: //# run-graphql Response: { "data": { - "object_within_available_range": { + "availableRange": { + "first": { + "sequenceNumber": 7 + }, + "last": { + "sequenceNumber": 12 + } + }, + "indexed_object": { "status": "INDEXED", "version": 6, "asMoveObject": { @@ -211,7 +275,7 @@ Response: { } } }, - "object_outside_available_range": { + "wrapped_or_deleted_object": { "status": "WRAPPED_OR_DELETED", "version": 5, "asMoveObject": null @@ -230,3 +294,26 @@ Response: { } } } + +task 32, lines 292-312: +//# run-graphql --cursors @{obj_1_0,6} +Response: { + "data": null, + "errors": [ + { + "message": "Requested data is outside the available range", + "locations": [ + { + "line": 11, + "column": 3 + } + ], + "path": [ + "objects" + ], + "extensions": { + "code": "BAD_USER_INPUT" + } + } + ] +} diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.move b/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.move index 4065ae9fccdf0..9bf96c0531cd7 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/object_at_version.move @@ -9,12 +9,10 @@ // 3 | 5 // 4 | 6 // 5 | 7 -// Verify that the object is returned in its WrappedOrDeleted or Historical state. Increment -// objects_snapshot to [0, 5). This coalesces objects in objects_snapshot to its verson at -// checkpoint 4. The object would only be visible at version 6 from objects_snapshot, and at version -// 7 from objects_history. +// Then have objects snapshot processor update `objects_snapshot` so that the available range is between checkpoints 7 and 11. +// The object should still be accessible through point lookups at all versions. -//# init --protocol-version 51 --addresses Test=0x0 --accounts A --simulator +//# init --protocol-version 51 --addresses Test=0x0 --accounts A --simulator --objects-snapshot-min-checkpoint-lag 5 //# publish module Test::M1 { @@ -214,14 +212,46 @@ module Test::M1 { } } -//# force-object-snapshot-catchup --start-cp 0 --end-cp 5 +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# run Test::M1::create --args 0 @A + +//# create-checkpoint + +//# advance-clock --duration-ns 1 //# create-checkpoint //# run-graphql # Querying objects by version doesn't require it to be in the snapshot table. { - object_within_available_range: object( + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } + indexed_object: object( address: "@{obj_2_0}" version: 6 ) { @@ -233,7 +263,7 @@ module Test::M1 { } } } - object_outside_available_range: object( + wrapped_or_deleted_object: object( address: "@{obj_2_0}" version: 5 ) { @@ -258,3 +288,25 @@ module Test::M1 { } } } + +//# run-graphql --cursors @{obj_1_0,6} +# But it would no longer be possible to try to paginate using a cursor that falls outside the available range +{ + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } + objects(after: "@{cursor_0}") { + nodes { + asMoveObject { + contents { + json + } + } + } + } +} diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.exp b/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.exp index b79c01ea4f6d8..55a3996f8c47e 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.exp @@ -1,4 +1,4 @@ -processed 24 tasks +processed 26 tasks init: A: object(0,0), B: object(0,1) @@ -509,15 +509,15 @@ task 18, line 221: //# create-checkpoint Checkpoint created: 5 -task 19, line 223: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 -Objects snapshot updated to [0 to 4) - task 20, line 225: //# create-checkpoint Checkpoint created: 6 -task 21, lines 227-242: +task 22, line 229: +//# create-checkpoint +Checkpoint created: 7 + +task 23, lines 231-255: //# run-graphql --cursors @{obj_6_0,2} Response: { "data": null, @@ -526,7 +526,7 @@ Response: { "message": "Requested data is outside the available range", "locations": [ { - "line": 2, + "line": 11, "column": 3 } ], @@ -540,7 +540,7 @@ Response: { ] } -task 22, lines 244-260: +task 24, lines 257-273: //# run-graphql Response: { "data": { @@ -601,7 +601,7 @@ Response: { } } -task 23, lines 262-288: +task 25, lines 275-301: //# run-graphql Response: { "data": { diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.move b/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.move index f17b1c04fc831..2bff6e3413b35 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/objects_pagination.move @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -//# init --protocol-version 51 --addresses Test=0x0 --accounts A B --simulator +//# init --protocol-version 51 --addresses Test=0x0 --accounts A B --simulator --objects-snapshot-min-checkpoint-lag 4 // cp | object_id | owner @@ -220,12 +220,25 @@ module Test::M1 { //# create-checkpoint -//# force-object-snapshot-catchup --start-cp 0 --end-cp 4 +//# advance-clock --duration-ns 1 + +//# create-checkpoint + +//# advance-clock --duration-ns 1 //# create-checkpoint //# run-graphql --cursors @{obj_6_0,2} +# This query will error due to requesting data outside of available range { + availableRange { + first { + sequenceNumber + } + last { + sequenceNumber + } + } before_obj_6_0_at_checkpoint_2: objects(filter: {type: "@{Test}"}, before: "@{cursor_0}") { nodes { version diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.exp b/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.exp index 211357e662262..e675f01e0812b 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.exp +++ b/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.exp @@ -1,4 +1,4 @@ -processed 17 tasks +processed 16 tasks init: A: object(0,0), B: object(0,1) @@ -890,14 +890,10 @@ Response: { } task 12, line 182: -//# force-object-snapshot-catchup --start-cp 0 --end-cp 3 -Objects snapshot updated to [0 to 3) - -task 13, line 184: //# create-checkpoint Checkpoint created: 5 -task 14, lines 186-260: +task 13, lines 184-258: //# run-graphql Response: { "data": { @@ -1223,11 +1219,11 @@ Response: { } } -task 15, line 262: +task 14, line 260: //# create-checkpoint Checkpoint created: 6 -task 16, lines 264-299: +task 15, lines 262-295: //# run-graphql Response: { "data": { diff --git a/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.move b/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.move index bca9988aa2af6..4f7bf42061ed0 100644 --- a/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.move +++ b/crates/sui-graphql-e2e-tests/tests/consistency/tx_address_objects.move @@ -179,8 +179,6 @@ module Test::M1 { } } -//# force-object-snapshot-catchup --start-cp 0 --end-cp 3 - //# create-checkpoint //# run-graphql @@ -262,9 +260,7 @@ module Test::M1 { //# create-checkpoint //# run-graphql -# First transaction should have no results since its data is no longer in objects_snapshot. Second -# transaction is still valid - since objects_snapshot table is at [0, 3), it will have data from -# checkpoint 2. +# Regardless of the transaction block, the nested fields should yield the same data. { all_transactions: transactionBlocks(first: 4, filter: {signAddress: "@{A}"}) { nodes { diff --git a/crates/sui-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-graphql-rpc/src/test_infra/cluster.rs index d1d8ee85cac4c..a986c000c6393 100644 --- a/crates/sui-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-graphql-rpc/src/test_infra/cluster.rs @@ -468,7 +468,7 @@ impl ExecutorCluster { .unwrap(); tokio::time::timeout(base_timeout, async { - while latest_cp > latest_snapshot_cp + self.snapshot_config.snapshot_max_lag as u64 { + while latest_cp > latest_snapshot_cp + self.snapshot_config.snapshot_min_lag as u64 { tokio::time::sleep(Duration::from_secs(1)).await; latest_snapshot_cp = self .indexer_store @@ -489,35 +489,4 @@ impl ExecutorCluster { self.cancellation_token.cancel(); let _ = join!(self.graphql_server_join_handle, self.indexer_join_handle); } - - pub async fn force_objects_snapshot_catchup(&self, start_cp: u64, end_cp: u64) { - self.indexer_store - .update_objects_snapshot(start_cp, end_cp) - .await - .unwrap(); - - let mut latest_snapshot_cp = self - .indexer_store - .get_latest_object_snapshot_checkpoint_sequence_number() - .await - .unwrap() - .unwrap_or_default(); - - tokio::time::timeout(Duration::from_secs(60), async { - while latest_snapshot_cp < end_cp - 1 { - tokio::time::sleep(Duration::from_secs(1)).await; - latest_snapshot_cp = self - .indexer_store - .get_latest_object_snapshot_checkpoint_sequence_number() - .await - .unwrap() - .unwrap_or_default(); - } - }) - .await - .unwrap_or_else(|_| panic!("Timeout waiting for indexer to update objects snapshot - latest_snapshot_cp: {}, end_cp: {}", - latest_snapshot_cp, end_cp)); - - tokio::time::sleep(Duration::from_secs(5)).await; - } } diff --git a/crates/sui-graphql-rpc/src/types/available_range.rs b/crates/sui-graphql-rpc/src/types/available_range.rs index 3c0b980e64040..ba879e6bbc0c7 100644 --- a/crates/sui-graphql-rpc/src/types/available_range.rs +++ b/crates/sui-graphql-rpc/src/types/available_range.rs @@ -69,7 +69,8 @@ impl AvailableRange { .order(snapshots::checkpoint_sequence_number.desc()) .limit(1); - lhs.union(rhs) + // We need to use `union_all` in case `lhs` and `rhs` have the same value. + lhs.union_all(rhs) })?; let (first, mut last) = match checkpoint_range.as_slice() { diff --git a/crates/sui-indexer/src/config.rs b/crates/sui-indexer/src/config.rs index 477ad9a0f87eb..1f8372ca87531 100644 --- a/crates/sui-indexer/src/config.rs +++ b/crates/sui-indexer/src/config.rs @@ -169,19 +169,12 @@ pub struct PruningOptions { #[derive(Args, Debug, Clone)] pub struct SnapshotLagConfig { #[arg( - long = "object-snapshot-min-checkpoint-lag", + long = "objects-snapshot-min-checkpoint-lag", default_value_t = Self::DEFAULT_MIN_LAG, env = "OBJECTS_SNAPSHOT_MIN_CHECKPOINT_LAG", )] pub snapshot_min_lag: usize, - #[arg( - long = "object-snapshot-max-checkpoint-lag", - default_value_t = Self::DEFAULT_MAX_LAG, - env = "OBJECTS_SNAPSHOT_MAX_CHECKPOINT_LAG", - )] - pub snapshot_max_lag: usize, - #[arg( long = "objects-snapshot-sleep-duration", default_value_t = Self::DEFAULT_SLEEP_DURATION_SEC, @@ -190,7 +183,6 @@ pub struct SnapshotLagConfig { } impl SnapshotLagConfig { - const DEFAULT_MAX_LAG: usize = 900; const DEFAULT_MIN_LAG: usize = 300; const DEFAULT_SLEEP_DURATION_SEC: u64 = 5; } @@ -198,8 +190,7 @@ impl SnapshotLagConfig { impl Default for SnapshotLagConfig { fn default() -> Self { SnapshotLagConfig { - snapshot_min_lag: Self::DEFAULT_MAX_LAG, - snapshot_max_lag: Self::DEFAULT_MIN_LAG, + snapshot_min_lag: Self::DEFAULT_MIN_LAG, sleep_duration: Self::DEFAULT_SLEEP_DURATION_SEC, } } diff --git a/crates/sui-indexer/src/handlers/objects_snapshot_processor.rs b/crates/sui-indexer/src/handlers/objects_snapshot_processor.rs index afb1cd93b3caf..daeb249bba276 100644 --- a/crates/sui-indexer/src/handlers/objects_snapshot_processor.rs +++ b/crates/sui-indexer/src/handlers/objects_snapshot_processor.rs @@ -19,6 +19,7 @@ use crate::store::package_resolver::{IndexerStorePackageResolver, InterimPackage use crate::store::PgIndexerStore; use crate::types::IndexerResult; use crate::{metrics::IndexerMetrics, store::IndexerStore}; +use std::collections::HashMap; use std::sync::{Arc, Mutex}; use super::checkpoint_handler::CheckpointHandler; @@ -163,6 +164,10 @@ impl ObjectsSnapshotProcessor { .ready_chunks(batch_size); let mut start_cp = watermark; + // To prevent the processor from committing more data than allowed by the min lag, keep an + // in-memory buffer of changes that should not be committed to `objects_snapshot` yet. + let mut unprocessed = HashMap::new(); + let mut batch = vec![]; info!("Starting objects snapshot committer..."); loop { @@ -177,21 +182,51 @@ impl ObjectsSnapshotProcessor { .await? .unwrap_or_default(); - // We update the snapshot table when it falls behind the rest of the indexer by more than the min_lag. + // We update the snapshot table when it falls behind the rest of the indexer by + // more than the min_lag. When `latest_indexer_cp = start_cp + + // config.snapshot_min_lag`, we have not actually indexed `start_cp` yet, hence + // why the condition is `>=`. while latest_indexer_cp >= start_cp + config.snapshot_min_lag as u64 { - // Stream the next object changes to be committed to the store. - if let Some(object_changes_batch) = stream.next().await { - let first_checkpoint_seq = object_changes_batch.first().as_ref().unwrap().checkpoint_sequence_number; - let last_checkpoint_seq = object_changes_batch.last().as_ref().unwrap().checkpoint_sequence_number; + // The maximum checkpoint sequence number that can be committed to the + // `objects_snapshot` table. + let max_allowed_cp = latest_indexer_cp - config.snapshot_min_lag as u64; + + // Fetch `batch_size` more data from the stream if the buffer is empty and + // we still need to catch up. + if unprocessed.is_empty() { + if let Some(new_changes) = stream.next().await { + for checkpoint in new_changes { + unprocessed.insert(checkpoint.checkpoint_sequence_number, checkpoint); + } + } + } + + // Collect the checkpoint object changes to write to `objects_snapshot`, + // stopping when there are gaps in the sequence of unprocessed checkpoints. + // This is an inclusive range, so if `start_cp` is equal to + // `max_allowed_cp`, we'll still index the one checkpoint. + for cp in start_cp..=max_allowed_cp { + if let Some(checkpoint) = unprocessed.remove(&cp) { + batch.push(checkpoint); + } + else { + break; + } + } + + if !batch.is_empty() { + let first_checkpoint_seq = batch.first().as_ref().unwrap().checkpoint_sequence_number; + let last_checkpoint_seq = batch.last().as_ref().unwrap().checkpoint_sequence_number; info!("Objects snapshot processor is updating objects snapshot table from {} to {}", first_checkpoint_seq, last_checkpoint_seq); - let changes_to_commit = object_changes_batch.into_iter().map(|obj| obj.object_changes).collect(); - store.backfill_objects_snapshot(changes_to_commit) + + store.backfill_objects_snapshot(batch.drain(..).map(|obj| obj.object_changes).collect()) .await .unwrap_or_else(|_| panic!("Failed to backfill objects snapshot from {} to {}", first_checkpoint_seq, last_checkpoint_seq)); start_cp = last_checkpoint_seq + 1; - // Tells the package buffer that this checkpoint has been processed and the corresponding package data can be deleted. + // Tells the package buffer that this checkpoint has been processed and + // the corresponding package data can be deleted. commit_notifier.send(Some(last_checkpoint_seq)).expect("Commit watcher should not be closed"); metrics .latest_object_snapshot_sequence_number diff --git a/crates/sui-transactional-test-runner/src/args.rs b/crates/sui-transactional-test-runner/src/args.rs index fb5ffb929b9d6..7203b48f5bd39 100644 --- a/crates/sui-transactional-test-runner/src/args.rs +++ b/crates/sui-transactional-test-runner/src/args.rs @@ -172,14 +172,6 @@ pub struct RunGraphqlCommand { pub wait_for_checkpoint_pruned: Option, } -#[derive(Debug, clap::Parser)] -pub struct ForceObjectSnapshotCatchup { - #[clap(long = "start-cp")] - pub start_cp: u64, - #[clap(long = "end-cp")] - pub end_cp: u64, -} - #[derive(Debug, clap::Parser)] pub struct CreateCheckpointCommand { pub count: Option, @@ -217,7 +209,6 @@ pub enum SuiSubcommand { SetRandomState(SetRandomStateCommand), ViewCheckpoint, RunGraphql(RunGraphqlCommand), - ForceObjectSnapshotCatchup(ForceObjectSnapshotCatchup), Bench(RunCommand, ExtraRunArgs), } @@ -263,11 +254,6 @@ impl clap::FromArgMatches Some(("run-graphql", matches)) => { SuiSubcommand::RunGraphql(RunGraphqlCommand::from_arg_matches(matches)?) } - Some(("force-object-snapshot-catchup", matches)) => { - SuiSubcommand::ForceObjectSnapshotCatchup( - ForceObjectSnapshotCatchup::from_arg_matches(matches)?, - ) - } Some(("bench", matches)) => SuiSubcommand::Bench( RunCommand::from_arg_matches(matches)?, ExtraRunArgs::from_arg_matches(matches)?, @@ -305,7 +291,6 @@ impl clap::CommandFactory .subcommand(SetRandomStateCommand::command().name("set-random-state")) .subcommand(clap::Command::new("view-checkpoint")) .subcommand(RunGraphqlCommand::command().name("run-graphql")) - .subcommand(ForceObjectSnapshotCatchup::command().name("force-object-snapshot-catchup")) .subcommand( RunCommand::::augment_args(ExtraRunArgs::command()).name("bench"), ) diff --git a/crates/sui-transactional-test-runner/src/test_adapter.rs b/crates/sui-transactional-test-runner/src/test_adapter.rs index 0137e16d29fab..85de6cf99fc62 100644 --- a/crates/sui-transactional-test-runner/src/test_adapter.rs +++ b/crates/sui-transactional-test-runner/src/test_adapter.rs @@ -562,30 +562,6 @@ impl<'a> MoveTestAdapter<'a> for SuiTestAdapter { }}; } match command { - SuiSubcommand::ForceObjectSnapshotCatchup(ForceObjectSnapshotCatchup { - start_cp, - end_cp, - }) => { - let cluster = self.cluster.as_ref().unwrap(); - let highest_checkpoint = self.executor.get_latest_checkpoint_sequence_number()?; - - if end_cp > highest_checkpoint { - bail!( - "end_cp {} is greater than highest checkpoint {}", - end_cp, - highest_checkpoint, - ); - } - - cluster - .force_objects_snapshot_catchup(start_cp, end_cp) - .await; - - Ok(Some(format!( - "Objects snapshot updated to [{} to {})", - start_cp, end_cp - ))) - } SuiSubcommand::RunGraphql(RunGraphqlCommand { show_usage, show_headers,