[#421] Create common interface for kv repositories #454
No reviewers
Labels
No labels
P0
P1
P2
P3
badger
frostfs-adm
frostfs-cli
frostfs-ir
frostfs-lens
frostfs-node
good first issue
triage
Infrastructure
blocked
bug
config
discussion
documentation
duplicate
enhancement
go
help wanted
internal
invalid
kludge
observability
perfomance
question
refactoring
wontfix
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: TrueCloudLab/frostfs-node#454
Loading…
Reference in a new issue
No description provided.
Delete branch "ale64bit/frostfs-node:feature/kvio"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Add a common interface for key-value repositories.
This makes it easier to keep implementation-specific details from leaking into our codebase and swap underlying implementations with ease for the various components.
In this particular PR,
writecache
is rewritten using the interfaces and a small example is provided on how to use e.g. a badger-backed repository instead.Signed-off-by: Alejandro Lopez a.lopez@yadro.com
9eae170c80
to00c8712dc6
I am not sure I see the usefulness of introducing new interface:
Write
usesBatch
, butReadWrite
usesUpdate
-- the distinction betweenWrite
/ReadWrite
seems unrelated to theBatch
/Update
distinction. We would like to control such things on the client, the interface makes this harder.So what about implementing some interface for just the write-cache?
I think it would be easier to maintain, albeit bigger in terms of LOC, would like to hear other opinions.
cc @TrueCloudLab/storage-core-developers @realloc
@ -28,2 +30,2 @@
func openWC(cmd *cobra.Command) *bbolt.DB {
db, err := writecache.OpenDB(vPath, true, os.OpenFile)
func openWC(cmd *cobra.Command) kvio.Repository {
db, err := bboltrepo.Open(vPath, &bboltrepo.Options{
That is an implementation detail, at some point it can stop being
bolt
, for example.I'm aware. I just replaced the original call, which was already using an implementation detail (i.e. depending literally on bbolt).
This is intentional. Nothing wrong with thin interfaces, though? I would argue those are preferred in Go vs fat ones (such as our own
common.Storage
which is more of a virtual class than an interface).This is also intentional, but can be refined. The distinction between
Batch
/Update
in bbolt is only meaningful for concurrent calls. While we can make the interface reflect this, I don't think we depend anywhere on actually blocking and waiting for flush withUpdate
.At any rate, I don't think this is an issue with the interface itself.
How is the interface preventing this? It provides the means to do the same type of transactions as both repository implementations (including copy-less value reading and batched reads/writes)
I don't see how is this related to having an interface or not.
From my viewpoint, an interface that is specific to write-cache serves no purpose or is not as useful as having a layer isolating this common piece of utility (a key-value repository). We use these all over our codebase for different purposes (write-cache, metabase, pilorama, blobovnicza, testing registries, etc.). Currently we are just spamming it with bbolt-specifics when we could use an interface to make it easy to switch or compose specific components easily. The argument could be equally applied to every thin interface in the standard
io
package. A key-value repository is pretty much the basic building block of our products.I would love to hear other's opinions as well.
I think it's premature to make one interface for key-value storage right now, since it's possible that you won't be able to use it in all cases. For example, it is possible that the key-value implementation of the repository for pilorama will differ from the implementation for writecache.
In addition, this interface will no longer be as thin as we would like, since the backend for writecache may differ from the backend for pilorama or blobovnizca.
This applies to any interface. When would the right time be?
The idea is not to abstract what pilorama and writecache and others do with the key value repository, but to abstract what realistic implementations of key value repositories provide (bbolt, badger, others).
Consider the alternative: we make separate interfaces
WriteCacheKVRepo
,PiloramaKVRepo
, etc. to hide bbolt or badger and these interfaces will end up being mostly identical to the one provided in this PR, for no further benefit. We will have to have duplicate wrappers for bbolt, badger to satisfy those interfaces. I don't see how this is any better.But perhaps I don't really understand what @fyrchik means by "So what about implementing some interface for just the write-cache?". If you can provide some minimal example, that would help and I will happily oblige if everyone thinks that's better.
LGTM
But when we will have duplicates then we can merge they into one, if they are the same.
How is that different/better than splitting them when they diverge instead?
Well, it is just my point of view.
Pull request closed