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


##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -766,91 +788,126 @@ public Map<String, String> getCustomProperties() {
         return getMaskedCustomProperties("property.");
     }
 
+    @Override
+    public boolean appliesRoutineLoadDescAtomically() {
+        return true;
+    }
+
     @Override
     public void modifyProperties(AlterRoutineLoadCommand command) throws 
UserException {
         Map<String, String> jobProperties = command.getAnalyzedJobProperties();
         KafkaDataSourceProperties dataSourceProperties = 
(KafkaDataSourceProperties) command.getDataSourceProperties();
-        if (null != dataSourceProperties) {
-            // if the partition offset is set by timestamp, convert it to real 
offset
-            convertOffset(dataSourceProperties);
-        }
 
         writeLock();
         try {
             if (getState() != JobState.PAUSED) {
                 throw new DdlException("Only supports modification of PAUSED 
jobs");
             }
+            if (command.getRoutineLoadDesc() != null && 
command.getLoadPropertyTableId() != tableId) {
+                throw new DdlException("Routine load target table changed 
while validating load properties; "
+                        + "please retry ALTER ROUTINE LOAD");
+            }
+            if (!command.hasTargetTable()) {
+                validateAlterJobPropertiesForMutation(command);
+            }
 
-            modifyPropertiesInternal(jobProperties, dataSourceProperties);
+            // Kafka offset resolution may perform external I/O. Keep it 
outside DB/table metadata locks.
+            PreparedKafkaProperties preparedDataSourceProperties =
+                    prepareDataSourceProperties(dataSourceProperties, false);
+            if (!command.hasTargetTable()) {
+                unprotectApplyAlter(command, dataSourceProperties, 
preparedDataSourceProperties);
+                return;
+            }
 
-            AlterRoutineLoadJobOperationLog log = new 
AlterRoutineLoadJobOperationLog(this.id,
-                    jobProperties, dataSourceProperties);
-            Env.getCurrentEnv().getEditLog().logAlterRoutineLoadJob(log);
+            Database db = Env.getCurrentInternalCatalog().getDbNullable(dbId);
+            if (db == null) {
+                throw new DdlException("Database not found: " + dbId);
+            }
+            db.readLock();
+            try {
+                Table table = db.getTableNullable(command.getTargetTableId());
+                if (table == null) {
+                    throw new DdlException("Table not found: " + 
command.getTargetTableId());
+                }
+                if (!(table instanceof OlapTable)) {
+                    throw new DdlException("Routine load target table must be 
an OLAP table");
+                }
+                table.readLock();
+                try {
+                    TUniqueKeyUpdateMode effectiveUniqueKeyUpdateMode = 
getEffectiveUniqueKeyUpdateMode(
+                            uniqueKeyUpdateMode, jobProperties);
+                    unprotectedValidateTargetTable(
+                            db, (OlapTable) table, jobProperties, 
effectiveUniqueKeyUpdateMode);
+                    unprotectApplyAlter(command, dataSourceProperties, 
preparedDataSourceProperties);
+                } finally {
+                    table.readUnlock();
+                }
+            } finally {
+                db.readUnlock();
+            }
         } finally {
             writeUnlock();
         }
     }
 
-    private void convertOffset(KafkaDataSourceProperties dataSourceProperties) 
throws UserException {
+    private void unprotectApplyAlter(AlterRoutineLoadCommand command,
+            KafkaDataSourceProperties dataSourceProperties,
+            PreparedKafkaProperties preparedDataSourceProperties) throws 
UserException {
+        modifyPropertiesInternal(command.getAnalyzedJobProperties(), 
dataSourceProperties,
+                preparedDataSourceProperties);
+        if (command.hasTargetTable()) {
+            tableId = command.getTargetTableId();

Review Comment:
   [P1] Make target/property alters survive checkpoint reload. EditLog replay 
restores this target and the new job properties, but 
RoutineLoadJob.gsonPostProcess() later reparses the unchanged CREATE origStmt, 
substitutes only the current table name, and validates the original properties 
against it. For example, a job created in fixed partial-update mode on MoW 
table A can switch to non-MoW B together with unique_key_update_mode=UPSERT, 
then be marked CANCELLED when an image reload validates the old fixed mode 
against B. Preserve the serialized current definition (or update the canonical 
statement) and add a full RoutineLoadJob image round-trip test.



##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -766,91 +788,126 @@ public Map<String, String> getCustomProperties() {
         return getMaskedCustomProperties("property.");
     }
 
+    @Override
+    public boolean appliesRoutineLoadDescAtomically() {
+        return true;
+    }
+
     @Override
     public void modifyProperties(AlterRoutineLoadCommand command) throws 
UserException {
         Map<String, String> jobProperties = command.getAnalyzedJobProperties();
         KafkaDataSourceProperties dataSourceProperties = 
(KafkaDataSourceProperties) command.getDataSourceProperties();
-        if (null != dataSourceProperties) {
-            // if the partition offset is set by timestamp, convert it to real 
offset
-            convertOffset(dataSourceProperties);
-        }
 
         writeLock();
         try {
             if (getState() != JobState.PAUSED) {
                 throw new DdlException("Only supports modification of PAUSED 
jobs");
             }
+            if (command.getRoutineLoadDesc() != null && 
command.getLoadPropertyTableId() != tableId) {
+                throw new DdlException("Routine load target table changed 
while validating load properties; "
+                        + "please retry ALTER ROUTINE LOAD");
+            }
+            if (!command.hasTargetTable()) {
+                validateAlterJobPropertiesForMutation(command);
+            }
 
-            modifyPropertiesInternal(jobProperties, dataSourceProperties);
+            // Kafka offset resolution may perform external I/O. Keep it 
outside DB/table metadata locks.
+            PreparedKafkaProperties preparedDataSourceProperties =
+                    prepareDataSourceProperties(dataSourceProperties, false);
+            if (!command.hasTargetTable()) {
+                unprotectApplyAlter(command, dataSourceProperties, 
preparedDataSourceProperties);
+                return;
+            }
 
-            AlterRoutineLoadJobOperationLog log = new 
AlterRoutineLoadJobOperationLog(this.id,
-                    jobProperties, dataSourceProperties);
-            Env.getCurrentEnv().getEditLog().logAlterRoutineLoadJob(log);
+            Database db = Env.getCurrentInternalCatalog().getDbNullable(dbId);
+            if (db == null) {
+                throw new DdlException("Database not found: " + dbId);
+            }
+            db.readLock();
+            try {
+                Table table = db.getTableNullable(command.getTargetTableId());
+                if (table == null) {
+                    throw new DdlException("Table not found: " + 
command.getTargetTableId());
+                }
+                if (!(table instanceof OlapTable)) {
+                    throw new DdlException("Routine load target table must be 
an OLAP table");
+                }
+                table.readLock();
+                try {
+                    TUniqueKeyUpdateMode effectiveUniqueKeyUpdateMode = 
getEffectiveUniqueKeyUpdateMode(
+                            uniqueKeyUpdateMode, jobProperties);
+                    unprotectedValidateTargetTable(
+                            db, (OlapTable) table, jobProperties, 
effectiveUniqueKeyUpdateMode);
+                    unprotectApplyAlter(command, dataSourceProperties, 
preparedDataSourceProperties);
+                } finally {
+                    table.readUnlock();
+                }
+            } finally {
+                db.readUnlock();
+            }
         } finally {
             writeUnlock();
         }
     }
 
-    private void convertOffset(KafkaDataSourceProperties dataSourceProperties) 
throws UserException {
+    private void unprotectApplyAlter(AlterRoutineLoadCommand command,
+            KafkaDataSourceProperties dataSourceProperties,
+            PreparedKafkaProperties preparedDataSourceProperties) throws 
UserException {
+        modifyPropertiesInternal(command.getAnalyzedJobProperties(), 
dataSourceProperties,
+                preparedDataSourceProperties);
+        if (command.hasTargetTable()) {
+            tableId = command.getTargetTableId();
+        }
+        setRoutineLoadDesc(command.getRoutineLoadDesc());
+        AlterRoutineLoadJobOperationLog log = new 
AlterRoutineLoadJobOperationLog(id,
+                command.getAnalyzedJobProperties(), dataSourceProperties, 
command.getTargetTableId(),
+                command.getRoutineLoadDesc());
+        Env.getCurrentEnv().getEditLog().logAlterRoutineLoadJob(log);

Review Comment:
   [P1] Do not wait for EditLog durability while holding the database and table 
metadata locks. This target path reaches synchronous logEdit with the job 
write, database read, and target-table read locks held. With batch logging, 
queue insertion retries indefinitely and logEditWithQueue waits without a 
timeout, so journal backpressure can indefinitely block DDL needing either 
metadata write lock; direct logging is synchronous too. This remains after 
Kafka/MetaService I/O was moved out of the locked region. Restructure the 
commit so journal ordering is preserved but no blocking journal operation runs 
under the metadata locks; the existing submitEdit/await split can separate 
completion in batch mode, while its synchronous direct-mode fallback also needs 
to stay outside those locks.



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