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


##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -885,6 +853,117 @@ private void modifyPropertiesInternal(Map<String, String> 
jobProperties,
                 this.id, jobProperties, dataSourceProperties);
     }
 
+    private PreparedKafkaProperties 
prepareDataSourceProperties(KafkaDataSourceProperties dataSourceProperties,
+            boolean isReplay) throws UserException {
+        if (dataSourceProperties == null) {
+            return null;
+        }
+
+        KafkaDataSourceSnapshot dataSourceSnapshot = 
stageDataSourceProperties(dataSourceProperties);
+        List<Pair<Integer, Long>> kafkaPartitionOffsets = Lists.newArrayList();
+        if 
(MapUtils.isNotEmpty(dataSourceProperties.getOriginalDataSourceProperties())) {
+            kafkaPartitionOffsets = 
dataSourceProperties.getKafkaPartitionOffsets();
+        }
+        if (!kafkaPartitionOffsets.isEmpty()

Review Comment:
   [P1] Validate numeric-offset partitions against the staged topic. For an 
unpinned topic switch this condition skips the old-progress check, and 
resolveOffsets() cannot replace it: KafkaUtil.getRealOffsets() returns an 
all-numeric list without contacting Kafka. ALTER ... kafka_topic=new, 
kafka_partitions=999, kafka_offsets=0 therefore succeeds and journals bogus 
progress even when new has only partition 0; dynamic discovery later ignores 
999 and starts real partitions from the default. Fetch the staged topic's 
partition metadata for every requested ID, including all-numeric and mixed 
lists, before the Cloud reset or local apply.



##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -885,6 +853,117 @@ private void modifyPropertiesInternal(Map<String, String> 
jobProperties,
                 this.id, jobProperties, dataSourceProperties);
     }
 
