-
Notifications
You must be signed in to change notification settings - Fork 78
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
NeoFS block storage: add uploading commands #3582
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3582 +/- ##
==========================================
- Coverage 85.26% 84.62% -0.65%
==========================================
Files 333 334 +1
Lines 39005 39292 +287
==========================================
- Hits 33256 33249 -7
- Misses 4177 4475 +298
+ Partials 1572 1568 -4 ☔ View full report in Codecov by Sentry. |
@AnnaShaleva what do you think about adding more commands to neo-go cli?
|
8e1d6b3
to
64f6c7a
Compare
2938069
to
13e075a
Compare
13e075a
to
a6dc319
Compare
a6dc319
to
e5601ee
Compare
cli/util/uploader.go
Outdated
indexFileAttribute := ctx.String("index-attribute") | ||
acc, _, err := options.GetAccFromContext(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to load account: %w", err) |
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.
It should be a proper CLI exit error.
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.
We need unit-tests at least for error cases of this command. As mach cases should be covered as possible without access to NeoFS nodes (NeoGo RPC is included into Executor and hence may be used for tests).
expectedIndexCount := currentHeight / uint(indexFileSize) | ||
|
||
if existingIndexCount == expectedIndexCount { | ||
return nil |
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.
Write that index files are up-to-date.
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.
...Existing: %d, expected:...
cli/util/uploader.go
Outdated
defer wg.Done() | ||
defer func() { <-workerPool }() | ||
|
||
oidBlock, err := searchBlockOID(ctx, clientSDK, account, containerID, blockAttributeKey, index) |
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.
It's still there; we can't use Search request for every block, it's too time-consuming, imagine we have to perform 128K Search requests.
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.
Time taken for index file generation with searches: 17m3.919291917s
Time taken for index file generation with getHeader: 14m57.008241s
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've expected a bigger difference, btw. Still, that's it.
BTW, linter is failing. |
706 seconds / 1000 blocks = 0.706 seconds/block. 11m46s for 1k blocks with slicer version 394 seconds / 1000 blocks = 0.394 seconds/block. 6m34s for 1k blocks with pool (it still a month) with something like:
74 seconds / 1000 blocks = 0.074 seconds/block. 1m14s for 1k blocks (~5 days)
I haven't managed to repeat panic. successfully uploaded 1447000 blocks to testnet. |
e5601ee
to
1ddbbda
Compare
cli/util/uploader.go
Outdated
} | ||
|
||
attrs := []object.Attribute{ | ||
*object.NewAttribute("block", strconv.Itoa(blockIndex)), // Block index |
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.
"block" to attr
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.
Yep, we have to use user-provided value.
cli/util/convert.go
Outdated
@@ -109,6 +147,13 @@ func NewCommands() []*cli.Command { | |||
}, | |||
}, | |||
}, | |||
{ | |||
Name: "upload-bin", | |||
Usage: "Fetch blocks from RPC node and upload it to the NeoFS container", |
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.
s/upload it/upload them?
cli/util/convert.go
Outdated
{ | ||
Name: "upload-bin", | ||
Usage: "Fetch blocks from RPC node and upload it to the NeoFS container", | ||
UsageText: "neo-go util upload-bin --fs-rpc-endpoint address --container cid --block-attribute string --index-attribute string --rpc-endpoint address --wallet wallet [--wallet-config config] [--address address]", |
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.
--fs-rpc-endpoint <address1>[,<address2>[...]]
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.
--block-attribute block
--index-attribute index
--rpc-endpoint <node> [--timeout <time>]
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.
And while we're not yet have mainnet uploads, let's rename index file object attribute from oid
to index
(documentation and node config should be fixed).
cli/util/convert.go
Outdated
Usage: "Fetch blocks from RPC node and upload it to the NeoFS container", | ||
UsageText: "neo-go util upload-bin --fs-rpc-endpoint address --container cid --block-attribute string --index-attribute string --rpc-endpoint address --wallet wallet [--wallet-config config] [--address address]", | ||
Action: uploadBin, | ||
Flags: putFlags, |
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.
Rename putFlags
to uploadBinFlags
.
With ObjectSearchInitter ObjectSearch can be done both NeoFS SDK client or pool. Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This command is used for keeping container with blocks for blockfetcher updated. Close #3578 Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io> README: add archival notice (#520) People are likely to find this repo and we better have some directions for them. Signed-off-by: Roman Khimov <roman@nspcc.ru> Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
1ddbbda
to
0a4e1d1
Compare
producerWg.Add(numProducers) | ||
|
||
// Retry function with exponential backoff | ||
retry := func(action func() error) error { |
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.
Should we save it? Maybe yes? I like it. With it, timeouts are rare occasions.
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.
Let's keep it. Could you please point to the part of code that has a lot of timeout failures?
*object.NewAttribute(attributeKey, strconv.Itoa(int(i))), | ||
*object.NewAttribute("size", strconv.Itoa(int(indexFileSize))), | ||
*object.NewAttribute("timestamp", strconv.FormatInt(time.Now().Unix(), 10)), | ||
*object.NewAttribute("block-attribute", blockAttributeKey), |
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.
@AnnaShaleva what do you think about adding two more attributes to index files? timestamp
seems to me now useless -NeoFS will put it by itself. But block-attribute could be helpful for debagging and manual search.
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.
For timestamp - OK, remove it from this list. For block-attribute
: I'd say it's a bit excessive for the real usage because we always have block-attribute
in the node settings.
@@ -6,6 +6,7 @@ import ( | |||
"fmt" |
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.
neo-vm will be removed from this commit
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.
and commit message should be adjusted
@@ -16,12 +16,12 @@ attributes: | |||
- primary node index (`primary:0`) | |||
- block hash in the LE form (`hash:5412a781caf278c0736556c0e544c7cfdbb6e3c62ae221ef53646be89364566b`) | |||
- previous block hash in the LE form (`prevHash:3654a054d82a8178c7dfacecc2c57282e23468a42ee407f14506368afe22d929`) | |||
- millisecond-precision block timestamp (`time:1627894840919`) | |||
- millisecond-precision block timestamp (`timestamp:1627894840919`) |
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.
commit message
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.
Very good indeed! A couple of logic fixes are still needed, but overall looks much better.
// ObjectSearch returns a list of object IDs from the provided container. | ||
func ObjectSearch(ctx context.Context, c *client.Client, priv *keys.PrivateKey, containerIDStr string, prm client.PrmObjectSearch) ([]oid.ID, error) { | ||
func ObjectSearch(ctx context.Context, initter ObjectSearchInitter, priv *keys.PrivateKey, containerIDStr string, prm client.PrmObjectSearch) ([]oid.ID, error) { |
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 code itself is perfect, but regarding commit message: neofs: add pool for searching
it seems not to be matching the commit content, thus please rephrase.
fmt.Fprintln(ctx.App.Writer, "Chain block height:", currentBlockHeight) | ||
|
||
signer := user.NewAutoIDSignerRFC6979(acc.PrivateKey().PrivateKey) | ||
|
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.
Useless blank line.
// fetchMaxBlockIndex searches the container for the maximum block index. | ||
func fetchMaxBlockIndex(ctx context.Context, p *pool.Pool, containerID cid.ID, priv *keys.PrivateKey, attributeKey string) (int, error) { | ||
var wg sync.WaitGroup | ||
height := 0 |
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.
Good, but: why not to search starting from the current height? Uploader can (and should) guarantee that only single latest batch may be incomplete; older batches are guaranteed to be completed. If currently uploader can't guarantee that, then uploader algorithm should be fixed.
if res.numOIDs < searchBatchSize { | ||
if res.startIndex == 0 && res.numOIDs == 0 { | ||
return -1, nil | ||
} | ||
// Return the start index of the first incomplete batch | ||
return res.startIndex, nil |
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.
Please, check it and fix the code if it's true: we'll try to re-upload incomplete batch starting from block with index res.startIndex
; then we should not return -1
because there's no block with index -1
. Genesis block is not special anymore, we should remove the following part:
if res.startIndex == 0 && res.numOIDs == 0 {
return -1, nil
}
} | ||
|
||
// fetchMaxBlockIndex searches the container for the maximum block index. | ||
func fetchMaxBlockIndex(ctx context.Context, p *pool.Pool, containerID cid.ID, priv *keys.PrivateKey, attributeKey string) (int, error) { |
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.
And since the algorithm was changed, let's rename this function to fetchLatestMissingBlockIndex
. And adjust documentation, specify that it's the index of the first block in the latest incomplete batch.
|
||
var ( | ||
processedCounter atomic.Int32 | ||
errCh = make(chan error, 1) |
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.
Make it non-buffered.
} | ||
fmt.Fprintf(ctx.App.Writer, "Uploaded index file %d\n", i) | ||
} | ||
close(oidCh) |
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.
Move this close
to a deferred statement.
hdr.SetVersion(v) | ||
|
||
checksum.Calculate(&ch, checksum.TZ, objData) | ||
hdr.SetPayloadHomomorphicHash(ch) |
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.
We need to calculate/set it only if it's enabled in the network.
func getBlockIndex(header object.Object, attribute string) (int, error) { | ||
for _, attr := range header.UserAttributes() { | ||
if attr.Key() == attribute { | ||
return strconv.Atoi(attr.Value()) |
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.
Very nice, much better way.
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= | ||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= | ||
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= | ||
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= |
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.
Something has happened with go modules and VM git submodule, please, remove these changes from the PR.
example usage: