Skip to content

Implement streaming replication - #4164

Open
cthulhu-rider wants to merge 3 commits into
masterfrom
replication-stream
Open

cthulhu-rider wants to merge 3 commits into
masterfrom
replication-stream

Conversation

@cthulhu-rider

Copy link
Copy Markdown
Contributor

No description provided.

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 40.95238% with 62 lines in your changes missing coverage. Please review.
✅ Project coverage is 31.49%. Comparing base (12f6437) to head (6cbae14).

Files with missing lines Patch % Lines
pkg/services/object/server.go 38.88% 55 Missing ⚠️
cmd/neofs-node/object.go 0.00% 4 Missing ⚠️
pkg/services/object/put/local.go 66.66% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4164   +/-   ##
=======================================
  Coverage   31.48%   31.49%           
=======================================
  Files         677      678    +1     
  Lines       41369    41447   +78     
=======================================
+ Hits        13025    13053   +28     
- Misses      28344    28394   +50     

☔ 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.

@cthulhu-rider
cthulhu-rider force-pushed the replication-stream branch 3 times, most recently from a1bacbc to 8c4e822 Compare September 2, 2026 15:52
Refactoring purpose, except that the status messages are updated
naturally. Make header verification, payload verification and local save
separately.

This will be useful for #4157. For ReplicateV2 handler, header is needed
to be checked before payload reading. Also, streaming write into local
storage is needed.

Signed-off-by: Leonard Liubich <leonard@morphbits.io>
Implementation relies on full payload buffering, which is something
we want to get rid of in ReplicateV2 (#4157). At the same time, the
implementation is no-op for regular objects.

Signed-off-by: Leonard Liubich <leonard@morphbits.io>
@cthulhu-rider
cthulhu-rider force-pushed the replication-stream branch 2 times, most recently from 6702af9 to e62eca4 Compare September 23, 2026 12:58
Stream them directly into the local storage instead.

Refs #4157.

Signed-off-by: Leonard Liubich <leonard@morphbits.io>
@cthulhu-rider

Copy link
Copy Markdown
Contributor Author

code is rdy for review. Gonna make performance runs and add unit tests in the background

@cthulhu-rider
cthulhu-rider marked this pull request as ready for review September 23, 2026 13:26
Comment thread cmd/neofs-node/object.go
return x.local.Search(ctx, cID, fs, attrs, cursor, count)
}

func (x storageForObjectService) VerifyAndStoreObjectLocally(ctx context.Context, obj object.Object) error {

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.

Fixes #2796?

if isStream {
// TODO: can be optimized from two sides:
// 1. header structure decoding can be done without unmarshaling (e.g. via protoscan funcs)
// 2. since header is already serialized in the original request, io.WriterTo can be implemented around it

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.

2 should be easy to do, isn't it? Although PUTs are relatively slow (and streamed ones are relatively big), so not likely to be noticeable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, it's not very difficult, but given the general case of unordered fields, the logic will have to branch. Therefore, I still suggest doing this separately

if len(chunk) == 0 {
return nil, newBadRequestStatus("empty payload chunk"), nil
var st *protostatus.Status
gotHash, gotPayloadLen, st, err = readReplicatedObjectPayload(obj.PayloadSize(), recvChunkFn, func(chunk []byte) *protostatus.Status {

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.

Why not passing a simple (optional) io.Writer there? This callback doesn't do a lot, can be simplified this way.


var st *protostatus.Status
gotHash, gotPayloadLen, st, err = readReplicatedObjectPayload(obj.PayloadSize(), recvChunkFn, func(chunk []byte) *protostatus.Status {
payload = append(payload, chunk...)

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.

bytes.Buffer can be used here to provide io.Writer.

This branch has not been deployed

No deployments
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.

2 participants