Skip to content

[Persistence] PrePersistence deprecation & Block lifecycle improvements (Issue #128 && Issue #105)#140

Merged
andrewnguyen22 merged 15 commits intomainfrom
issue-#128
Aug 15, 2022
Merged

[Persistence] PrePersistence deprecation & Block lifecycle improvements (Issue #128 && Issue #105)#140
andrewnguyen22 merged 15 commits intomainfrom
issue-#128

Conversation

@andrewnguyen22
Copy link
Copy Markdown
Contributor

@andrewnguyen22 andrewnguyen22 commented Aug 3, 2022

Objective

closes #128

  • Enable the lifecycle of block processing and production by creating a transactional architecture around persistence contexts instead of writing directly to the database on every operation.

closes #105 and closes #104

  • Deprecate and remove all PrePersistence related code.

Origin Document

Background

#128
Multiple persistence contexts enable a proper lifecycle for validators and full nodes as they maintain 'ephemeral' states in situations like block validation/processing and block production.

Pretty early on - it was discovered that though ephemeral states are needed, there seems to be little validity in having multiple write contexts in parallel - rather enable write contexts sequentially (only one at a time) and enable multiple read contexts. This is currently not strictly enforced, rather needs discussion on where to delegate this responsibility (Consensus, Utility, or Persistence module).

#105
[Persistence] V1 Persistence Foundation Integration Issue

Goals / Deliverables

  • Deliver completed code
  • Document the architecture and intended use
  • Test the transactional nature within the persistence module
  • Deprecation of the PrePersistence Module and all related code, docs, resources, etc...

General milestone checklist

  • Update all the relevant CHANGELOGs
  • Update all the relevant READMEs
  • Update the source code tree explanation
  • Add or update a state, sequence or flowchart diagram using mermaid
  • Create followup milestones + issues
  • Document small TODO along the way

Follow-up Work

All follow-up work is being tracked in #149


Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have tested my changes using the available tooling
  • If applicable, I have made corresponding changes to related or global README
  • If applicable, I have added added new diagrams using mermaid.js
  • If applicable, I have added tests that prove my fix is effective or that my feature works

Co-authored-by: Daniel Olshansky olshansky.daniel@gmail.com
Co-authored-by: Andrew Nguyen andrewnguyen@Andrews-MacBook-Pro-2.local
Co-authored-by: Andrew Nguyen andrewnguyen@Andrews-MBP-2.lan
Co-authored-by: Daniel Olshansky olshansky@pokt.network

Andrew Nguyen and others added 9 commits July 6, 2022 16:49
#73)

## Objective

Foundational iteration of PostgreSQL based persistence module implementation.

## Origin Document

#68

## Type of change

New major module implementation.

### Persistence-related core changes:
- List of actors / interfaces with MVP implementation:
    - Applications
    - Fisherman
    - ServiceNode
    - Accounts
    - Pools
- List of actors / interfaces with partial MVP implementation:
    - Validator
    - Gov params
- List of actors / interfaces with minorimplementation:
    - Block
- SQL Schema definition of the actors above
- SQL Query implementation for common actor persistence functionality
- PostgresContext implementation of the actors actors above
- Base infrastructure for fuzz testing

Non-persistence “fly-by” changes
- Updates to the PrePersistence module and utility module with breaking changes
- A few minor improvements/additions to the Makefile
- TODOs & comment cleanups throughout the codebase

## How Has This Been Tested?

### Unit Tests

```
make test_persistence
make test_all
```

### LocalNet
Ran a basic LocalNet following the instructions in the [development README](docs/development/README.md).


Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Andrew Nguyen <andrewnguyen@Andrews-MacBook-Pro-2.local>
Co-authored-by: Andrew Nguyen <andrewnguyen@Andrews-MBP-2.lan>
Co-authored-by: Daniel Olshansky <olshansky@pokt.network>
@andrewnguyen22 andrewnguyen22 requested a review from a team August 3, 2022 17:43
@andrewnguyen22
Copy link
Copy Markdown
Contributor Author

A ton of conflicts here. Will work on this in parallel - but wanted to get the PR up to get some eyes on immediately

@andrewnguyen22 andrewnguyen22 self-assigned this Aug 3, 2022
@andrewnguyen22 andrewnguyen22 changed the title Issue #128 Issue #128 && Issue #105 Aug 3, 2022
@Olshansk
Copy link
Copy Markdown
Collaborator

Olshansk commented Aug 3, 2022

@andrewnguyen22 It's a bit hard to review the changes in isolation because of all the conflicts with master so I think you'll need to do "merge with master" (i.e. I don't suggest a rebase here) and likely spend an hour or two resolvings. I acknowledge this isn't fun, but I think it's worth it and we'll have smaller PRs as the MVP takes shape make these less painful.

I looked at the changelogs and the interface changes and my high level understanding is this: Instead of writing to the postgres DB, we read/write to a transaction and commit it at the very end.

If that's the case, at a high level, it looks good to me and will review in depth once ready.

@andrewnguyen22
Copy link
Copy Markdown
Contributor Author

@andrewnguyen22 It's a bit hard to review the changes in isolation because of all the conflicts with master so I think you'll need to do "merge with master" (i.e. I don't suggest a rebase here) and likely spend an hour or two resolvings. I acknowledge this isn't fun, but I think it's worth it and we'll have smaller PRs as the MVP takes shape make these less painful.

I looked at the changelogs and the interface changes and my high level understanding is this: Instead of writing to the postgres DB, we read/write to a transaction and commit it at the very end.

If that's the case, at a high level, it looks good to me and will review in depth once ready.

Understood and agree, working on it now

@andrewnguyen22
Copy link
Copy Markdown
Contributor Author

Merged with main, conflicts gone.

Added two follow up issues #148 and #149

@Olshansk Olshansk added core Core infrastructure - protocol related persistence Persistence specific changes labels Aug 7, 2022
@Olshansk Olshansk added this to the V1 Persistence Foundation milestone Aug 7, 2022
@Olshansk Olshansk changed the title Issue #128 && Issue #105 [Persistence] PrePersistence deprecation & Block lifecycle improvements (Issue #128 && Issue #105) Aug 7, 2022
Copy link
Copy Markdown
Collaborator

@Olshansk Olshansk left a comment

Choose a reason for hiding this comment

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

I took a first pass at this PR, but will do a more detailed one after we address some of the comments and discuss some of the open questions I left inline.

@andrewnguyen22 I also left a couple of open-ended refactoring comments but didn't have time to tackle the changes myself. If you find that it's too much of a waste of time or too out of scope, feel free just to leave a TODO or comment and I can address it in a follow-up PR.

@andrewnguyen22 andrewnguyen22 requested a review from Olshansk August 9, 2022 19:49
@Olshansk
Copy link
Copy Markdown
Collaborator

@andrewnguyen22 I've spent most of the day going over this PR and the changes have become big enough that I've moved it into a separate branch for now.

I think there are some foundational business logic issues, but wanted to know your preference on:

  1. Merging this as is and reviewing / discussing [Persistence] Followup on PrePersistence deprecation & Block lifecycle  #165 separately
  2. Waiting for me to fix [Persistence] Followup on PrePersistence deprecation & Block lifecycle  #165 and pushing those changes to this branch

I would personally prefer (2), but am okay with (1) in order to unblock other work in parallel

@andrewnguyen22
Copy link
Copy Markdown
Contributor Author

@andrewnguyen22 I've spent most of the day going over this PR and the changes have become big enough that I've moved it into a separate branch for now.

I think there are some foundational business logic issues, but wanted to know your preference on:

  1. Merging this as is and reviewing / discussing Issue #128 fixes #165 separately
  2. Waiting for me to fix Issue #128 fixes #165 and pushing those changes to this branch

I would personally prefer (2), but am okay with (1) in order to unblock other work in parallel

Let's sync offline to make sure everything goes smoothly. Not closed off to either solution, but 1) does seem attractive given you've already split the PR into two

Copy link
Copy Markdown
Collaborator

@Olshansk Olshansk left a comment

Choose a reason for hiding this comment

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

@andrewnguyen22 As discussed offline, I'm working on the follow-ups to this in EDIT: Moving this to #165.

Hoping to approve this by EOD, but just reviewing to make sure I didn't lose any context.

I'm posting some of my previous comments, only one of which I believe needs an answer.

return
}
if err = conn.QueryRow(ctx, schema.GetAccountAmountQuery(address, height)).Scan(&amount); err != nil {
amount = "0"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I played around with this and cannot understand the intended behaviour.

We only return this default value if err != nil, but if err != nil, then the result should not be used because we should handle the error.

If we want to keep this in place, what we need to do is check the err and do something like (pseudocode):

amount = 0
if err = QueryRow.scan(&amount); err != RowNotFound {
     return "", err
}
return amount, nil      

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We only return this default value if err != nil, but if err != nil, then the result should not be used because we should handle the error.

The error returned can be row_not_found (pseudo) which should be translated to the default value

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can handle this higher in the stack if you prefer

func SelectAccounts(height int64, tableName string) string {
return fmt.Sprintf(`
SELECT address, balance, height
FROM %s WHERE height<=%d AND (height,address) IN (SELECT MAX(height),address from %s GROUP BY address)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

EDIT: Moving this to #165.

I'm updating this to use DISTINCT and avoiding the IN query. Even though this probably yields some performance gains (did not benchmark), I think it's more readable / understandable to see what query we're making.

Also going to add some unit tests here too.

func SelectAccounts(height int64, tableName string) string {
return fmt.Sprintf(`
SELECT address, balance, height
FROM %s WHERE height<=%d AND (height,address) IN (SELECT MAX(height),address from %s GROUP BY address)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

EDIT: Moving this to #165.

I added a few unit tests and there seemed to be a bug in the previous approach but I didn't dive deep enough to understand the reasoning. Here is the new business logic:

func SelectAccounts(height int64, tableName string) string {
	return fmt.Sprintf(`
			SELECT DISTINCT ON (address) address, balance, height
			FROM %s
			WHERE height<=%d
			ORDER BY address, height DESC
       `, tableName, height)
}

@andrewnguyen22
Copy link
Copy Markdown
Contributor Author

Continued conversation here #165 (comment)

BlockStore: m.blockStore,
ContextStore: kvstore.NewMemKVStore(),
func (m *persistenceModule) NewRWContext(height int64) (modules.PersistenceRWContext, error) {
db, err := ConnectAndInitializeDatabase(m.postgresURL, m.nodeSchema)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this might be the source of the issues I'm running into in the #128-fixes/improvements.

Can we reuse the same DB connection from Create here?

@Olshansk
Copy link
Copy Markdown
Collaborator

@andrewnguyen22 I'm getting close to finishing #165, so what are your thoughts on merging this in so #139 can start resolving merging conflicts while reviewing #165 in parallel?

Can approve the PR if that sounds good per out offline discussion.

@andrewnguyen22 andrewnguyen22 requested review from Olshansk and removed request for phthan0 August 15, 2022 21:48
Copy link
Copy Markdown
Collaborator

@Olshansk Olshansk left a comment

Choose a reason for hiding this comment

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

:shipit:

@andrewnguyen22 andrewnguyen22 merged commit 4358d64 into main Aug 15, 2022
@andrewnguyen22 andrewnguyen22 deleted the issue-#128 branch August 15, 2022 21:50
Olshansk added a commit that referenced this pull request Aug 18, 2022
#165)

# Objective

Follow up on both critical and non-critical fixes to #140.

# Origin Document

#140 deprecated PrePersistence and implemented multiple contexts. This PR is a follow with some stylistic changes, improvements in the readability of the tests, the addition of unit tests, bug fixes in some SQL business logic, and implementation of the read context.

Followup work is being tracked in #149.

## Learnings to streamline workflow in the future
- Do not conflate non-critical stylistic changes as it leads to more conflicts down the road
- Implemented an automated "LocalNet" for easier testing
- Try to plan work ahead of time so we can work in smaller PRs / iterations

## Changelog / changes

**Main persistence module changes:**

- Split `ConnectAndInitializeDatabase` into `connectToDatabase` and `initializeDatabase`
  - This enables creating multiple contexts in parallel without re-initializing the DB connection
- Fix the SQL query used in `SelectActors`, `SelectAccounts` & `SelectPools`
  - Add a generalized unit test for all actors
- Remove `NewPersistenceModule` and an injected `Config` + `Create`
  - This improves isolation a a “injection-like” paradigm for unit testing
- Change `SetupPostgresDocker` to `SetupPostgresDockerPersistenceMod`
  - This enables more “functional” like testing by returning a persistence module and avoiding global testing variables
  - Only return once a connection to the DB has been initialized reducing the likelihood of test race conditions
- Implemented `NewReadContext` with a proper read-only context

**Secondary persistence module changes**

- Improve return values in `Commit` and `Release` (return error, add logging, etc…)
- Add `pgx.Conn` pointer to `PostgresDB`
- `s/db/conn/g` and `s/conn/tx/g` in some (not all) places where appropriate
- Make some exported variables / functions unexported for readability & access purposes
- Add a few helpers for persistence related unit testing
- Added unit tests and TODOs for handling multiple read/write contexts

## General milestone checklist
- [x] Update all the relevant CHANGELOGs
- [ ] Update all the relevant READMEs
- [ ] Update the source code tree explanation
- [ ] Add or update a state, sequence or flowchart diagram using [mermaid](https://mermaid-js.github.io/mermaid/)
- [x] Create followup milestones + issues
- [x] Document small TODO along the way

## Follow-up Work

All follow-up work is being tracked in #149

---

## Checklist
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have tested my changes using the available tooling
- [ ] If applicable, I have made corresponding changes to related or global README
- [ ] If applicable, I have added added new diagrams using [memaid.js](https://mermaid-js.github.io)
- [ ] If applicable, I have added tests that prove my fix is effective or that my feature works

---

Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Andrew Nguyen <andrewnguyen@Andrews-MacBook-Pro-2.local>
Co-authored-by: Andrew Nguyen <andrewnguyen@Andrews-MBP-2.lan>
Co-authored-by: Daniel Olshansky <olshansky@pokt.network>
Co-authored-by: Andrew Nguyen <amnguyen1@mail.usf.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Core infrastructure - protocol related persistence Persistence specific changes

Projects

Status: Done

2 participants