Copilot commented on code in PR #19115:
URL: https://github.com/apache/pinot/pull/19115#discussion_r3678057870


##########
pinot-segment-local/src/main/java/org/apache/pinot/segment/local/upsert/BasePartitionUpsertMetadataManager.java:
##########
@@ -155,7 +156,10 @@ protected BasePartitionUpsertMetadataManager(String 
tableNameWithType, int parti
     _comparisonColumns = context.getComparisonColumns();
     _deleteRecordColumn = context.getDeleteRecordColumn();
     _hashFunction = context.getHashFunction();
-    _partialUpsertHandler = context.getPartialUpsertHandler();
+    // Build a handler owned by this partition. PartialUpsertHandler is not 
thread safe, and merges for a partition
+    // run on one consumer thread at a time, same as the _reusePreviousRow 
scratch state used alongside it.
+    Supplier<PartialUpsertHandler> partialUpsertHandlerSupplier = 
context.getPartialUpsertHandlerSupplier();
+    _partialUpsertHandler = partialUpsertHandlerSupplier != null ? 
partialUpsertHandlerSupplier.get() : null;

Review Comment:
   This change fixes a concurrency correctness issue by moving 
PartialUpsertHandler ownership to the partition, but there is no regression 
test asserting that two different partition metadata managers do not share the 
same handler instance. Adding a deterministic unit test (no timing) that 
creates two partition managers from the same UpsertContext and asserts the 
supplier is invoked twice and yields distinct handlers would help prevent 
accidental reintroduction of table-level sharing.



##########
pinot-segment-local/src/main/java/org/apache/pinot/segment/local/upsert/BasePartitionUpsertMetadataManager.java:
##########
@@ -155,7 +156,10 @@ protected BasePartitionUpsertMetadataManager(String 
tableNameWithType, int parti
     _comparisonColumns = context.getComparisonColumns();
     _deleteRecordColumn = context.getDeleteRecordColumn();
     _hashFunction = context.getHashFunction();
-    _partialUpsertHandler = context.getPartialUpsertHandler();
+    // Build a handler owned by this partition. PartialUpsertHandler is not 
thread safe, and merges for a partition
+    // run on one consumer thread at a time, same as the _reusePreviousRow 
scratch state used alongside it.
+    Supplier<PartialUpsertHandler> partialUpsertHandlerSupplier = 
context.getPartialUpsertHandlerSupplier();
+    _partialUpsertHandler = partialUpsertHandlerSupplier != null ? 
partialUpsertHandlerSupplier.get() : null;

Review Comment:
   If the context provides a non-null PartialUpsertHandler supplier but it 
returns null, this partition manager ends up treating the table as FULL upsert 
(because _partialUpsertHandler is null) while UpsertContext.getUpsertMode() 
reports PARTIAL (because the supplier is non-null). That mismatch can silently 
skip partial-upsert merging and lead to incorrect ingestion behavior. Consider 
enforcing the contract that a non-null supplier must return a non-null handler.



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