github-actions[bot] commented on code in PR #67759:
URL: https://github.com/apache/doris/pull/67759#discussion_r3980257147


##########
be/src/load/channel/load_channel_mgr.cpp:
##########
@@ -177,7 +186,12 @@ Status LoadChannelMgr::add_batch(const 
PTabletWriterAddBlockRequest& request,
     // this case will be handled in load channel's add batch method.
     Status st = channel->add_batch(request, response);
     if (UNLIKELY(!st.ok())) {
-        RETURN_IF_ERROR(channel->cancel());
+        // Release the manager's ownership too. The last in-flight request
+        // releases the writers with the channel.
+        PTabletWriterCancelRequest cancel_request;
+        *cancel_request.mutable_id() = request.id();
+        cancel_request.set_cancel_reason(st.to_string());
+        RETURN_IF_ERROR(cancel(cancel_request));

Review Comment:
   [P1] Bind the failure transition to the retained channel instance
   
   At this point this RPC has already observed `st`, but it re-enters the 
manager by load ID without first publishing `st` to `channel`. A concurrent 
final EOS can take `_lock`, still see that same channel as uncancelled, and 
install a success tombstone; the later cancel then finds no live entry and 
preserves that success. Conversely, if timeout cleanup removed X and an open 
created Y with the same ID, this stale RPC cancels Y instead of X. Both 
orderings are reachable from independent heavy-work-pool RPCs. Please publish 
the error on the captured channel and make the manager transition compare the 
current mapping with that exact instance (or generation) before erasing/caching 
it. A barrier test should cover failure versus final EOS and replacement open.



##########
be/src/cloud/cloud_delta_writer.cpp:
##########
@@ -154,6 +157,7 @@ void CloudDeltaWriter::update_tablet_stats() {
 Status CloudDeltaWriter::commit_rowset() {
     g_cloud_commit_rowset_count << 1;
     std::lock_guard<bthread::Mutex> lock(_mtx);
+    RETURN_IF_ERROR(_get_load_cancel_status());

Review Comment:
   [P2] Recheck cancellation before the empty-rowset commit
   
   This is the only check before `_commit_empty_rowset()`, but 
`CloudRowsetBuilder::init()` ends with a separate, potentially blocking 
`prepare_rowset` RPC. If cancellation is published while prepare is in flight, 
the helper returns from init, builds the rowset, and starts the later metadata 
`commit_rowset` RPC without another status load. That creates avoidable 
post-cancel metadata work and can extend close/final-owner latency while 
transaction abort is already under way. Please recheck after init/build and 
before the distinct commit RPC; a delayed-prepare test should assert that 
cancellation prevents commit.



##########
be/src/load/channel/load_channel.cpp:
##########
@@ -304,13 +310,18 @@ bool LoadChannel::is_finished() {
     return _tablets_channels.empty();
 }
 
-Status LoadChannel::cancel() {
-    _cancelled.store(true);
-    std::lock_guard<std::mutex> l(_lock);
-    for (auto& it : _tablets_channels) {
-        static_cast<void>(it.second->cancel());
-    }
+Status LoadChannel::cancel(const Status& reason) {
+    DCHECK(!reason.ok());
+    _cancel_status->update(reason);

Review Comment:
   [P2] Make pressure flushing observe the shared load status
   
   This publisher no longer traverses writers, so 
`MemTableWriter::_is_cancelled` stays false until final-owner destruction. 
Meanwhile an unrelated request hitting global memory pressure can promote this 
load's registered writer and call `flush_async()`, which checks only that local 
flag; even after manager cancellation has returned it can submit/reset the 
active memtable and start new local/cloud segment work. Please make 
`flush_async()` inspect its copied `WriteRequest::load_cancel_status` under the 
writer lock before submission/reset (without counting cancellation as flushed 
memory or invoking a blocking error path under the limiter lock), and cover the 
retained-cancelled-writer pressure ordering with a deterministic test.



##########
be/src/load/delta_writer/delta_writer.cpp:
##########
@@ -182,6 +196,7 @@ Status DeltaWriter::write(const Block* block, const 
TabletAddRowsPayload& rows,
                 config::memtable_flush_running_count_limit *
                 (_req.write_req_type == WriteRequestType::GROUP ? 2 : 1);
         while (_memtable_writer->flush_running_count() >= 
effective_flush_running_count_limit) {
+            RETURN_IF_ERROR(_get_load_cancel_status());

Review Comment:
   [P2] Recheck cancellation after the blocking writer phases
   
   The new checks do not cover return from lazy `init()` or exit from the final 
backpressure sleep. If cancellation is published while either phase blocks and 
the next flush-count condition is false, this path reaches 
`MemTableWriter::write()` without another status load; the empty local 
`close()` has the same post-`init()` gap. `CloudDeltaWriter::write()` has the 
parallel post-loop omission, including the S3-queue condition. Because 
cancellation no longer waits on writer locks, these paths can append/close and 
acknowledge work after cancellation is already observable. Please add 
post-`init()` and post-loop gates immediately before the next memtable 
operation in both implementations, with a barrier test for the final-sleep exit.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to