Skip to content

Commit

Permalink
0.8.0 High-level update (#79)
Browse files Browse the repository at this point in the history
* feat: NEAR Lake Helper (high-level Lake Framework) (#51)

* feat: NEAR Lake Helper (high-level Lake Framework)

* cover all top-level primitives

* Update changelog

* Add getters to fields in primitives, update the required function, change Event structure

* chore: Closes #61: Changes made to the lib should be picked to 0.8.0

* fix(tests): Resolved #60: Fix failing doc tests (#66)

* fix(tests): Resolved #60: Fix failing doc tests

* fix: add proper code annotations where possible

* feat(primitives): Add support for DelegateAction (NEP-366) + LEP-002 (Focus on action and Events) (#67)

* feat(primitives): Add support for DelegateAction (NEP-336)

* Refactor the structures completely (LEP-002)

* (examples) Address review suggestions

* remove refactoring commented leftovers

* (primitives) Address review suggestion, optimize the structure, do some renaming

* Return iterators from methods instead of clone, improve return types, handle tx actions

* add todo for later to create dedicated structures for possible errors of Failure ExecutionStatus

* DelegateAction struct, split receipts file

* remove commented code

* expose delegate_actions mod

* feat: Expose concurrency parameter to the Lake structure (and builder) (#69)

* feat: LEP-001 Introduce Lake Context (#68)

* feat: Implement LEP-001 (Context)

* clean up Lake impl to reuse code

* Update docstrings

* refactor: Resolves #42 replace anyhow with LakeError enum (thiserror) (#70)

* fix: typo in README

* fix: CHANGELOG typos and bring back the concurrency usage lost during merging

* feat: ParentTransactionCache context and example (#74)

* feat: ParentTransactionCache context and example

* Update README for ParentTransactionCache about advanced usage

* refactor: Add LakeContext derive and introduce a concept of LakeContext with calls before and after user function

* Update lake-parent-transaction-cache/README.md

Co-authored-by: Morgan McCauley <morgan@mccauley.co.nz>

* address review suggestion rename field accounts_id -> account_ids

* add comments to the example, add READMEs, drop accidental artifact

* Update documentation, add docs about the LakeContext

* Add ParentTransactionCache to the Lake Framework README

* refactor Lake::run method to drop code duplication

---------

Co-authored-by: Morgan McCauley <morgan@mccauley.co.nz>

* docs: Lake Primitives documentation added (#75)

* feat: ParentTransactionCache context and example

* Update documentation, add docs about the LakeContext

* docs: Lake Primitives documentation added

* chore: Upgrade near primitives to 0.17.0 version (#77)

* chore: Prepare 0.8.0-beta.1 release (#78)

* chore: Prepare 0.8.0-beta.1 release

* Change to use CUSTOM_GITHUB_TOKEN and add a link to the workflow for the reasoning

* Setup versioning and add release-plz.toml

* Drop the release-plz job limitation on the CI job

* Add missing versions to the changelog

* Add 0.7.x branch to the CI

---------

Co-authored-by: Morgan McCauley <morgan@mccauley.co.nz>
  • Loading branch information
khorolets and morgsmccauley authored Jun 6, 2023
1 parent fb662d6 commit 67fede7
Show file tree
Hide file tree
Showing 38 changed files with 4,379 additions and 269 deletions.
107 changes: 24 additions & 83 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ name: Rust

on:
push:
branches: [ main ]
branches:
- main
- 0.7.x # we're going to maintain 0.7.x version until the adoption of 0.8.x will be completed
pull_request:
branches: [ main ]
branches:
- main
- 0.7.x # we're going to maintain 0.7.x version until the adoption of 0.8.x will be completed

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -53,85 +57,22 @@ jobs:
run: |
cargo clippy
test:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
components: clippy
- name: Run tests
run: |
cargo test
publish:
runs-on: ubuntu-20.04
needs: [rustfmt, rustclippy]
if: github.ref == 'refs/heads/main'

release-plz:
name: release-plz
runs-on: ubuntu-latest
needs: [check, rustclippy, rustfmt]
if: ${{ github.event_name != 'pull_request' }} # Specify the branch condition
steps:
- name: Checkout Repository
uses: actions/checkout@v2
with:
# fetch tags for cargo ws publish
# might be a simple `fetch-tags: true` option soon, see https://github.com/actions/checkout/pull/579
fetch-depth: 0

- name: Setup
run: |
git config user.name github-actions
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
cargo install --git https://github.com/miraclx/cargo-workspaces --rev b2d49b9e575e29fd2395352e4d0df47def025039 cargo-workspaces
export GIT_PREVIOUS_TAG=$(git describe --tags --abbrev=0)
echo "GIT_PREVIOUS_TAG=${GIT_PREVIOUS_TAG}" >> $GITHUB_ENV
echo "[ pre run] current latest git tag is \"${GIT_PREVIOUS_TAG}\""
- name: Publish to crates.io and tag the commit
id: tag-and-publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
cargo ws publish --all --yes --exact \
--skip-published --no-git-commit --allow-dirty \
--tag-existing --tag-prefix 'v' \
--tag-msg 'crates.io snapshot' --tag-msg '%{https://crates.io/crates/%n/%v}' \
--no-individual-tags --no-git-push
export GIT_LATEST_TAG=$(git describe --tags --abbrev=0)
echo "GIT_LATEST_TAG=${GIT_LATEST_TAG}" >> $GITHUB_ENV
echo "[post run] current latest git tag is \"${GIT_LATEST_TAG}\""
echo "::set-output name=tagged::$( [[ "$GIT_LATEST_TAG" == "$GIT_PREVIOUS_TAG" ]] && echo 0 || echo 1 )"
# returning multi-line outputs gets truncated to include only the first line
# we have to escape the newline chars, runner auto unescapes them later
# https://github.saobby.my.eu.orgmunity/t/set-output-truncates-multiline-strings/16852/3
GIT_TAG_MESSAGE="$(git tag -l --format='%(body)' ${GIT_LATEST_TAG})"
GIT_TAG_MESSAGE="${GIT_TAG_MESSAGE//'%'/'%25'}"
GIT_TAG_MESSAGE="${GIT_TAG_MESSAGE//$'\n'/'%0A'}"
GIT_TAG_MESSAGE="${GIT_TAG_MESSAGE//$'\r'/'%0D'}"
echo "::set-output name=git_tag_message::${GIT_TAG_MESSAGE}"
- name: Push tags to GitHub (if any)
if: steps.tag-and-publish.outputs.tagged == 1
run: git push --tags

- name: Extract release notes
if: steps.tag-and-publish.outputs.tagged == 1
id: extract-release-notes
uses: ffurrer2/extract-release-notes@c24866884b7a0d2fd2095be2e406b6f260479da8

- name: Create release
if: steps.tag-and-publish.outputs.tagged == 1
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.GIT_LATEST_TAG }}
release_name: ${{ env.GIT_LATEST_TAG }}
body: |
## What's changed?
${{ steps.extract-release-notes.outputs.release_notes }}
**Crate Link**: ${{ steps.tag-and-publish.outputs.git_tag_message }}
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ env.GIT_PREVIOUS_TAG }}...${{ env.GIT_LATEST_TAG }}
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run release-plz
uses: MarcoIeni/release-plz-action@v0.5
env:
# https://marcoieni.github.io/release-plz/github/trigger.html
GITHUB_TOKEN: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
27 changes: 25 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/near/near-lake-framework/compare/v0.7.2...HEAD)
- Simpler start boilerplate, simpler structures to deal with!

### Breaking changes

This version introduces a different much simplified concept of Lake Framework usage. Thus it brings breaking changes.

We introduce `near-lake-primitives` crate with simplified primitive structures (e.g `Block`, `Transaction`, `StateChange`, etc.) which is heavily used by Lake Framework since now.

And some other changes:

- `LakeConfig` is renamed to be just `Lake`. It is done because since this update `Lake` is accepting the **indexing function** from a user and runs the streamer implicitly. Thus shortening and simplifying the start boilerplate to something like this:
```rust
fn main() -> anyhow::Result<()> {
// Lake Framework start boilerplate
near_lake_framework::LakeBuilder::default()
.mainnet()
.start_block_height(80504433)
.build()?
.run(handle_block) // user-defined asynchronous function that handles each block
}
```

Please note your main function isn't required to be asynchronous anymore! It is now handled by Lake Framework under the hood.

## [0.7.2](https://github.com/near/near-lake-framework/compare/v0.7.1...0.7.2)

Expand Down Expand Up @@ -36,7 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added proper error handling in a few places
- Updated the dependencies version of AWS crates

## [0.6.0](https://github.com/near/near-lake-framework/compare/v0.5.2...0.6.0)
## [0.6.0](https://github.com/near/near-lake-framework/compare/v0.5.2...v0.6.0)

- Upgrade underlying dependency `near-indexer-primitives` to versions between 0.15 and 0.16

Expand All @@ -51,7 +74,7 @@ a base64-encoded String that now became raw `Vec<u8>`:

**Refer to this [`nearcore` commit](https://github.com/near/nearcore/commit/8e9be9fff4d520993c81b0e3738c0f223a9538c0) to find all the changes of this kind.**

## [0.5.2](https://github.com/near/near-lake-framework/compare/v0.5.1...0.5.2)
## [0.5.2](https://github.com/near/near-lake-framework/compare/v0.5.1...v0.5.2)

- Fixed the bug that caused a lag by 100 blocks that was introduced in 0.5.1

Expand Down
46 changes: 12 additions & 34 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
[package]
name = "near-lake-framework"
version = "0.0.0" # managed by cargo-workspaces, see below
[workspace]
members = [
"lake-framework",
"lake-primitives",
"lake-parent-transaction-cache",
"lake-context-derive",
]

# cargo-workspaces
[workspace.package]
version = "0.8.0"
license = "MIT OR Apache-2.0"
repository = "https://github.com/near/near-lake-framework"
description = "Library to connect to the NEAR Lake S3 and stream the data"
categories = ["asynchronous", "api-bindings", "network-programming"]
keywords = ["near", "near-lake", "near-indexer"]
authors = ["Near Inc <hello@nearprotocol.com>"]
edition = "2021"
rust-version = "1.58.1"

# cargo-workspaces
[workspace.metadata.workspaces]
version = "0.7.2"

[dependencies]
anyhow = "1.0.51"
aws-config = "0.53.0"
aws-types = "0.53.0"
aws-credential-types = "0.53.0"
aws-sdk-s3 = "0.23.0"
async-stream = "0.3.3"
async-trait = "0.1.64"
derive_builder = "0.11.2"
futures = "0.3.23"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.75"
thiserror = "1.0.38"
tokio = { version = "1.28.2", features = ["sync", "time", "rt", "macros"] }
tokio-stream = { version = "0.1" }
tracing = "0.1.13"

near-indexer-primitives = "0.17"

[dev-dependencies]
aws-smithy-http = "0.53.0"

[lib]
doctest = false
rust-version = "1.69.0"
12 changes: 12 additions & 0 deletions lake-context-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "lake-context-derive"
version.workspace = true
# version = "0.0.0" # managed by cargo-workspaces
edition = "2021"

[lib]
proc-macro = true

[dependencies]
syn = "2.0"
quote = "1.0"
51 changes: 51 additions & 0 deletions lake-context-derive/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Lake Context Derive

Lake Context Derive is a Rust crate that provides a derive macro for easy and convenient implementation of the `near_lake_framework::LakeContextExt` trait. This trait has two functions: `execute_before_run` and `execute_after_run` that are executed before and after the user-provided indexer function respectively.

## Usage

The Lake Context Derive macro can be utilized by annotating the context struct with `#[derive(LakeContext)]`. This trait implementation will then facilitate the combination of different contexts. For instance, to use a `ParentTransactionCache` with some additional data, one would define a context like:

```no_run
use lake_parent_transaction_cache::ParentTransactionCache;
#[derive(LakeContext)]
struct MyContext {
db_connection_string: String,
parent_tx_cache: ParentTransactionCache,
}
```

### Instantiation

You can create an instance of your context as follows:

```no_run
let my_context = MyContext {
db_connection_string: String::from("postgres://user:pass@host/db"),
parent_tx_cache: ParentTransactionCache::default().build().unwrap(),
};
```

### User Indexer Function

This will simplify your indexer function signature. It now needs only the context as an additional parameter:

```no_run
async fn handle_block(
mut block: Block,
ctx: &MyContext,
) -> anyhow::Result<()> {
// body
}
```

The Lake Context Derive will look for all fields in the struct that implement `LakeContextExt`, and will append their trait methods to the top-level calls. For `execute_before_run`, it is done in ascending order, and for `execute_after_run` in descending order.

## Purpose

The purpose of the Lake Context Derive crate is to alleviate some of the common pain points in context development and usage in Rust. By encapsulating and standardizing the handling of these function calls, we aim to create a more accessible and user-friendly approach to context implementation.

## Collaboration

We hope that this tool will be useful for the Rust community and look forward to seeing how it can be used in a range of different projects. We encourage community contributions, whether that's through sharing your own unique context implementations or by providing feedback and suggestions for how we can continue to improve the Lake Context Derive.
80 changes: 80 additions & 0 deletions lake-context-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#![doc = include_str!("../README.md")]
use proc_macro::TokenStream;
use quote::quote;

#[proc_macro_derive(LakeContext)]
pub fn lake_context_derive(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);

// Used in the quasi-quotation below as `#name`.
let name = input.ident;

// Build the trait impl.
// Iterate over all fields and for each field generate a call to `execute_before_run`.
// if the field is a an impl of LakeContext, then call `execute_before_run` on the struct.

let fields = if let syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(syn::FieldsNamed { named, .. }),
..
}) = &input.data
{
named
} else {
unimplemented!();
};

let calls_before_run = fields
.iter()
.filter(|f| {
let ty = &f.ty;
if let syn::Type::Path(syn::TypePath { path, .. }) = ty {
if let Some(ident) = path.get_ident() {
ident == "LakeContext"
} else {
false
}
} else {
false
}
})
.map(|f| {
let name = &f.ident;
quote! { self.#name.execute_before_run(block); }
});

let calls_after_run = fields
.iter()
.rev()
.filter(|f| {
let ty = &f.ty;
if let syn::Type::Path(syn::TypePath { path, .. }) = ty {
if let Some(ident) = path.get_ident() {
ident == "LakeContext"
} else {
false
}
} else {
false
}
})
.map(|f| {
let name = &f.ident;
quote! { self.#name.execute_after_run(); }
});

let expanded = quote! {
// The generated impl.
impl near_lake_framework::LakeContextExt for #name {
fn execute_before_run(&self, block: &mut near_lake_primitives::block::Block) {
#( #calls_before_run )*
}

fn execute_after_run(&self) {
#( #calls_after_run )*
}
}
};

// Hand the output tokens back to the compiler.
proc_macro::TokenStream::from(expanded)
}
Loading

0 comments on commit 67fede7

Please sign in to comment.