Skip to content

mempool: move interface into mempool package#3524

Merged
melekes merged 20 commits intodevelopfrom
2659-mempool
May 4, 2019
Merged

mempool: move interface into mempool package#3524
melekes merged 20 commits intodevelopfrom
2659-mempool

Conversation

@melekes
Copy link
Contributor

@melekes melekes commented Apr 2, 2019

Refs #2659

Breaking changes in the mempool package:

[mempool] #2659 Mempool now an interface
    old Mempool renamed to CListMempool
    NewMempool renamed to NewCListMempool
    Option renamed to CListOption
    MempoolReactor renamed to Reactor
    NewMempoolReactor renamed to NewReactor
    unexpose TxID method
    TxInfo.PeerID renamed to SenderID
    unexpose MempoolReactor.Mempool

Breaking changes in the state package:

[state] #2659 Mempool interface moved to mempool package
    MockMempool moved to top-level mock package and renamed to Mempool

Non Breaking changes in the node package:

[node] #2659 Add Mempool method, which allows you to access mempool
  • Updated all relevant documentation in docs
  • Updated all code comments where relevant
  • Wrote tests
  • Updated CHANGELOG_PENDING.md

====

https://en.wikipedia.org/wiki/Nighthawks
Nighthawks by Edward Hopper

@codecov-io
Copy link

codecov-io commented Apr 2, 2019

Codecov Report

Merging #3524 into develop will decrease coverage by 1.28%.
The diff coverage is 79.53%.

@@             Coverage Diff             @@
##           develop    #3524      +/-   ##
===========================================
- Coverage    64.25%   62.96%   -1.29%     
===========================================
  Files          213      217       +4     
  Lines        17463    18135     +672     
===========================================
+ Hits         11221    11419     +198     
- Misses        5308     5754     +446     
- Partials       934      962      +28
Impacted Files Coverage Δ
state/services.go 25% <ø> (-8.34%) ⬇️
mempool/mempool.go 84.21% <ø> (+3.67%) ⬆️
consensus/replay_file.go 0% <0%> (ø) ⬆️
rpc/core/pipe.go 28.84% <0%> (ø) ⬆️
consensus/wal_generator.go 82.17% <100%> (ø) ⬆️
consensus/replay.go 71.02% <100%> (+0.81%) ⬆️
state/execution.go 73.3% <100%> (ø) ⬆️
mempool/errors.go 30% <30%> (ø)
node/node.go 63.83% <45.45%> (-0.24%) ⬇️
mempool/clist_mempool.go 81.96% <81.96%> (ø)
... and 19 more

@melekes
Copy link
Contributor Author

melekes commented Apr 2, 2019

#2659 (comment)

Copy link
Contributor

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

Left some comments about the interfaces (and some nits about aliases).
I might lack some context. So please bare with me 🙈 I'll continue reading through the code and the changes.

@xla xla changed the title move Mempool interface into mempool package mempool: move interface into mempool package Apr 3, 2019
@melekes
Copy link
Contributor Author

melekes commented Apr 4, 2019

I think I went into the rabbit hole 🐇

