Skip to content

sn: do not treat more than a single EC part on the same node as a success#4069

Open
carpawell wants to merge 1 commit into
masterfrom
fix/EC-placement-must-support-at-least-DATAPART-number-of-successes
Open

sn: do not treat more than a single EC part on the same node as a success#4069
carpawell wants to merge 1 commit into
masterfrom
fix/EC-placement-must-support-at-least-DATAPART-number-of-successes

Conversation

@carpawell

@carpawell carpawell commented Jul 7, 2026

Copy link
Copy Markdown
Member

No description provided.

@carpawell carpawell self-assigned this Jul 7, 2026
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.23810% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.56%. Comparing base (facd0db) to head (d1a104e).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
pkg/services/object/put/ec.go 96.61% 2 Missing ⚠️
pkg/services/object/put/distributed.go 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4069      +/-   ##
==========================================
+ Coverage   26.45%   26.56%   +0.10%     
==========================================
  Files         671      671              
  Lines       45581    45632      +51     
==========================================
+ Hits        12060    12122      +62     
+ Misses      32390    32383       -7     
+ Partials     1131     1127       -4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@carpawell carpawell changed the title sn: do not treat more that single EC part on the same node as success sn: do not treat more than a single EC part on the same node as a success Jul 7, 2026
@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch from ab98864 to 551f29e Compare July 7, 2026 20:32
@carpawell

carpawell commented Jul 8, 2026

Copy link
Copy Markdown
Member Author
NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              1d4h ⚑ ◒  
▶ neofs-cli container create -r s01.neofs.devenv:8080 --policy 'EC 3/1 CBF 1' -w wallets/wallet.json --basic-acl "public-read-write"                           
Enter password > 
neofscontainer creation request accepted for processing (the operation may not be completed yet)
container ID: CaSmiYvN6SuQ8E7bMVzHkzLsMPEB1f9tuZYEXZNuaBFK

NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1y75d § ◒  ⍉
▶ neofs-cli object put -r s01.neofs.devenv:8080 -w wallets/wallet.json --cid CaSmiYvN6SuQ8E7bMVzHkzLsMPEB1f9tuZYEXZNuaBFK --file tmp/10Klines.txt --timeout 1m
Enter password > 
 100000 / 100000 [========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================] 100.00% 0s
[tmp/10Klines.txt] Object successfully stored
  OID: ExuNBE8ucepxuxHjaCPDKA3B2YMCZBwYPzST5mB9VXM7
  CID: CaSmiYvN6SuQ8E7bMVzHkzLsMPEB1f9tuZYEXZNuaBFK

NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         1y75d § ◒  
▶ docker stop s04                                                                                                                                             
s04

NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         1y75d § ◒  
▶ neofs-cli object put -r s01.neofs.devenv:8080 -w wallets/wallet.json --cid CaSmiYvN6SuQ8E7bMVzHkzLsMPEB1f9tuZYEXZNuaBFK --file tmp/10Klines.txt --timeout 1m
Enter password > 
 100000 / 100000 [=======================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================] 100.00% 40s
Error: rpc error: finish object stream: status: code = 1024 message = incomplete object PUT by placement: only 3 EC parts was put successfully for 3 data parts number, latest error: save on SN #2: could not close object stream: replicate object to remote node (key=038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35): all 038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35 endpoints failed, first error: /dns4/s04.neofs.devenv/tcp/8080: API transport (op=/neo.fs.v2.object.ObjectService/Replicate): rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 192.168.130.74:8080: i/o timeout"

NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1y75d ⚑ ◒  ⍉
▶ docker stop s03
s03

NSPCC/git/neofs-dev-env  master ✗                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         1y75d ⚑ ◒  
▶ neofs-cli object put -r s01.neofs.devenv:8080 -w wallets/wallet.json --cid CaSmiYvN6SuQ8E7bMVzHkzLsMPEB1f9tuZYEXZNuaBFK --file tmp/10Klines.txt --timeout 1m
Enter password > 
 100000 / 100000 [=======================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================] 100.00% 20s
Error: rpc error: finish object stream: status: code = 1024 message = not enought nodes for EC parts (2 parts were put)

