-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Conversation
This commit introduces a Backend trait and attempts to move away from the Action model via an OverlayBackend as in the ChainSelection subsystem.
3173449
to
0d28f06
Compare
0d28f06
to
3f48fad
Compare
This commit modifies all tests to ensure tests are passing.
3f48fad
to
844e56b
Compare
This commit addresses some oversights in the prior commit. 1. Inner errors in backend.write were swallowed 2. One-off write functions removed to avoid useless abstraction 3. Touch-ups in general
This commit removes the TestDB from tests.rs and replaces it with an in-memory kvdb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good modulo nits. Not sure if this warrants a burnin on Rococo, but it won't hurt.
fb802a0
to
7b9ff0d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First iteration looks good - a few small nits, logic check will be done in the second pass.
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use super::ops; |
&self, | ||
candidate_hash: &CandidateHash, | ||
) -> SubsystemResult<Option<CandidateEntry>> { | ||
super::ops::load_candidate_entry(&*self.inner, &self.config, candidate_hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super::ops::load_candidate_entry(&*self.inner, &self.config, candidate_hash) | |
ops::load_candidate_entry(&*self.inner, &self.config, candidate_hash) |
inner: &'a B, | ||
|
||
// `None` means unchanged | ||
stored_block_range: Option<StoredBlockRange>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of this implicit encoding set with Option
s, could we not store BackendWriteOp
directly? It costs a few extra bytes for the hash being present in addition, but from a clarity pov this would be advantageous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's actually a great suggestion... I would suggest we merge this PR and then follow-up in an additional PR, but more than happy to explore the right approach in this PR.
Paging @rphmeier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So basically, instead of a HashMap<K, Option<V>>
, you are suggesting we use
HashMap<K, BackendWriteOp>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the idea there be to have a single map K -> BackendWriteOp
? Otherwise I think it could get less clear, not more, because the type system would then express the possibility to have a BackendWriteOp::WriteCandidateEntry
in the block_entries
map, for example.
Reusing Option
for this is a little semantically wrong, but maybe a new enum is a better solution:
enum OverlayValue<T> { Present(T), Deleted }
// Semantically - `None` means 'defer to underlying'
stored_block_range: Option<OverlayValue<StoredBlockRange>>,
// Same here, when calling 'get' for a particular `Hash`.
block_entries: HashMap<Hash, OverlayValue<BlockEntry>>,
node/core/approval-voting/src/ops.rs
Outdated
Some(range) => if range.0 >= canon_number { | ||
return Ok(()) | ||
} else { | ||
range | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some(range) => if range.0 >= canon_number { | |
return Ok(()) | |
} else { | |
range | |
}, | |
Some(range) if range.0 >= canon_number => return Ok(()), | |
Some(range) => range, |
node/core/approval-voting/src/ops.rs
Outdated
Some(range) => if range.1 <= number { | ||
Some(StoredBlockRange(range.0, number + 1)) | ||
} else { | ||
None | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some(range) => if range.1 <= number { | |
Some(StoredBlockRange(range.0, number + 1)) | |
} else { | |
None | |
} | |
Some(range) if range.1 <= number => Some(StoredBlockRange(range.0, number + 1)), | |
Some(_) => None, |
node/core/approval-voting/src/ops.rs
Outdated
// All the block heights we visited but didn't necessarily delete everything from. | ||
let mut visited_heights = HashMap::new(); | ||
|
||
let visit_and_remove_block_entry = | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: If this does not capture state, make it a full fn
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, logic appears good from what I can see 👍
a70316a
to
103b873
Compare
|
||
pub(super) struct DbBackend { | ||
inner: Arc<dyn KeyValueDB>, | ||
pub(super) config: Config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would prefer this to be a getter fn config(&self) -> &Config
to protect mutability of the config.
} | ||
|
||
self.inner.write(tx)?; | ||
Ok(()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok(())
here is redundant if the ?;
is omitted from the above line, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference is the current impl does an implicit type conversion, if the returned Error types are the same, it indeed can be omitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks like the right direction. Could use a few organizational tweaks I've outlined in the comments.
f86a29c
to
ffabf96
Compare
// You should have received a copy of the GNU General Public License | ||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
//! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs better module docs 😅
backing_group: GroupIndex, | ||
our_assignment: Option<OurAssignment>, | ||
our_approval_sig: Option<ValidatorSignature>, | ||
pub tranches: Vec<TrancheEntry>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like any of this stuff being pub
. What happens when you remove it that is causing issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was due to the code move because the struct is created explicitly in tests. I added a constructor helper and pushed. Should be good to ship
bce41ed
to
4e8dde8
Compare
bot merge |
Trying merge. |
Closes #3311
This PR refactors the old
Action
logic in Approval Voting; opting for the more efficientOverlayedBackend
pattern proposed by @rphmeier in theChainSelection
subsystem.Note that the tests could be refactored further to reduce duplication of code, however this will be addressed in the PR for #3365. In addition, the tests in
tests.rs
could be further refactored to remove the use of TestStore and instead make use of an in-memorydyn KeyValueDB
. Due to this PR already getting quite large, I opted to address these items in the next refactor for cleaning up test logic.Otherwise, would it be preferential to address the superfluous use of
TestStore
in this PR?