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

Improve docs related to storage #150

Merged
merged 4 commits into from
Nov 11, 2024
Merged
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
2 changes: 0 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@

- [Advanced Topics](developers/advanced_topics.md)

- [Views](developers/advanced_topics/views.md)
- [Persistent Storage](developers/advanced_topics/persistent_storage.md)
- [Contract Finalization](developers/advanced_topics/contract_finalize.md)
- [Validators](developers/advanced_topics/validators.md)
- [Creating New Blocks](developers/advanced_topics/block_creation.md)
Expand Down
2 changes: 1 addition & 1 deletion src/developers/advanced_topics/contract_finalize.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl Contract for MyContract {
type Parameters = ();

async fn load(runtime: ContractRuntime<Self>) -> Self {
let state = MyState::load(ViewStorageContext::from(runtime.key_value_store()))
let state = MyState::load(runtime.root_view_storage_context())
.await
.expect("Failed to load state");

Expand Down
58 changes: 0 additions & 58 deletions src/developers/advanced_topics/persistent_storage.md

This file was deleted.

26 changes: 0 additions & 26 deletions src/developers/advanced_topics/views.md

This file was deleted.

2 changes: 1 addition & 1 deletion src/developers/sdk/contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ instance:

```rust,ignore
async fn load(runtime: ContractRuntime<Self>) -> Self {
let state = Counter::load(ViewStorageContext::from(runtime.key_value_store()))
let state = Counter::load(runtime.root_view_storage_context())
.await
.expect("Failed to load state");
CounterContract { state, runtime }
Expand Down
2 changes: 1 addition & 1 deletion src/developers/sdk/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ it to load the application state:

```rust,ignore
async fn load(runtime: ServiceRuntime<Self>) -> Self {
let state = Counter::load(ViewStorageContext::from(runtime.key_value_store()))
let state = Counter::load(runtime.root_view_storage_context())
.await
.expect("Failed to load state");
Ok(CounterService { state })
Expand Down
56 changes: 32 additions & 24 deletions src/developers/sdk/state.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
# Creating the Application State

The `struct` which defines your application's state can be found in
`src/state.rs`. An application state is the data that is persisted on storage
The state of a Linera application consists of onchain data that are persisted
between transactions.

To represent our counter, we're going to need a single `u64`. To persist the
counter we'll be using Linera's [view](../advanced_topics/views.md) paradigm.

Views are a little like an
[ORM](https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping), however
instead of mapping data structures to a relational database like Postgres, they
are instead mapped onto key-value stores like [RocksDB](https://rocksdb.org/).
The `struct` which defines your application's state can be found in
`src/state.rs`. To represent our counter, we're going to use a `u64` integer.

In vanilla Rust, we might represent our Counter as so:
While we could use a plain data-structure for the entire application state:

```rust,ignore
// do not use this
struct Counter {
value: u64
}
```

However, to persist your data, you'll need to replace the existing `Application`
state struct in `src/state.rs` with the following view:
in general, we prefer to manage persistent data using the concept of "views":

> [Views](https://docs.rs/linera-views/latest/linera_views/) allow an
> application to load persistent data in memory and stage modifications in a
> flexible way.
>
> Views resemble the persistent objects of an
> [ORM](https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping)
> framework, except that they are stored as a set of key-value pairs (instead of
> a SQL row).

In this case, the placeholder `Application` struct in `src/state.rs` should be
replaced by

```rust,ignore
/// The application state.
#[derive(RootView, async_graphql::SimpleObject)]
#[view(context = "ViewStorageContext")]
pub struct Counter {
pub value: RegisterView<u64>,
// Additional fields here will get their own key in storage.
}
```

and all other occurrences of `Application` in your app.
and the occurrences of `Application` in the rest of the project should be
replaced by `Counter`.

The `RegisterView<T>` supports modifying a single value of type `T`. There are
different types of views for different use-cases, but the majority of common
data structures have already been implemented:
The derive macro `async_graphql::SimpleObject` is related to GraphQL queries
discussed in the [next section](service.md).

- A `Vec` or `VecDeque` corresponds to a `LogView`
- A `BTreeMap` corresponds to a `MapView` if its values are primitive, or to
`CollectionView` if its values are other views;
- A `Queue` corresponds to a `QueueView`
A `RegisterView<T>` supports modifying a single value of type `T`. Other data
structures available in the library
[`linera_views`](https://docs.rs/linera-views/latest/linera_views/) include:

For an exhaustive list refer to the Views
[documentation](../advanced_topics/views.md).
- `LogView` for a growing vector of values;
- `QueueView` for queues;
- `MapView` and `CollectionView` for associative maps; specifically, `MapView`
in the case of static values, and `CollectionView` when values are other
views.

Finally, run `cargo check` to ensure that your changes compile.
For an exhaustive list of the different constructions, refer to the crate
[documentation](https://docs.rs/linera-views/latest/linera_views/).
2 changes: 1 addition & 1 deletion src/developers/sdk/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod tests {
// Check that the state in memory is different from the state in storage
assert_ne!(
contract.state,
ApplicationState::load(ViewStorageContext::from(runtime.key_value_store()))
ApplicationState::load(runtime.root_view_storage_context())
);
}
}
Expand Down
Loading