@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch from 551f29e to b707499 Compare July 8, 2026 17:32
@carpawell carpawell marked this pull request as ready for review July 8, 2026 17:32
@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch 3 times, most recently from c1425f3 to 9c3418c Compare July 8, 2026 19:18
@carpawell carpawell marked this pull request as draft July 8, 2026 19:18
@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch 2 times, most recently from cc042cd to 3662963 Compare July 8, 2026 19:35
@carpawell carpawell marked this pull request as ready for review July 8, 2026 19:38
@carpawell carpawell marked this pull request as draft July 8, 2026 19:44
@carpawell carpawell marked this pull request as ready for review July 8, 2026 19:45
@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch from b8bdfbe to 3662963 Compare July 8, 2026 19:56
Comment thread pkg/services/object/put/distributed.go Outdated
err := t.applyECRule(t.sessionSigner, obj, ecRuleIdx, payloadParts, objNodeLists[ruleIdx])
handleECRule := func(ruleIdx int, ecRuleIdx int, payloadParts [][]byte, ecRule iec.Rule) (bool, error) {
var nodes = objNodeLists[ruleIdx]
if len(nodes) < int(ecRule.DataPartNum) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unrelated. And this must never happen

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

not unrelated to me, this is highly used inside PR's new logic. but if it is always true (nothing is said about it in ContainerNodes interface) then ok, dropped

Comment thread pkg/services/object/put/ec.go Outdated

func (t *distributedTarget) applyECRule(signer neofscrypto.Signer, obj object.Object, ruleIdx int, payloadParts [][]byte, nodeList []netmap.NodeInfo) error {
var eg errgroup.Group
var errStopECIter = errors.New("stop EC placement iteration")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

seems redundant, it's enough returning bool from submitNodeFailure()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

err is more explicit to me that smth is wrong, ok made it bool

Comment thread pkg/services/object/put/ec.go Outdated
}

func (p *ecProgress) canTryNode(n netmap.NodeInfo) bool {
if p == nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

checking this by callers is more clear to me

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

i read it as "no need to track progress" logic, so put it inside ecProgress. moved

Comment thread pkg/services/object/put/ec.go Outdated
return errStopECIter
}
p.leftAvailableNodes--
placementFailed := p.leftAvailableNodes-int(p.ecRule.DataPartNum) < 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what if there is 1 part left to save, 1 available node is left and policy is 2/1?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

reworked

Comment thread pkg/services/object/put/ec.go Outdated
var errStopECIter = errors.New("stop EC placement iteration")

func newECProgress(nodeList []netmap.NodeInfo, ecRule iec.Rule) *ecProgress {
nodes := make(map[string]struct{}, len(nodeList))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nodeList is a set, so it's enough to deal with idxs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can even be a bit set. And can use atomics instead of locks then.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

not sure why you think it is critical in a routine that calculates EC objects, hashes, uses network, disks, etc, but reworked

Comment thread pkg/services/object/put/ec.go Outdated
return fmt.Errorf("not enought nodes for EC parts (%d parts were put)", successes)
}
err.singleErr = fmt.Errorf("only %d EC parts were put successfully"+
" for %d/%d EC rule, latest error: %w", successes, p.ecRule.DataPartNum, p.ecRule.ParityPartNum, err.singleErr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
" for %d/%d EC rule, latest error: %w", successes, p.ecRule.DataPartNum, p.ecRule.ParityPartNum, err.singleErr)
" for %s EC rule, latest error: %w", successes, p.ecRule, err.singleErr)

Comment thread pkg/services/object/put/ec.go Outdated

var successes = p.successPuts.Load()
if p.stop {
return fmt.Errorf("not enought nodes for EC parts (%d parts were put)", successes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return fmt.Errorf("not enought nodes for EC parts (%d parts were put)", successes)
return fmt.Errorf("not enough nodes for EC parts (%d parts were put)", successes)

Comment thread pkg/services/object/put/ec.go Outdated
if p.stop {
return fmt.Errorf("not enought nodes for EC parts (%d parts were put)", successes)
}
err.singleErr = fmt.Errorf("only %d EC parts were put successfully"+

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

there can be several rules with same X/Y parameters. Worth adding rule number

Comment thread pkg/services/object/put/ec.go
Comment thread CHANGELOG.md Outdated
Comment thread pkg/services/object/put/ec.go Outdated
var errStopECIter = errors.New("stop EC placement iteration")

func newECProgress(nodeList []netmap.NodeInfo, ecRule iec.Rule) *ecProgress {
nodes := make(map[string]struct{}, len(nodeList))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can even be a bit set. And can use atomics instead of locks then.

Closes #3994.

Signed-off-by: Pavel Karpy <carpawell@nspcc.io>
@carpawell carpawell force-pushed the fix/EC-placement-must-support-at-least-DATAPART-number-of-successes branch from 3662963 to d1a104e Compare July 10, 2026 13:35
Comment thread pkg/services/object/put/ec.go
return false
}
p.failedPuts++
placementFailed := len(p.nodes)-p.failedPuts < int(p.ecRule.DataPartNum)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • EC 1/1 CBF 1, i.e. 2 nodes
  • 1st node fails, 1 node is left

we cannot put 2 parts, so it's a complete fail. But condition will be false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants