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

ORM codegen #10737

Closed
aaronc opened this issue Dec 10, 2021 · 4 comments · Fixed by #11033
Closed

ORM codegen #10737

aaronc opened this issue Dec 10, 2021 · 4 comments · Fixed by #11033
Labels

Comments

@aaronc
Copy link
Member

aaronc commented Dec 10, 2021

We may want to codegen a friendly client API than what we can do just with #10735. Details to be determined based on whatever shortcomings arise with #10735.

@aaronc
Copy link
Member Author

aaronc commented Dec 10, 2021

/cc @fdymylja

@aaronc aaronc added the C:orm label Jan 5, 2022
@aaronc
Copy link
Member Author

aaronc commented Jan 25, 2022

Here's what I'm currently thinking in terms of design.

Let's consider this simplified bank schema which by convention we could store in a file call state.proto

// state.proto

package bankexample;

message Balance {
  option (cosmos.orm.v1alpha1.table) = {
    id: 1;
    primary_key:{fields: "address,denom"}
    index: {id: 1 fields: "denom"}
  };

  string address = 1;
  string denom = 2;
  uint64 amount = 3;
}

message Supply {
  option (cosmos.orm.v1alpha1.table) = {
    id: 2;
    primary_key:{fields: "denom"}
  };

  string denom = 1;
  uint64 amount = 2;
}

This would generate two Store interfaces for Balance and Supply and one combined StateStore interface with its name derived from the file name state.proto. (If there are multiple files with ORM definitions in the same package we probably wouldn't try to combine them.)

type StateStore interface {
	BalanceStore
	SupplyStore
}

type BalanceStore interface {
	HasBalance(address string, denom string) (found bool, err error)
	GetBalance(address string, denom string) (*testpb.Balance, error)
	InsertBalance(*testpb.Balance) error
	UpdateBalance(*testpb.Balance) error
	SaveBalance(*testpb.Balance) error
	DeleteBalance(*testpb.Balance) error
	ListBalance(BalanceIndexKey, ...ormlist.Option) (BalanceIterator, error)
	ListBalanceRange(from, to BalanceIndexKey, ...ormlist.Option) (BalanceIterator, error)
        DeleteBalanceBy(BalanceIndexKey) error
}

type SupplyStore interface {
  ...
}

with index key types like this:

type BalanceIndexKey interface { ... }

type BalanceAddressDenomKey struct {	address, denom *string }

type BalanceDenomAddressKey struct { denom, address *string }

var _, _ BalanceIndexKey = BalanceAddressDenomKey{}. BalanceDenomAddressKey

func (k BalanceAddressDenomKey) WithAddress(address string) BalanceAddressDenomKey { ... }

func (k BalanceAddressDenomKey) WithAddressDenom(address, denom string) BalanceAddressDenomKey { ... }

func (k BalanceDenomAddressKey) WithDenom(denom string) BalanceAddressDenomKey { ... }

func (k BalanceDenomAddressKey) WithDenomAddress(denom, address string) BalanceAddressDenomKey { ... }

a range query with partial keys might look like:

it, err := stateStore.ListBalanceRange(
  BalanceAddressDenomKey{}.WithAddress("bar"),
  BalanceAddressDenomKey{}.WithAddress("foo"))

In terms of context.Context, we'd either need to add it as a param to each of the methods above or we could maybe get away with something like this where context isn't needed for every method:

type keeper struct {
  stateStoreAccessor bankexample.StateStoreAccessor
}

func (k keeper) Send(ctx context.Context, from, to, denom string, amount uint64) error {
  stateStore := stateStoreAccessor.Open(ctx)
  ...
}

I think we could get away with this accessor approach better with codegen than the current API because with the current API you probably want to statically store all the tables and indexes on the keeper like in

type keeper struct {
balanceTable ormtable.Table
balanceAddressDenomIndex ormtable.UniqueIndex
balanceDenomIndex ormtable.Index
supplyTable ormtable.Table
supplyDenomIndex ormtable.UniqueIndex


What do you think @fdymylja @technicallyty ?

@technicallyty
Copy link
Contributor

technicallyty commented Jan 26, 2022

+1 It looks like this design will simplify spinning up a module with the ORM by reducing boilerplate code. Are there any downsides to this approach?

@aaronc
Copy link
Member Author

aaronc commented Jan 26, 2022

+1 It looks like this design will simplify spinning up a module with the ORM by reducing boilerplate code. Are there any downsides to this approach?

generally the only downside I can think of is the dev time to write the codegen. but that will pay off many fold IMHO

@aaronc aaronc mentioned this issue Jan 26, 2022
19 tasks
@aaronc aaronc changed the title ORM client codegen ORM codegen Jan 26, 2022
@technicallyty technicallyty mentioned this issue Jan 27, 2022
19 tasks
@mergify mergify bot closed this as completed in #11033 Jan 28, 2022
mergify bot pushed a commit that referenced this issue Jan 28, 2022
## Description

adds orm code generation

Closes: #10737 



---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

2 participants