Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GraphQL/TransactionBlock] Scan Limits #18413

Merged
merged 7 commits into from
Aug 22, 2024
Merged

Conversation

wlmyng
Copy link
Contributor

@wlmyng wlmyng commented Jun 25, 2024

Description

Implement learnings from GraphQL performance benchmarks:

  • Implement transaction block pagination as a two step process: First fetch the relevant transaction sequence numbers, then fetch their contents.
  • Every "atomic" filter on transaction blocks is served by a single tx_ table, with two indices on it, both of which are prepped to perform index-only scans.
    • The primary index is used to apply the filter directly.
    • The secondary index applies the filter after limiting results to one sender.
  • Compound filters are served by joining multiple atomic filters together.
  • The "scan limit" concept is introduced to limit the amount of work done when dealing with compound filters (see below).

Scan Limits

  • If a filter is compound, a scan limit must be provided, and controls how many transactions are considered as candidates when building a page of results.
  • There is an upperbound on the scan limit, currently 100M, which is enough for over a week of transactions at 100TPS.
  • When scan limits are enabled, pagination behaviour changes: Pages can be returned with fewer results than the page size (including no results), but still have a previous or next page, because there were no valid candidates in the area scanned but there is more room to scan on either side.
  • The start and end cursor for the page may no longer point to an element in the results, because they point to the first and last candidate transaction.

Test plan

sui$ cargo build -p sui-indexer
sui$ cargo nextest run -p sui-graphql-rpc
sui$ cargo nextest run -p sui-graphql-e2e-tests --features pg_integration

Release notes

Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.

For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates.

  • Protocol:
  • Nodes (Validators and Full nodes):
  • Indexer:
  • JSON-RPC:
  • GraphQL: Introduce scanLimit for paginating TransactionBlocks. Queries that include multiple complex filters (filters on the function called, affected objects, recipient), need to include a scan limit that controls the number of transactions that are looked at as candidates.
  • CLI:
  • Rust SDK:

Copy link

vercel bot commented Jun 25, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sui-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 22, 2024 10:35am
3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Aug 22, 2024 10:35am
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Aug 22, 2024 10:35am
sui-typescript-docs ⬜️ Ignored (Inspect) Visit Preview Aug 22, 2024 10:35am

Copy link
Contributor

@amnn amnn left a comment

Choose a reason for hiding this comment

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

Initial round of comments -- main thing to watch out for is the fact that it looks like in this implementation the scan limit is given in terms of checkpoints, when it should be in terms of transactions.

crates/sui-graphql-rpc/src/data/pg.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/lib.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/tx_lookups.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/tx_lookups.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/tx_lookups.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/tx_lookups.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/lib.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@amnn amnn left a comment

Choose a reason for hiding this comment

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

Quick scan through to get caught up before our pairing session today!

crates/sui-graphql-rpc/src/raw_query.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/address.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/checkpoint.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/object.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@amnn amnn left a comment

Choose a reason for hiding this comment

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

We got there, congrats @wlmyng :)

Mostly small nits left about docs etc, but there is one important detail to correct about avoiding underflow/overflow.

Let's also hold off on landing this until we get the green light from @gegaowp that the breaking changes pick is safe to build on top of.

Well done, again 🎉

crates/sui-graphql-rpc/src/config.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block/mod.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block/mod.rs Outdated Show resolved Hide resolved
crates/sui-graphql-rpc/src/types/transaction_block/mod.rs Outdated Show resolved Hide resolved
wlmyng and others added 2 commits August 20, 2024 22:18
comments elucidating why we check the transaction's first or last cursor against the scan limited cursor of the current page

do the same for the backwards pagination case

when a cursor is specified, bump scan_limit by one so we don't count it among the txs scanned. otherwise we'll be short one
There was a bug related to bounds for the first page, when it contains
the genesis checkpoint. This was fixed by refactoring `TxBounds` to
systematically use a half-open interval (inclusive lowerbounds and
exclusive upperbounds) when calculating and combining intervals to be
used on the DB, regardless of where the bounds came from and whether
they were inclusive or exclusive at source.