// Updates to the mempool need to be synchronized with committing a block so
// apps can reset their transient state on Commit.
type Mempool interface {
Lock()
Copy link
Contributor

Choose a reason for hiding this comment

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

++ glad to see this is still here - we need to be able to claim this lock to avoid issues around recheck/commit.

See further: https://github.com/hyperledger/burrow/blob/develop/consensus/tendermint/abci/app.go#L321-L344

melekes added 6 commits April 4, 2019 12:48
Refs #2659

Breaking changes in the mempool package:

- Mempool now an interface
- old Mempool renamed to CListMempool

Breaking changes to state package:

- MockMempool moved to mempool/mock package and renamed to Mempool
- Mempool interface moved to mempool package
- combine everything into one interface
- rename TxInfo.PeerID to TxInfo.SenderID
- unexpose MempoolReactor.Mempool
TxsFront should not be a part of the Mempool interface
because it leaks implementation details. Instead, we need to come up
with general interface for querying the mempool so the MempoolReactor
can fetch and broadcast txs to peers.
// TxsFront returns the first transaction in the ordered list for peer
// goroutines to call .NextWait() on.
// FIXME: leaking implementation details!
TxsFront() *clist.CElement
Copy link
Contributor Author

@melekes melekes Apr 4, 2019

Choose a reason for hiding this comment

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

This needs to be fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

can't it just return *mempoolTx?

Copy link
Contributor

Choose a reason for hiding this comment

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

or is that the same problem?

Copy link
Contributor Author

@melekes melekes Apr 4, 2019

Choose a reason for hiding this comment

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

No, because later in the broadcastTxRoutine loop we're calling next.WaitNextChan followed by next.Next(). I don't think we want either of these methods in the MempoolTx interface.

What we want is

a simple interface for Reactor to subscribe/get txs from the mempool, so it can broadcast them to peers (order of txs for a single peer must be preserved).

Current design 👍 👍

A bunch of goroutines (broadcastTxRoutine) are blocked on a single channel. Once the channel is closed, they all access concurrent list (clist) and send txs to peers (preserving order). Later, at some point, the channel is recreated.

I like the current implementation, but struggling to find a good abstraction for it (to separate mempool and mempool reactor).

Iterator interface (plus a channel to get notified about txs) 👎

type Iterator interface {
  Next() bool
  Tx() MempoolTx
}

type Mempool interface {
  # creates an iterator starting from Nth item in the list/tree/any ordered structure
  Iterator(offset int) Iterator
  
  # Closed once there're txs in the mempool. Reopened after.
  TxsWaitChan() <-chan struct{}
}

Txs method (plus a channel to get notified about txs) 👎

type Mempool interface {
  # returns an array of txs in the mempool
  Txs(n, offset int) []MempoolTx
  
  # Closed once there're txs in the mempool. Reopened after.
  TxsWaitChan() <-chan struct{}
}

A single channel exposed by mempool 👍

type Mempool interface {
  TxsChan() <-chan MempoolTx
}

exposing a single channel should allow us to remove TxsWaitChan() <-chan struct{} method. But it's gets messy when it comes down to impl details - unbuffered vs buffered channel + we'll need an additional channel for each peer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On the second thought, maybe it's okay for MempoolReactor to require the CList implementation for now. It can be a follow-up PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

p2p.BaseReactor
config *cfg.MempoolConfig
Mempool *Mempool
mempool Mempool
Copy link
Contributor Author

@melekes melekes Apr 4, 2019

Choose a reason for hiding this comment

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

don't understand why it was exposed in the first place

Copy link
Contributor

@silasdavis silasdavis Apr 4, 2019

Choose a reason for hiding this comment

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

Not sure the reasoning, but as mentioned above we need the Mempool locker and until you added node.Mempool() (in this PR) node.MempoolReactor().Mempool was the only way to get it...

Come to think of it I think it was the only way to get CheckTx too, which I've always found handy :)

}