+    private PreparedKafkaProperties 
prepareDataSourceProperties(KafkaDataSourceProperties dataSourceProperties,
+            boolean isReplay) throws UserException {
+        if (dataSourceProperties == null) {
+            return null;
+        }
+
+        KafkaDataSourceSnapshot dataSourceSnapshot = 
stageDataSourceProperties(dataSourceProperties);
+        List<Pair<Integer, Long>> kafkaPartitionOffsets = Lists.newArrayList();
+        if 
(MapUtils.isNotEmpty(dataSourceProperties.getOriginalDataSourceProperties())) {
+            kafkaPartitionOffsets = 
dataSourceProperties.getKafkaPartitionOffsets();
+        }
+        if (!kafkaPartitionOffsets.isEmpty()
+                && (!dataSourceSnapshot.resetProgress || 
CollectionUtils.isNotEmpty(customKafkaPartitions))) {
+            ((KafkaProgress) progress).checkPartitions(kafkaPartitionOffsets);
+        }
+
+        if (!isReplay) {
+            kafkaPartitionOffsets = resolveOffsets(dataSourceProperties, 
dataSourceSnapshot);
+            resetCloudProgressIfNeeded(dataSourceSnapshot, 
kafkaPartitionOffsets);

Review Comment:
   [P1] Do not commit Cloud progress during preparation. This RPC runs before 
the new target is re-resolved/replanned and before local apply or the EditLog 
write. In a combined target/source ALTER, another session can drop the analyzed 
target or make its schema incompatible; the reset commits, final validation 
then throws, and the FE job/journal stay unchanged while MetaService contains 
the new offsets. A later progress refresh or failover can import them into the 
old job and skip or replay records. Use a durable two-phase/conditional 
protocol or compensation so a rejected ALTER cannot change MetaService.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterRoutineLoadCommand.java:
##########
@@ -166,13 +193,21 @@ public void validate(ConnectContext ctx) throws 
UserException {
         // check load properties
         RoutineLoadJob job = Env.getCurrentEnv().getRoutineLoadManager()
                 .getJob(getDbName(), getJobName());
-        this.routineLoadDesc = CreateRoutineLoadInfo.checkLoadProperties(ctx, 
loadPropertyMap,
-                job.getDbFullName(), job.getTableName(), job.isMultiTable(), 
job.getMergeType());
+        if (MapUtils.isNotEmpty(loadPropertyMap)) {
+            this.routineLoadDesc = 
CreateRoutineLoadInfo.checkLoadProperties(ctx, loadPropertyMap,
+                    job.getDbFullName(), job.getTableName(), 
job.isMultiTable(), job.getMergeType());

Review Comment:
   [P1] Bind load-clause validation and application to the current target. Two 
concurrent ALTERs can bypass the same-statement exclusion: T1 validates WHERE 
k1 against target A here; T2 switches the paused job to incompatible B; then T1 
completes and RoutineLoadManager installs its A-derived RoutineLoadDesc after 
modifyProperties() has released the job lock. T1 succeeds but the job fails 
planning when resumed on B. This is distinct from the existing 
privilege/existence race because authorization may correctly use B. Revalidate 
and apply the descriptor in the same target-version/job-lock and journal 
boundary.



##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -907,7 +986,11 @@ private void 
resetCloudProgress(Cloud.ResetRLProgressRequest.Builder builder) th
     @Override
     public void replayModifyProperties(AlterRoutineLoadJobOperationLog log) {
         try {
-            modifyPropertiesInternal(log.getJobProperties(), 
(KafkaDataSourceProperties) log.getDataSourceProperties());
+            modifyPropertiesInternal(log.getJobProperties(),
+                    (KafkaDataSourceProperties) log.getDataSourceProperties());
+            if (log.getTargetTableId() != 0) {

Review Comment:
   [P1] Make replay independent of follower-local progress before applying the 
target. In Cloud mode a follower's KafkaProgress can lag the MetaService-owned 
master state. A combined target plus same-topic offset record for a dynamically 
discovered partition can therefore pass on the master but make this replay call 
throw checkPartitions() on the follower; the catch below consumes the journal 
record before the newly added tableId assignment runs. A later failover retains 
the old target. Replay the already validated prepared transition without 
state-dependent membership checks, and cover same-version Cloud failover with 
stale follower progress.



##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kinesis/KinesisRoutineLoadJob.java:
##########
@@ -675,25 +674,11 @@ private Map<String, String> 
getMaskedCustomProperties(String keyPrefix) {
     }
 
     @Override
-    public void modifyProperties(AlterRoutineLoadCommand command) throws 
UserException {
+    protected PreparedAlter prepareAlter(AlterRoutineLoadCommand command) {
         Map<String, String> jobProperties = command.getAnalyzedJobProperties();
         KinesisDataSourceProperties dataSourceProperties =
                 (KinesisDataSourceProperties) 
command.getDataSourceProperties();
-
-        writeLock();
-        try {
-            if (getState() != JobState.PAUSED) {
-                throw new DdlException("Only supports modification of PAUSED 
jobs");
-            }
-
-            modifyPropertiesInternal(jobProperties, dataSourceProperties);
-
-            AlterRoutineLoadJobOperationLog log = new 
AlterRoutineLoadJobOperationLog(this.id,
-                    jobProperties, dataSourceProperties);
-            Env.getCurrentEnv().getEditLog().logAlterRoutineLoadJob(log);
-        } finally {
-            writeUnlock();
-        }
+        return () -> modifyPropertiesInternal(jobProperties, 
dataSourceProperties);

Review Comment:
   [P1] Preserve the stored Kinesis default when this ALTER delta omits one. 
KinesisDataSourceProperties still calls analyzeKinesisDefaultPositionProperty() 
for every ALTER without explicit positions, which inserts 
kinesis_default_pos=LATEST into the delta. This closure feeds that synthetic 
value to customProperties.putAll(), so a stream/region/endpoint/custom-only 
ALTER overwrites an existing TRIM_HORIZON; on a stream switch, initial shard 
discovery then starts at LATEST and skips every record already present. Mirror 
Kafka's ALTER early return when neither shards nor a default was supplied, and 
cover live/replay/image preservation.



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