Also added a new test to exercise this behaviour -- all existing tests
also pass, unchanged.
@amnn amnn changed the title [gql] transactions queries uses scan limit approach from benchmarking [GraphQL/TransactionBlock] Scan Limits Aug 22, 2024
@amnn amnn self-assigned this Aug 22, 2024
@amnn amnn merged commit f746620 into main Aug 22, 2024
48 checks passed
@amnn amnn deleted the wlmyng/gql/scan-limit-tx-approach branch August 22, 2024 12:28
tx-tomcat pushed a commit to tx-tomcat/sui-network that referenced this pull request Aug 27, 2024
## Description 

Implement learnings from GraphQL performance benchmarks:

- Implement transaction block pagination as a two step process: First fetch the relevant transaction sequence numbers, then fetch their contents.
- Every "atomic" filter on transaction blocks is served by a single `tx_` table, with two indices on it, both of which are prepped to perform index-only scans.
  - The primary index is used to apply the filter directly.
  - The secondary index applies the filter after limiting results to one sender.
- Compound filters are served by joining multiple atomic filters together.
- The "scan limit" concept is introduced to limit the amount of work done when dealing with compound filters (see below).

### Scan Limits

- If a filter is compound, a scan limit must be provided, and controls how many transactions are considered as candidates when building a page of results.
- There is an upperbound on the scan limit, currently 100M, which is enough for over a week of transactions at 100TPS.
- When scan limits are enabled, pagination behaviour changes: Pages can be returned with fewer results than the page size (including no results), but still have a previous or next page, because there were no valid candidates in the area scanned but there is more room to scan on either side.
- The start and end cursor for the page may no longer point to an element in the results, because they point to the first and last candidate transaction.

## Test plan 

```
sui$ cargo build -p sui-indexer
sui$ cargo nextest run -p sui-graphql-rpc
sui$ cargo nextest run -p sui-graphql-e2e-tests --features pg_integration
```

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.

For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. 

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [x] GraphQL: Introduce `scanLimit` for paginating `TransactionBlocks`. Queries that include multiple complex filters (filters on the function called, affected objects, recipient), need to include a scan limit which controls the number of transactions that are looked at as candidates.
- [ ] CLI: 
- [ ] Rust SDK: 


---------

Co-authored-by: Ashok Menon <[email protected]>
suiwombat pushed a commit that referenced this pull request Sep 16, 2024
## Description 

Implement learnings from GraphQL performance benchmarks:

- Implement transaction block pagination as a two step process: First fetch the relevant transaction sequence numbers, then fetch their contents.
- Every "atomic" filter on transaction blocks is served by a single `tx_` table, with two indices on it, both of which are prepped to perform index-only scans.
  - The primary index is used to apply the filter directly.
  - The secondary index applies the filter after limiting results to one sender.
- Compound filters are served by joining multiple atomic filters together.
- The "scan limit" concept is introduced to limit the amount of work done when dealing with compound filters (see below).

### Scan Limits

- If a filter is compound, a scan limit must be provided, and controls how many transactions are considered as candidates when building a page of results.
- There is an upperbound on the scan limit, currently 100M, which is enough for over a week of transactions at 100TPS.
- When scan limits are enabled, pagination behaviour changes: Pages can be returned with fewer results than the page size (including no results), but still have a previous or next page, because there were no valid candidates in the area scanned but there is more room to scan on either side.
- The start and end cursor for the page may no longer point to an element in the results, because they point to the first and last candidate transaction.

## Test plan 

```
sui$ cargo build -p sui-indexer
sui$ cargo nextest run -p sui-graphql-rpc
sui$ cargo nextest run -p sui-graphql-e2e-tests --features pg_integration
```

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.

For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. 

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [x] GraphQL: Introduce `scanLimit` for paginating `TransactionBlocks`. Queries that include multiple complex filters (filters on the function called, affected objects, recipient), need to include a scan limit which controls the number of transactions that are looked at as candidates.
- [ ] CLI: 
- [ ] Rust SDK: 


---------

Co-authored-by: Ashok Menon <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants