Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit 5ac661e

Browse files
committed
add steps page
1 parent 34dc2f6 commit 5ac661e

File tree

5 files changed

+138
-9
lines changed

5 files changed

+138
-9
lines changed

apps/nextra/next.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ export default withBundleAnalyzer(
407407
destination: "/en/build/indexer/indexer-sdk/documentation/setup",
408408
permanent: true,
409409
},
410+
{
411+
source: "/indexer/indexer-sdk/documentation/steps",
412+
destination: "/en/build/indexer/indexer-sdk/documentation/steps",
413+
permanent: true,
414+
},
410415
{
411416
source: "/indexer/indexer-sdk/documentation/parsing-txns",
412417
destination: "/en/build/indexer/indexer-sdk/documentation/parsing-txns",

apps/nextra/pages/en/build/indexer/indexer-sdk/documentation/_meta.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export default {
22
setup: { title: "Initial Setup" },
3+
"steps": {
4+
title: "Creating a Step",
5+
},
36
"parsing-txns": {
47
title: "Parsing Transactions",
58
},

apps/nextra/pages/en/build/indexer/indexer-sdk/documentation/setup.mdx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
---
22
title: "Initial Setup"
33
---
4-
import { Callout } from 'nextra/components'
5-
import { IndexerBetaNotice } from '@components/index';
64

75
# Initial Setup
86

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
title: "Creating a Step"
3+
---
4+
5+
# Creating a Step
6+
7+
## What is a step?
8+
A step is a unit of processing lgoic in the SDK. It can be used to extract, transform, or store data. Steps are the building blocks of a processor.
9+
10+
There are two types of steps in the SDK:
11+
1. **AsyncStep**: Processes a batch of input items and returns a batch of output items.
12+
2. **PollableAsyncStep**: Does the same as `AsyncStep`, but it also periodically polls its internal state and returns a batch of output items if available.
13+
14+
## How to create a Step
15+
To create a step with the SDK, follow these instructions:
16+
17+
1. Implement the `Processable` trait. This trait defines several important details about the step: the input and output types, the processing logic, and the run type (either `AsyncStepRunType` or `PollableAsyncStepRunType`).
18+
19+
```rust
20+
#[async_trait]
21+
impl Processable for MyExtractorStep {
22+
// The Input is a batch of Transaction
23+
type Input = Transaction;
24+
// The Output is a batch of MyData
25+
type Output = MyData;
26+
27+
// Depending on the type of step this is, the RunType is either
28+
// - AsyncRunType
29+
// - PollableAsyncRunType
30+
type RunType = AsyncRunType;
31+
32+
// Processes a batch of input items and returns a batch of output items.
33+
async fn process(
34+
&mut self,
35+
input: TransactionContext<Transaction>,
36+
) -> Result<Option<TransactionContext<MyData>>, ProcessorError> {
37+
let transactions = input.data;
38+
let data = transactions.iter().map(|transaction| {
39+
// Define the processing logic to extract MyData from a Transaction
40+
}).collect();
41+
42+
Ok(Some(TransactionContext {
43+
data,
44+
metadata: input.metadata,
45+
}))
46+
}
47+
}
48+
```
49+
50+
In the example code above, you'll notice that the input and output types are wrapped within a `TransactionContext`.
51+
`TransactionContext` contains relevant metadata about the batch of data being processed, such as the transaction versions and timestamp, and are used for metrics and logging.
52+
53+
2. Implement the `NamedStep` trait. This is used for logging.
54+
55+
```rust
56+
impl NamedStep for MyExtractorStep {
57+
fn name(&self) -> String {
58+
"MyExtractorStep".to_string()
59+
}
60+
}
61+
```
62+
63+
3. Implement either `AsyncStep` trait or `PollableAsyncStep` trait, which defines how the step will be run in the processor.
64+
1. If you're using `AsyncStep`, add this to your code:
65+
66+
```rust
67+
impl AsyncStep for MyExtractorStep {}
68+
```
69+
70+
2. If you're creating a `PollableAsyncStep`, you will need to define the poll interval and what the step should do every time it polls.
71+
72+
```rust
73+
#[async_trait]
74+
impl<T: Send + 'static> PollableAsyncStep for MyPollStep<T>
75+
where
76+
Self: Sized + Send + Sync + 'static,
77+
T: Send + 'static,
78+
{
79+
fn poll_interval(&self) -> std::time::Duration {
80+
// Define duration
81+
}
82+
83+
async fn poll(&mut self) -> Result<Option<Vec<TransactionContext<T>>>, ProcessorError> {
84+
// Define code here on what this step should do every time it polls
85+
// Optionally return a batch of output items
86+
}
87+
}
88+
```
89+
90+
## How to connect step's
91+
92+
Now that you have created a step, you can connect it to other steps in the processor.
93+
`ProcessorBuilder` is used to connect a graph of steps to construct a processor.
94+
It uses trait bounds to ensure that the output type of each step matches the input type of its connected step.
95+
96+
### How to use `ProcessorBuilder`
97+
98+
1. Initialize the processor with the first step using `ProcessorBuilder::new_with_inputless_first_step`.
99+
2. Connect the next step using `.connect_to(second_step.into_runnable_step(), channel_size)`.
100+
- `.into_runnable_step()` converts your step into a `RunnableStep`, which enables it to store the step's input and output channels and allows the step to be spawned in a task.
101+
- When you use `.connect_to`, a channel gets created with size `channel_size` and connected to the previous and current steps, and the previous step is spawned in a task.
102+
3. To close off the `ProcessorBuilder`, use `.end_and_return_output_receiver(channel_size)`. This returns a channel receiver that can be used to receive the final output of the processor.
103+
104+
### Example
105+
```rust
106+
let (pb, buffer_receiver) = ProcessorBuilder::new_with_inputless_first_step(
107+
first_step.into_runnable_step(),
108+
)
109+
.connect_to(second_step.into_runnable_step(), channel_size)
110+
.connect_to(third_step.into_runnable_step(), channel_size)
111+
.end_and_return_output_receiver(channel_size);
112+
```
113+
114+
## Common steps
115+
116+
The SDK provides several common steps that you can use in your processor.
117+
118+
1. `TransactionStreamStep` provides a stream of Aptos transactions to the processor
119+
2. `TimedBufferStep` buffers a batch of items and periodically polls to release the items to the next step
120+
121+
{/* <!-- Add the rest of the common SDK steps --> */}

apps/nextra/pages/en/build/indexer/indexer-sdk/quickstart.mdx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Quickstart Guide on Aptos Indexer SDK
2-
In this guide, we’re going to walk you through all the steps involved with creating a basic events processor in Rust to
3-
track events on the Aptos blockchain. At the end of this guide, you’ll be able to run a simple events processor and customize
4-
the processor for your indexing needs.
52

6-
# Getting started
3+
## What to expect from this guide
4+
This guide will walk you through setting up and running a Rust processor to index events on the Aptos blockchain into PostgreSQL.
5+
We provide a template processor that you can customize to index events from your custom contracts.
6+
By the end of the guide, you should have a basic understanding of how a processor works and be able to customize the processor for your indexing needs.
7+
8+
## Getting started
79

810
To get started, clone
911
the [aptos-indexer-processors-example](https://github.com/aptos-labs/aptos-indexer-processor-example/tree/main) repo.
@@ -48,7 +50,7 @@ towards PostgreSQL for the sake of simplicity. We use the following database con
4850
Explaining how to create a database is beyond the scope of this tutorial. If you are not sure how to do it, consider
4951
checking out tutorials on how to create a database with the `psql` tool.
5052

51-
# Setting up your environment
53+
## Setting up your environment
5254

5355
Make sure to start the `postgresql` service:
5456

@@ -64,7 +66,7 @@ For mac, if you’re using brew, start it up with:
6466
brew services start postgresql
6567
```
6668

67-
# **Configuring your processor**
69+
## **Configuring your processor**
6870

6971
Now let’s set up the configuration details for the actual indexer processor we’re going to use.
7072

@@ -122,7 +124,7 @@ indexer_grpc_data_service_address: grpc.testnet.aptoslabs.com:443
122124
indexer_grpc_data_service_address: grpc.mainnet.aptoslabs.com:443
123125
```
124126

125-
# Explanation of the processor
127+
## Explanation of the processor
126128

127129
At a high level, each processor is responsible for receiving a stream of transactions, parsing and transforming the
128130
relevant data, and storing the data into a database.

0 commit comments

Comments
 (0)