// txID is the hex encoded hash of the bytes as a types.Tx.
func txID(tx []byte) string {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

same here. seems like an implementation detail

@melekes
Copy link
Contributor Author

melekes commented Apr 23, 2019

Tests failed with:

--- FAIL: TestStartNextHeightCorrectly (0.22s)
    assertions.go:247: ^M                          ^M   Error Trace:    state_test.go:1329
        ^M      Error:          Should be true
        ^M      Test:           TestStartNextHeightCorrectly

seems not related.

@melekes melekes marked this pull request as ready for review April 23, 2019 12:23
@melekes melekes requested a review from xla as a code owner April 23, 2019 12:23
@liamsi
Copy link
Contributor

liamsi commented Apr 23, 2019

This failure was seen before in: #3310 (comment)

// cb: A callback from the CheckTx command.
// It gets called from another goroutine.
// CONTRACT: Either cb will get called, or err returned.
func (mem *CListMempool) CheckTx(tx types.Tx, cb func(*abci.Response)) (err error) {
Copy link
Contributor Author

@melekes melekes Apr 23, 2019

Choose a reason for hiding this comment

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

remove and force people to always use CheckTxWithInfo?

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably a good idea to discuss this in a separate issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Size() int

// TxsBytes returns the total size of all txs in the mempool.
TxsBytes() int64
Copy link
Contributor Author

Choose a reason for hiding this comment

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

better abstraction for stats?

@melekes melekes added the T:breaking Type: Breaking Change label Apr 23, 2019
@melekes melekes requested a review from jaekwon April 23, 2019 15:02
node/node.go Outdated
blockStore *bc.BlockStore // store the blockchain to disk
bcReactor *bc.BlockchainReactor // for fast-syncing
mempoolReactor *mempl.Reactor // for gossipping transactions
mempool *mempl.CListMempool
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this a pointer while in rpc/core/pipe.go it was changed to not be a pointer?

Copy link
Contributor Author

@melekes melekes Apr 24, 2019

Choose a reason for hiding this comment

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

Because node's mempool calls InitWAL/CloseWAL, but I don't want to add these methods to Mempool interface

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I created mempoolWithWAL interface

Copy link
Contributor Author

@melekes melekes Apr 24, 2019

Choose a reason for hiding this comment

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

Made them a part of Mempool interface for now.

  1. WAL is an implementation details and shouldn't really be a part of the interface.
  2. But we need a way to init/close associated resources
  3. And we need a way to configure them (wal path, etc.)

so we should either make node.Mempool a concrete type OR make InitWAL/CloseWAL/ConfigureWAL a part of any mempool interface (or make them more abstract like Start/Stop/Config)

// the DetachPrev() call, which makes old elements not reachable by
// peer broadcastTxRoutine() automatically garbage collected.

// TODO: Better handle abci client errors. (make it automatically handle connection errors)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same: is there an issue tracking this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so. There's #1993, which is one of the bugs

Copy link
Contributor

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

LGTM

blockStore: blockStore,
bcReactor: bcReactor,
mempoolReactor: mempoolReactor,
mempool: mempool,
Copy link
Contributor

Choose a reason for hiding this comment

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

cannot use mempool (variable of type *mempool.Mempool) as mempool.Mempool value in struct literal: missing method CheckTx (from typecheck)


"github.com/tendermint/tendermint/abci/example/code"
abci "github.com/tendermint/tendermint/abci/types"
mempl "github.com/tendermint/tendermint/mempool"
Copy link
Contributor

Choose a reason for hiding this comment

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

File is not gofmt-ed with -s (from gofmt)

Copy link
Contributor

@ebuchman ebuchman left a comment

Choose a reason for hiding this comment

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

Very nice start. This doesn't change any functionality right, just renames and file re-org?

Would be nice if we could preserve file names if files are changing, and then change the file names in a separate PR. Otherwise it's very difficult to review.

@melekes
Copy link
Contributor Author

melekes commented May 4, 2019

This doesn't change any functionality right, just renames and file re-org?

renames and re-org

@melekes melekes merged commit 5051a1f into develop May 4, 2019
@melekes melekes deleted the 2659-mempool branch May 4, 2019 06:41
@melekes melekes mentioned this pull request May 7, 2019
36 tasks
This was referenced May 30, 2019
brapse pushed a commit to brapse/tendermint that referenced this pull request Jun 5, 2019
## Description

Refs tendermint#2659

Breaking changes in the mempool package:

[mempool] tendermint#2659 Mempool now an interface
    old Mempool renamed to CListMempool
    NewMempool renamed to NewCListMempool
    Option renamed to CListOption
    MempoolReactor renamed to Reactor
    NewMempoolReactor renamed to NewReactor
    unexpose TxID method
    TxInfo.PeerID renamed to SenderID
    unexpose MempoolReactor.Mempool

Breaking changes in the state package:

[state] tendermint#2659 Mempool interface moved to mempool package
    MockMempool moved to top-level mock package and renamed to Mempool

Non Breaking changes in the node package:

[node] tendermint#2659 Add Mempool method, which allows you to access mempool

## Commits

* move Mempool interface into mempool package

Refs tendermint#2659

Breaking changes in the mempool package:

- Mempool now an interface
- old Mempool renamed to CListMempool

Breaking changes to state package:

- MockMempool moved to mempool/mock package and renamed to Mempool
- Mempool interface moved to mempool package

* assert CListMempool impl Mempool

* gofmt code

* rename MempoolReactor to Reactor

- combine everything into one interface
- rename TxInfo.PeerID to TxInfo.SenderID
- unexpose MempoolReactor.Mempool

* move mempool mock into top-level mock package

* add a fixme

TxsFront should not be a part of the Mempool interface
because it leaks implementation details. Instead, we need to come up
with general interface for querying the mempool so the MempoolReactor
can fetch and broadcast txs to peers.

* change node#Mempool to return interface

* save commit = new reactor arch

* Revert "save commit = new reactor arch"

This reverts commit 1bfceac.

* require CListMempool in mempool.Reactor

* add two changelog entries

* fixes after my own review

* quote interfaces, structs and functions

* fixes after Ismail's review

* make node's mempool an interface

* make InitWAL/CloseWAL methods a part of Mempool interface

* fix merge conflicts

* make node's mempool an interface
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T:breaking Type: Breaking Change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants