morningman opened a new pull request, #70121:
URL: https://github.com/apache/doris/pull/70121

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #70118
   
   Problem Summary:
   
   **In short.** When an FE rebuilds a routine load job from metadata (a 
follower replaying the edit log, a restart, a new master), the job loses 
`max_filter_ratio`, `exec_mem_limit`, `send_batch_parallelism`, 
`load_to_single_tablet`, `enclose`, `escape` and the 
`enable_memtable_on_sink_node` it was created with, and runs with defaults from 
then on. Separately, `ALTER ROUTINE LOAD` on `enclose` / `escape` never reaches 
the running job. This PR restores them when the job is rebuilt and applies the 
altered values.
   
   **Background.** A routine load job is persisted with GSON, which writes only 
the fields annotated with `@SerializedName`; these seven are plain fields. 
`gsonPostProcess` re-parses the stored CREATE statement, but only to rebuild 
the `RoutineLoadDesc` (columns, filters, separators, partitions, merge type), 
and restores the partial update settings from the persisted `jobProperties` 
map. CREATE records the other values in `jobProperties` as well (all but 
`exec_mem_limit`), and SHOW ROUTINE LOAD prints them from there, so the loss 
does not show. Found while making `SHOW CREATE ROUTINE LOAD` print these 
properties (#70118).
   
   **The problem, and what it cost.** Measured on master `856194ece0e` with a 
unit test that creates jobs from SQL and rebuilds them with a GSON round trip 
on a thread without a session, as a follower or a restarting FE does:
   
   | | Job as created | Job rebuilt from metadata |
   |---|---|---|
   | `max_filter_ratio` = 0.5 | 0.5 | 1.0: up to every row may be filtered 
instead of the job pausing |
   | `exec_mem_limit` = 4294967296 | 4 GB | 2 GB |
   | `send_batch_parallelism` = 3, or 4 from the creating session | 3 / 4 | 1 |
   | `load_to_single_tablet` = true | true | false |
   | `enclose` `"`, `escape` `\` | `"` / `\` | none: quoted CSV fields are 
split at the separators inside the quotes |
   | `enable_memtable_on_sink_node` of the creating session (on by default) | 
true | false |
   | `ALTER ... ("enclose" = "'", "escape" = "\|")` | tasks keep `"` / `\` | 
SHOW ROUTINE LOAD shows the new values, tasks never use them |
   | `ALTER ... ("enclose" = "ab")` | accepted, without effect | CREATE rejects 
it |
   
   The CSV and filter ratio cases change what gets loaded, without any error, 
after an event (a failover, a restart) that has nothing to do with the job.
   
   **How this PR fixes it.**
   
   - `gsonPostProcess` restores `max_filter_ratio`, `send_batch_parallelism`, 
`load_to_single_tablet`, `enclose` and `escape` from `jobProperties`, in the 
loop that already restores the partial update settings from there. CREATE has 
recorded these values since each property was introduced, and ALTER records the 
new ones; a job created before one of them existed has no key and keeps the 
default, as today. `exec_mem_limit`, which no ALTER changes and `jobProperties` 
does not hold, is taken from the CREATE statement that `gsonPostProcess` 
already re-parses.
   - CREATE records the creating session's `enable_memtable_on_sink_node` in 
the job's persisted session variables, next to `sql_mode`, and 
`gsonPostProcess` restores it. A job created before this has no record and 
keeps `false`, which is what it has run with after every restart so far.
   - `ALTER ROUTINE LOAD` checks `enclose` and `escape` the way CREATE does, 
and `modifyCommonJobProperties`, which Kafka and Kinesis jobs and the replay of 
an ALTER share, installs them on the job. The two rules move into 
`CsvFileFormatProperties.parseEnclose` / `parseEscape`, which 
`analyzeFileFormatProperties` now calls without any change in behavior.
   - A value that an older ALTER stored without the check is ignored with a 
warning, as it always was, instead of failing the replay of the job (which 
would cancel it) or of the ALTER.
   
   No new persisted field: the only addition is one key in the job's existing 
session variable map, which older FEs ignore.
   
   **Results.**
   
   | | Before | After |
   |---|---|---|
   | declared properties above, job rebuilt from metadata | defaults | as 
declared, also in what tasks are built from |
   | `send_batch_parallelism` and `enable_memtable_on_sink_node` from the 
creating session | 1 / false | the session's values |
   | ALTER of `enclose` / `escape` | shown, never used | used by the next task, 
kept when the job is rebuilt |
   | ALTER with `"enclose" = "ab"` | accepted | `enclose should not be longer 
than one byte.` |
   | such a value stored by an older ALTER | no effect | no effect, the replay 
goes on |
   
   branch-4.1 and branch-4.2 have the same gaps.
   
   ### Release note
   
   Routine load jobs keep max_filter_ratio, exec_mem_limit, 
send_batch_parallelism, load_to_single_tablet, enclose, escape and the 
enable_memtable_on_sink_node of the creating session on followers and after an 
FE restart or a master switch, instead of falling back to the defaults. ALTER 
ROUTINE LOAD now applies a new enclose or escape to the running job, and 
rejects the values CREATE ROUTINE LOAD rejects.
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [ ] Regression test
       - [x] Unit Test
       - [ ] Manual test (add detailed scripts or steps below)
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason <!-- Add your reason?  -->
   
       New `RoutineLoadJobReplayTest` (4 cases on a mocked FE) rebuilds jobs 
with a GSON round trip on a thread without a session: the declared properties 
survive, including in what tasks are built from; the values taken from the 
creating session survive; an altered enclose and escape reach the tasks and 
survive a rebuild; an invalid value from an older ALTER neither applies nor 
fails the replay. `AlterRoutineLoadCommandTest` gets a case for the new check. 
15 test classes (routine load, ALTER, CSV and JSON file formats, load 
commands), 146 cases, pass. With the production files reverted to master, all 5 
new cases fail, and each of the 12 parts of the fix, removed on its own, fails 
its assertion. Kinesis jobs share the changed code paths but need an AWS 
endpoint to create, so they have no case of their own.
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. <!-- Explain the behavior change -->
         A job rebuilt from metadata keeps these values instead of the 
defaults. ALTER ROUTINE LOAD rejects an invalid enclose or escape, which it 
used to accept without effect, and applies a valid one.
   
   - Does this need documentation?
       - [x] No.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label <!-- Add branch pick label that this PR should 
merge into -->
   


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