[#54] Fix patch logic #55
4 changed files with 76 additions and 31 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,5 +1,30 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.12.0] - 2025-04-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Patch logic
|
||||||
|
- Patch payload requirements
|
||||||
|
|
||||||
|
## [0.11.0] - 2025-04-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Placement policy vectors
|
||||||
|
|
||||||
|
## [0.10.0] - 2025-03-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Auto deploy to forgejo
|
||||||
|
|
||||||
|
## [0.9.0] - 2025-03-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- APE rule deserializer
|
||||||
|
|
||||||
## [0.9.0] - 2025-03-05
|
## [0.9.0] - 2025-03-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -6,9 +6,7 @@ import info.frostfs.sdk.dto.object.patch.Address;
|
||||||
import info.frostfs.sdk.dto.object.patch.Range;
|
import info.frostfs.sdk.dto.object.patch.Range;
|
||||||
import info.frostfs.sdk.dto.session.SessionToken;
|
import info.frostfs.sdk.dto.session.SessionToken;
|
||||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.*;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,12 +19,8 @@ public class PrmObjectPatch implements SessionContext {
|
||||||
@NotNull
|
@NotNull
|
||||||
private Address address;
|
private Address address;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Range range;
|
private Range range;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private InputStream payload;
|
private InputStream payload;
|
||||||
|
|
||||||
private List<ObjectAttribute> newAttributes;
|
private List<ObjectAttribute> newAttributes;
|
||||||
private boolean replaceAttributes;
|
private boolean replaceAttributes;
|
||||||
private int maxChunkLength;
|
private int maxChunkLength;
|
||||||
|
@ -39,4 +33,10 @@ public class PrmObjectPatch implements SessionContext {
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
this.maxChunkLength = maxChunkLength;
|
this.maxChunkLength = maxChunkLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PrmObjectPatch(Address address, List<ObjectAttribute> newAttributes, boolean replaceAttributes) {
|
||||||
|
this.address = address;
|
||||||
|
this.newAttributes = newAttributes;
|
||||||
|
this.replaceAttributes = replaceAttributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,21 +231,29 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
||||||
public ObjectId patchObject(PrmObjectPatch args, CallContext ctx) {
|
public ObjectId patchObject(PrmObjectPatch args, CallContext ctx) {
|
||||||
validate(args);
|
validate(args);
|
||||||
|
|
||||||
var request = createInitPatchRequest(args);
|
|
||||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
|
||||||
getOrCreateSession(args, ctx),
|
|
||||||
request.getBody().getAddress(),
|
|
||||||
frostfs.session.Types.ObjectSessionContext.Verb.PATCH,
|
|
||||||
getContext().getKey()
|
|
||||||
);
|
|
||||||
|
|
||||||
var currentPos = args.getRange().getOffset();
|
|
||||||
var chunkSize = args.getMaxChunkLength();
|
|
||||||
byte[] chunkBuffer = new byte[chunkSize];
|
|
||||||
|
|
||||||
var service = deadLineAfter(objectServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
var service = deadLineAfter(objectServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||||
PatchStreamer writer = new PatchStreamer(service);
|
PatchStreamer writer = new PatchStreamer(service);
|
||||||
|
|
||||||
|
var request = createInitPatchRequest(args, ctx);
|
||||||
|
writer.write(request.build());
|
||||||
|
|
||||||
|
if (nonNull(args.getPayload())) {
|
||||||
|
patchObjectPayload(request, args, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = writer.complete();
|
||||||
|
|
||||||
|
Verifier.checkResponse(response);
|
||||||
|
|
||||||
|
return ObjectIdMapper.toModel(response.getBody().getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void patchObjectPayload(Service.PatchRequest.Builder request, PrmObjectPatch args, PatchStreamer writer) {
|
||||||
|
var currentPos = args.getRange().getOffset();
|
||||||
|
|
||||||
|
var chunkSize = args.getMaxChunkLength() > 0 ? args.getMaxChunkLength() : AppConst.OBJECT_CHUNK_SIZE;
|
||||||
|
byte[] chunkBuffer = new byte[chunkSize];
|
||||||
|
|
||||||
var bytesCount = readNBytes(args.getPayload(), chunkBuffer, chunkSize);
|
var bytesCount = readNBytes(args.getPayload(), chunkBuffer, chunkSize);
|
||||||
while (bytesCount > 0) {
|
while (bytesCount > 0) {
|
||||||
var range = Service.Range.newBuilder()
|
var range = Service.Range.newBuilder()
|
||||||
|
@ -253,25 +261,25 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
||||||
.setLength(bytesCount)
|
.setLength(bytesCount)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Service.PatchRequest.Body.Patch.newBuilder()
|
var patch = Service.PatchRequest.Body.Patch.newBuilder()
|
||||||
.setChunk(ByteString.copyFrom(chunkBuffer, 0, bytesCount))
|
.setChunk(ByteString.copyFrom(chunkBuffer, 0, bytesCount))
|
||||||
.setSourceRange(range)
|
.setSourceRange(range)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
currentPos += bytesCount;
|
var body = Service.PatchRequest.Body.newBuilder()
|
||||||
|
.setAddress(request.getBody().getAddress())
|
||||||
|
.setPatch(patch)
|
||||||
|
.build();
|
||||||
|
request.setBody(body);
|
||||||
|
|
||||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
RequestConstructor.addMetaHeader(request, args.getXHeaders(), request.getMetaHeader().getSessionToken());
|
||||||
sign(request, getContext().getKey());
|
sign(request, getContext().getKey());
|
||||||
|
|
||||||
writer.write(request.build());
|
writer.write(request.build());
|
||||||
|
|
||||||
|
currentPos += bytesCount;
|
||||||
bytesCount = readNBytes(args.getPayload(), chunkBuffer, chunkSize);
|
bytesCount = readNBytes(args.getPayload(), chunkBuffer, chunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = writer.complete();
|
|
||||||
|
|
||||||
Verifier.checkResponse(response);
|
|
||||||
|
|
||||||
return ObjectIdMapper.toModel(response.getBody().getObjectId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectFrostFS getObject(Service.GetRequest request, CallContext ctx) {
|
private ObjectFrostFS getObject(Service.GetRequest request, CallContext ctx) {
|
||||||
|
@ -635,14 +643,26 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
||||||
return request.build();
|
return request.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Service.PatchRequest.Builder createInitPatchRequest(PrmObjectPatch args) {
|
private Service.PatchRequest.Builder createInitPatchRequest(PrmObjectPatch args, CallContext ctx) {
|
||||||
var address = AddressMapper.toGrpcMessage(args.getAddress());
|
var address = AddressMapper.toGrpcMessage(args.getAddress());
|
||||||
var body = Service.PatchRequest.Body.newBuilder()
|
var body = Service.PatchRequest.Body.newBuilder()
|
||||||
.setAddress(address)
|
.setAddress(address)
|
||||||
.setReplaceAttributes(args.isReplaceAttributes())
|
.setReplaceAttributes(args.isReplaceAttributes())
|
||||||
.addAllNewAttributes(ObjectAttributeMapper.toGrpcMessages(args.getNewAttributes()))
|
.addAllNewAttributes(ObjectAttributeMapper.toGrpcMessages(args.getNewAttributes()))
|
||||||
.build();
|
.build();
|
||||||
return Service.PatchRequest.newBuilder()
|
var request = Service.PatchRequest.newBuilder()
|
||||||
.setBody(body);
|
.setBody(body);
|
||||||
|
|
||||||
|
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||||
|
getOrCreateSession(args, ctx),
|
||||||
|
request.getBody().getAddress(),
|
||||||
|
frostfs.session.Types.ObjectSessionContext.Verb.PATCH,
|
||||||
|
getContext().getKey()
|
||||||
|
);
|
||||||
|
|
||||||
|
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||||
|
sign(request, getContext().getKey());
|
||||||
|
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -17,7 +17,7 @@
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>0.11.0</revision>
|
<revision>0.12.0</revision>
|
||||||
|
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
|
Loading…
Add table
Reference in a new issue