Skip to content

Conversation

@joker-star-l
Copy link

@joker-star-l joker-star-l commented Oct 23, 2024

Add new doris out plugin.

#9501

Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
[SERVICE]
    Log_Level debug
    parsers_file github_parsers.conf

[INPUT]
    Name tail
    Parser github
    Path /path/to/github.log
    read_from_head true

[OUTPUT]
    name doris
    match *
    host localhost
    port 8030
    endpoint_type fe
    user admin
    password admin
    database d_fb
    table github_events
    header columns created_at=now()
    time_key false
    log_request true
    log_progress_interval 10
  • Debug log output from testing the change
Fluent Bit v4.2.0
* Copyright (C) 2015-2025 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io

______ _                  _    ______ _ _             ___   __  
|  ___| |                | |   | ___ (_) |           /   | /  | 
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   __/ /| | `| | 
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / / /_| |  | | 
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V /\___  |__| |_
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/     |_(_)___/


[2025/11/04 21:49:02.109225310] [ info] Configuration:
[2025/11/04 21:49:02.134329406] [ info]  flush time     | 1.000000 seconds
[2025/11/04 21:49:02.140882544] [ info]  grace          | 5 seconds
[2025/11/04 21:49:02.141181436] [ info]  daemon         | 0
[2025/11/04 21:49:02.141532890] [ info] ___________
[2025/11/04 21:49:02.141971795] [ info]  inputs:
[2025/11/04 21:49:02.142444375] [ info]      tail
[2025/11/04 21:49:02.142857269] [ info] ___________
[2025/11/04 21:49:02.143171395] [ info]  filters:
[2025/11/04 21:49:02.143549062] [ info] ___________
[2025/11/04 21:49:02.143880524] [ info]  outputs:
[2025/11/04 21:49:02.144289429] [ info]      doris.0
[2025/11/04 21:49:02.144683129] [ info] ___________
[2025/11/04 21:49:02.145013736] [ info]  collectors:
[2025/11/04 21:49:02.221361483] [ info] [fluent bit] version=4.2.0, commit=480885ac71, pid=1510627
[2025/11/04 21:49:02.227425227] [debug] [engine] coroutine stack size: 24576 bytes (24.0K)
[2025/11/04 21:49:02.233638441] [ info] [storage] ver=1.5.3, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2025/11/04 21:49:02.234225303] [ info] [simd    ] disabled
[2025/11/04 21:49:02.234592801] [ info] [cmetrics] version=1.0.5
[2025/11/04 21:49:02.340957646] [ info] [output:doris:doris.0] Start progress reporter with interval 10
[2025/11/04 21:49:02.235134748] [ info] [ctraces ] version=0.6.6
[2025/11/04 21:49:02.258644192] [ info] [input:tail:tail.0] initializing
[2025/11/04 21:49:02.260147108] [ info] [input:tail:tail.0] storage_strategy='memory' (memory only)
[2025/11/04 21:49:02.408204660] [ info] [output:doris:doris.0] worker initializing
[2025/11/04 21:49:02.503053637] [ info] [output:doris:doris.0] worker initializing
[2025/11/04 21:49:02.261652379] [debug] [tail:tail.0] created event channels: read=32 write=33
[2025/11/04 21:49:02.504457463] [ info] [output:doris:doris.0] worker #1 started
[2025/11/04 21:49:02.504244803] [ info] [output:doris:doris.0] worker #0 started
[2025/11/04 21:49:02.272400019] [debug] [input:tail:tail.0] flb_tail_fs_inotify_init() initializing inotify tail input
[2025/11/04 21:49:02.273085766] [debug] [input:tail:tail.0] inotify watch fd=38
[2025/11/04 21:49:02.275563907] [debug] [input:tail:tail.0] scanning path /home/liumx/CProjects/fluent-bit-test/github.log
[2025/11/04 21:49:02.286008133] [debug] [input:tail:tail.0] file will be read in POSIX_FADV_DONTNEED mode /home/liumx/CProjects/fluent-bit-test/github.log
[2025/11/04 21:49:02.295177954] [debug] [input:tail:tail.0] inode=2517030 with offset=0 appended as /home/liumx/CProjects/fluent-bit-test/github.log
[2025/11/04 21:49:02.296327261] [debug] [input:tail:tail.0] scan_glob add(): /home/liumx/CProjects/fluent-bit-test/github.log, inode 2517030
[2025/11/04 21:49:02.297910800] [debug] [input:tail:tail.0] 1 new files found on path '/home/liumx/CProjects/fluent-bit-test/github.log'
[2025/11/04 21:49:02.301937224] [debug] [doris:doris.0] created event channels: read=40 write=41
[2025/11/04 21:49:02.391692822] [ info] [sp] stream processor started
[2025/11/04 21:49:02.397100778] [ info] [engine] Shutdown Grace Period=5, Shutdown Input Grace Period=2
[2025/11/04 21:49:02.504780969] [debug] [input:tail:tail.0] [static files] processed 32.0K
[2025/11/04 21:49:02.544919090] [debug] [input:tail:tail.0] [static files] processed 32.0K
[2025/11/04 21:49:02.584081706] [debug] [input:tail:tail.0] [static files] processed 32.0K
[2025/11/04 21:49:02.621604682] [debug] [input:tail:tail.0] [static files] processed 32.0K
[2025/11/04 21:49:02.655484562] [debug] [input:tail:tail.0] [static files] processed 32.0K
[2025/11/04 21:49:02.687522847] [debug] [input:tail:tail.0] [static files] processed 29.2K
[2025/11/04 21:49:02.689733927] [debug] [input:tail:tail.0] inode=2517030 file=/home/liumx/CProjects/fluent-bit-test/github.log promote to TAIL_EVENT
[2025/11/04 21:49:02.692422666] [ info] [input:tail:tail.0] inotify_fs_add(): inode=2517030 watch_fd=1 name=/home/liumx/CProjects/fluent-bit-test/github.log
[2025/11/04 21:49:02.695955159] [debug] [input:tail:tail.0] [static files] processed 0b, done
[2025/11/04 21:49:02.731015173] [debug] [task] created task=0x844c570 id=0 OK
[2025/11/04 21:49:02.734446902] [debug] [output:doris:doris.0] task_id=0 assigned to thread #0
[2025/11/04 21:49:02.935613411] [ info] [output:doris:doris.0] http body: {"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}
{"id":"37066529222","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-30T23:00:00Z"}
{"id":"37066529223","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":
[2025/11/04 21:49:03.169021457] [debug] [output:doris:doris.0] send to fe
[2025/11/04 21:49:03.298560731] [debug] [upstream] KA connection #75 to localhost:8030 is connected
[2025/11/04 21:49:03.300296804] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:03.304826445] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264142_153218d6-d5bd-426a-ade1-75ed896bf1d7
[2025/11/04 21:49:03.339393605] [debug] [http_client] server localhost:8030 will close connection #75
[2025/11/04 21:49:03.340280881] [ info] [output:doris:doris.0] localhost:8030, HTTP status=307
(null)

[2025/11/04 21:49:03.341601942] [debug] [output:doris:doris.0] send to be
[2025/11/04 21:49:03.348544072] [debug] [upstream] KA connection #76 to 127.0.0.1:8040 is connected
[2025/11/04 21:49:03.348807069] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:03.349034341] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264142_153218d6-d5bd-426a-ade1-75ed896bf1d7
[2025/11/04 21:49:03.417505374] [ info] [output:doris:doris.0] 127.0.0.1:8040, HTTP status=200
{
    "TxnId": 3094,
    "Label": "fluentbit_d_fb_github_events_1762264142_153218d6-d5bd-426a-ade1-75ed896bf1d7",
    "Comment": "",
    "TwoPhaseCommit": "false",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 1100,
    "NumberLoadedRows": 1100,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 193600,
    "LoadTimeMs": 67,
    "BeginTxnTimeMs": 1,
    "StreamLoadPutTimeMs": 5,
    "ReadDataTimeMs": 0,
    "WriteDataTimeMs": 36,
    "ReceiveDataTimeMs": 7,
    "CommitAndPublishTimeMs": 23
}


[2025/11/04 21:49:03.433853903] [debug] [upstream] KA connection #76 to 127.0.0.1:8040 is now available
[2025/11/04 21:49:03.439641327] [debug] [out flush] cb_destroy coro_id=0
[2025/11/04 21:49:03.448035542] [debug] [task] destroy task=0x844c570 (task_id=0)
[2025/11/04 21:49:08.563124128] [debug] [input:tail:tail.0] inode=2517030, /home/liumx/CProjects/fluent-bit-test/github.log, events: IN_MODIFY 
[2025/11/04 21:49:08.718203513] [debug] [task] created task=0x83d07d0 id=0 OK
[2025/11/04 21:49:08.718618941] [debug] [output:doris:doris.0] task_id=0 assigned to thread #1
[2025/11/04 21:49:08.719147047] [ info] [output:doris:doris.0] http body: {"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}

[2025/11/04 21:49:08.719881357] [debug] [output:doris:doris.0] send to fe
[2025/11/04 21:49:08.722889753] [debug] [upstream] KA connection #75 to localhost:8030 is connected
[2025/11/04 21:49:08.723033812] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:08.723196380] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264148_900d53f7-8aed-4297-8815-cf36e7783b4c
[2025/11/04 21:49:08.732258819] [debug] [http_client] server localhost:8030 will close connection #75
[2025/11/04 21:49:08.732412645] [ info] [output:doris:doris.0] localhost:8030, HTTP status=307
(null)

[2025/11/04 21:49:08.732514024] [debug] [output:doris:doris.0] send to be
[2025/11/04 21:49:08.735325567] [debug] [upstream] KA connection #77 to 127.0.0.1:8040 is connected
[2025/11/04 21:49:08.735591889] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:08.735818431] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264148_900d53f7-8aed-4297-8815-cf36e7783b4c
[2025/11/04 21:49:08.796330478] [ info] [output:doris:doris.0] 127.0.0.1:8040, HTTP status=200
{
    "TxnId": 3095,
    "Label": "fluentbit_d_fb_github_events_1762264148_900d53f7-8aed-4297-8815-cf36e7783b4c",
    "Comment": "",
    "TwoPhaseCommit": "false",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 1,
    "NumberLoadedRows": 1,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 176,
    "LoadTimeMs": 59,
    "BeginTxnTimeMs": 0,
    "StreamLoadPutTimeMs": 5,
    "ReadDataTimeMs": 0,
    "WriteDataTimeMs": 22,
    "ReceiveDataTimeMs": 7,
    "CommitAndPublishTimeMs": 29
}


[2025/11/04 21:49:08.797214868] [debug] [upstream] KA connection #77 to 127.0.0.1:8040 is now available
[2025/11/04 21:49:08.797591566] [debug] [out flush] cb_destroy coro_id=0
[2025/11/04 21:49:08.798124874] [debug] [task] destroy task=0x83d07d0 (task_id=0)
[2025/11/04 21:49:10.459620334] [debug] [input:tail:tail.0] inode=2517030, /home/liumx/CProjects/fluent-bit-test/github.log, events: IN_MODIFY 
[2025/11/04 21:49:10.717974745] [debug] [task] created task=0x8417f50 id=0 OK
[2025/11/04 21:49:10.718294756] [debug] [output:doris:doris.0] task_id=0 assigned to thread #0
[2025/11/04 21:49:10.718881087] [ info] [output:doris:doris.0] http body: {"id":"37066529221","type":"PushEvent","actor":{"id":46139131},"repo":{"id":780125623},"payload":{"repository_id":780125623},"public":true,"created_at":"2024-10-29T23:00:00Z"}

[2025/11/04 21:49:10.719488093] [debug] [output:doris:doris.0] send to fe
[2025/11/04 21:49:10.722433300] [debug] [upstream] KA connection #75 to localhost:8030 is connected
[2025/11/04 21:49:10.722581116] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:10.722780567] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264150_99c37158-832f-4a80-922f-d52715fad801
[2025/11/04 21:49:10.731513563] [debug] [http_client] server localhost:8030 will close connection #75
[2025/11/04 21:49:10.731718609] [ info] [output:doris:doris.0] localhost:8030, HTTP status=307
(null)

[2025/11/04 21:49:10.731854969] [debug] [output:doris:doris.0] send to be
[2025/11/04 21:49:10.733496400] [debug] [upstream] KA connection #76 to 127.0.0.1:8040 has been assigned (recycled)
[2025/11/04 21:49:10.733841673] [debug] [http_client] not using http_proxy for header
[2025/11/04 21:49:10.734033574] [debug] [output:doris:doris.0] add label: fluentbit_d_fb_github_events_1762264150_99c37158-832f-4a80-922f-d52715fad801
[2025/11/04 21:49:10.802559661] [ info] [output:doris:doris.0] 127.0.0.1:8040, HTTP status=200
{
    "TxnId": 3096,
    "Label": "fluentbit_d_fb_github_events_1762264150_99c37158-832f-4a80-922f-d52715fad801",
    "Comment": "",
    "TwoPhaseCommit": "false",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 1,
    "NumberLoadedRows": 1,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 176,
    "LoadTimeMs": 67,
    "BeginTxnTimeMs": 0,
    "StreamLoadPutTimeMs": 6,
    "ReadDataTimeMs": 0,
    "WriteDataTimeMs": 29,
    "ReceiveDataTimeMs": 8,
    "CommitAndPublishTimeMs": 31
}


[2025/11/04 21:49:10.803164704] [debug] [upstream] KA connection #76 to 127.0.0.1:8040 is now available
[2025/11/04 21:49:10.804056150] [debug] [task] destroy task=0x8417f50 (task_id=0)
[2025/11/04 21:49:10.803573384] [debug] [out flush] cb_destroy coro_id=1
[2025/11/04 21:49:12.343166222] [ info] [output:doris:doris.0] total 0 MB 1102 ROWS, total speed 0 MB/s 110 R/s, last 10 seconds speed 0 MB/s 110 R/s
^C[2025/11/04 21:49:14] [engine] caught signal (SIGINT)
[2025/11/04 21:49:14.154391712] [ warn] [engine] service will shutdown in max 5 seconds
[2025/11/04 21:49:14.156204058] [ info] [engine] pausing all inputs..
[2025/11/04 21:49:14.157238887] [ info] [input] pausing tail.0
[2025/11/04 21:49:14.719365243] [ info] [engine] service has stopped (0 pending tasks)
[2025/11/04 21:49:14.719719673] [ info] [input] pausing tail.0
[2025/11/04 21:49:14.722080686] [ info] [output:doris:doris.0] thread worker #0 stopping...
[2025/11/04 21:49:14.723416032] [ info] [output:doris:doris.0] worker exiting
[2025/11/04 21:49:14.730201146] [ info] [output:doris:doris.0] thread worker #0 stopped
[2025/11/04 21:49:14.754540070] [ info] [output:doris:doris.0] thread worker #1 stopping...
[2025/11/04 21:49:14.754694866] [ info] [output:doris:doris.0] worker exiting
[2025/11/04 21:49:14.755363757] [ info] [output:doris:doris.0] thread worker #1 stopped
[2025/11/04 21:49:22.343781895] [ info] [output:doris:doris.0] total 0 MB 1102 ROWS, total speed 0 MB/s 55 R/s, last 10 seconds speed 0 MB/s 0 R/s
[2025/11/04 21:49:22.354835509] [debug] [input:tail:tail.0] inode=2517030 removing file name /home/liumx/CProjects/fluent-bit-test/github.log
[2025/11/04 21:49:22.356770665] [ info] [input:tail:tail.0] inotify_fs_remove(): inode=2517030 watch_fd=1
  • Attached Valgrind output that shows no leaks or memory corruption was found
image

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

fluent-bit-docs/pull/1483

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Added an Apache Doris output plugin: configurable endpoint/auth, database/table, JSON formatting and time_key options, optional payload labeling, HTTP(S) delivery with redirect/retry, optional request logging and periodic progress reporting.
  • Tests

    • Added runtime tests validating Doris output formatting (JSON) and time_key handling.
  • Chores

    • Plugin registered in the build and enabled by default on Windows.

@patrick-stephens
Copy link
Collaborator

Does this need additional dependencies?
Do we need to update the packaging builds for the releases for each target (specifically older ones like CentOS 7 if new deps are required)?

@joker-star-l
Copy link
Author

Does this need additional dependencies? Do we need to update the packaging builds for the releases for each target (specifically older ones like CentOS 7 if new deps are required)?

This component has no new additional dependencies.

@joker-star-l
Copy link
Author

joker-star-l commented Oct 31, 2024

It seems that msvc does not have __sync_fetch_and_add function. <stdatomic.h> is not available until after c11. How can I use a general atomic counting method? @patrick-stephens
image

@patrick-stephens
Copy link
Collaborator

It seems that msvc does not have __sync_fetch_and_add function. <stdatomic.h> is not available until after c11. How can I use a general atomic counting method? @patrick-stephens image

Yes, you have to support all legacy targets I'm afraid so the various vendored libraries have atomic support in place. I'm not sure if there is a general way in Fluent Bit to do it @cosmo0920 ?

@cosmo0920
Copy link
Contributor

It seems that msvc does not have __sync_fetch_and_add function. <stdatomic.h> is not available until after c11. How can I use a general atomic counting method? @patrick-stephens image

Yes, you have to support all legacy targets I'm afraid so the various vendored libraries have atomic support in place. I'm not sure if there is a general way in Fluent Bit to do it @cosmo0920 ?

We need to use InterlockedAdd in Windows for the equivalent operation of __sync_fetch_and_add.

@joker-star-l
Copy link
Author

It seems that msvc does not have __sync_fetch_and_add function. <stdatomic.h> is not available until after c11. How can I use a general atomic counting method? @patrick-stephens image

Yes, you have to support all legacy targets I'm afraid so the various vendored libraries have atomic support in place. I'm not sure if there is a general way in Fluent Bit to do it @cosmo0920 ?

We need to use InterlockedAdd in Windows for the equivalent operation of __sync_fetch_and_add.

Thank you both!

Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Signed-off-by: composer <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
plugins/out_doris/doris.c (1)

259-272: CRITICAL: Redirect parsing crashes on missing/malformed Location header.

Past review comments marked this as "Addressed in commits 9b08297 to 41a623c" but the unsafe parsing is still present. This code will segfault if:

  1. Location header is missing (strstr returns NULL at line 261, then line 262 dereferences it)
  2. "@" is absent (line 262: strstr returns NULL, adding 1 gives invalid pointer)
  3. The format doesn't match expectations

This is also brittle for IPv6 addresses and doesn't handle authentication tokens in URLs correctly.

Apply defensive parsing with NULL checks at each step:

         if (c->resp.status == 307) { // redirect
             // example: Location: http://admin:[email protected]:8040/api/d_fb/t_fb/_stream_load?
             char* location = strstr(c->resp.data, "Location:");
+            if (!location) {
+                flb_plg_error(ctx->ins, "307 redirect missing Location header");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            location += 9; // skip "Location:"
+            while (*location == ' ') location++; // skip whitespace
+            
             char* start = strstr(location, "@");
+            if (!start) {
+                flb_plg_error(ctx->ins, "malformed Location header (no @)");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            start += 1;
+            
             char* mid = strstr(start, ":");
+            if (!mid) {
+                flb_plg_error(ctx->ins, "malformed Location header (no port)");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            
             char* end = strstr(mid, "/api");
+            if (!end) {
+                flb_plg_error(ctx->ins, "malformed Location header (no /api)");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            
             char redirect_host[1024] = {0};
+            size_t host_len = mid - start;
+            if (host_len >= sizeof(redirect_host)) {
+                flb_plg_error(ctx->ins, "redirect host too long");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
             memcpy(redirect_host, start, mid - start);
             char redirect_port[10] = {0};
+            size_t port_len = end - (mid + 1);
+            if (port_len >= sizeof(redirect_port)) {
+                flb_plg_error(ctx->ins, "redirect port too long");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
             memcpy(redirect_port, mid + 1, end - (mid + 1));
             
             out_ret = http_put(ctx, redirect_host, atoi(redirect_port), 
                                body, body_len, tag, tag_len, label, label_len, "be");
+cleanup:;
         }

Better yet, consider using Fluent Bit's URL parsing utilities (e.g., flb_utils_url_split) if available for more robust parsing.

🧹 Nitpick comments (3)
plugins/out_doris/doris.h (1)

31-36: Consider documenting atomic access requirement for the running field.

Based on past review comments, the running field is accessed via platform-specific atomic wrapper functions in the implementation. Adding a comment here would help prevent future bugs from direct non-atomic access.

 struct flb_doris_progress_reporter {
+    /* Accessed via atomic operations - do not read/write directly */
     int running;
     size_t total_bytes;
tests/runtime/out_doris.c (1)

88-92: Remove redundant NULL check for res_data.

The res_data parameter is already checked for NULL at lines 74-77. This duplicate check is harmless but unnecessary.

     if (!TEST_CHECK(res_ret == 0)) {
         TEST_MSG("callback ret=%d", res_ret);
     }
-    if (!TEST_CHECK(res_data != NULL)) {
-        TEST_MSG("res_data is NULL");
-        flb_sds_destroy(out_line);
-        return;
-    }
plugins/out_doris/doris.c (1)

45-59: Minor: Document return value semantics mismatch in sync_fetch_and_add.

InterlockedAdd returns the new value (after addition), while __sync_fetch_and_add returns the old value (before addition). This semantic inconsistency doesn't cause bugs currently since the return value is never used (lines 408, 425, 426, 428), but could confuse future developers or cause bugs if the return value is later used.

Consider either:

  1. Documenting this mismatch with a comment, or
  2. Using InterlockedExchangeAdd on Windows to match __sync_fetch_and_add semantics
+/* Note: Return value semantics differ between platforms - not used in this code */
 static inline void sync_fetch_and_add(size_t *dest, size_t value) {
 #ifdef FLB_SYSTEM_WINDOWS
     #ifdef _WIN64
         InterlockedAdd64((LONG64 volatile *) dest, (LONG64) value);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 480885a and 7b2d9ef.

📒 Files selected for processing (10)
  • cmake/plugins_options.cmake (1 hunks)
  • cmake/windows-setup.cmake (1 hunks)
  • plugins/CMakeLists.txt (1 hunks)
  • plugins/out_doris/CMakeLists.txt (1 hunks)
  • plugins/out_doris/doris.c (1 hunks)
  • plugins/out_doris/doris.h (1 hunks)
  • plugins/out_doris/doris_conf.c (1 hunks)
  • plugins/out_doris/doris_conf.h (1 hunks)
  • tests/runtime/CMakeLists.txt (1 hunks)
  • tests/runtime/out_doris.c (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • cmake/plugins_options.cmake
  • plugins/CMakeLists.txt
  • cmake/windows-setup.cmake
  • plugins/out_doris/doris_conf.c
  • plugins/out_doris/doris_conf.h
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-08T11:21:33.975Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 10851
File: include/fluent-bit/flb_simd.h:60-66
Timestamp: 2025-09-08T11:21:33.975Z
Learning: Fluent Bit currently only supports MSVC compiler on Windows, so additional compiler compatibility guards may be unnecessary for Windows-specific code paths.

Applied to files:

  • plugins/out_doris/doris.h
  • plugins/out_doris/doris.c
📚 Learning: 2025-09-04T12:32:46.030Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10825
File: plugins/out_s3/s3.c:0-0
Timestamp: 2025-09-04T12:32:46.030Z
Learning: In Fluent Bit plugins, avoid creating plugin-local config_map entries that duplicate core functionality. The core already provides Retry_Limit parsed into ins->retry_limit, so plugins should use that directly rather than defining their own retry_limit configuration option.

Applied to files:

  • plugins/out_doris/doris.c
🧬 Code graph analysis (2)
tests/runtime/out_doris.c (2)
src/flb_sds.c (1)
  • flb_sds_destroy (389-399)
src/flb_lib.c (10)
  • flb_create (143-225)
  • flb_service_set (652-678)
  • flb_input (266-276)
  • flb_output (279-289)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
  • flb_output_set (520-551)
  • flb_output_set_test (584-615)
  • flb_start (983-994)
  • flb_lib_push (843-870)
plugins/out_doris/doris.c (6)
plugins/out_doris/doris_conf.c (2)
  • flb_doris_conf_create (91-222)
  • flb_doris_conf_destroy (224-241)
src/flb_hash_table.c (4)
  • flb_hash_table_create (99-137)
  • flb_hash_table_destroy (197-215)
  • flb_hash_table_get_ptr (591-603)
  • flb_hash_table_add (401-494)
src/flb_upstream.c (4)
  • flb_upstream_destroy (656-698)
  • flb_upstream_create (290-363)
  • flb_upstream_conn_get (711-844)
  • flb_upstream_conn_release (862-947)
src/flb_http_client.c (5)
  • flb_http_client (814-859)
  • flb_http_add_header (963-995)
  • flb_http_basic_auth (1323-1327)
  • flb_http_do (1572-1632)
  • flb_http_client_destroy (1688-1695)
src/flb_pack.c (2)
  • flb_pack_json (530-535)
  • flb_pack_msgpack_to_json_format (1169-1450)
src/flb_sds.c (1)
  • flb_sds_destroy (389-399)
🔇 Additional comments (12)
plugins/out_doris/CMakeLists.txt (1)

1-6: LGTM! Clean CMake configuration.

The build configuration correctly defines source files and registers the out_doris plugin following the standard Fluent Bit plugin pattern.

tests/runtime/CMakeLists.txt (1)

242-242: LGTM! Test registration follows established pattern.

The Doris runtime test is correctly registered in the output plugins section, consistent with other output plugin tests like Chronicle (line 241).

plugins/out_doris/doris.h (1)

23-29: LGTM! Header is now self-contained with proper includes and forward declarations.

The header correctly includes flb_sds.h for the flb_sds_t typedef and provides forward declarations for all opaque pointer types used in the structs. This addresses previous review concerns about header self-containment.

tests/runtime/out_doris.c (2)

65-103: LGTM! Test callback properly validates output.

The callback correctly:

  • Validates input parameters with TEST_CHECK
  • Searches for expected substrings in the output
  • Properly cleans up with flb_sds_destroy
  • Thread-safely increments the output counter

148-207: LGTM! Well-structured runtime tests.

Both test functions (flb_test_json and flb_test_time_key) properly:

  • Create and configure the test context
  • Set up the Doris output with appropriate parameters
  • Register the formatter test callback to validate output
  • Push test data and verify results
  • Clean up resources

The tests effectively validate JSON formatting and time_key configuration.

Also applies to: 209-265

plugins/out_doris/doris.c (7)

64-87: LGTM! Proper plugin initialization.

The initialization correctly:

  • Initializes TLS for BE pool
  • Creates the Doris configuration context
  • Sets the plugin context
  • Registers HTTP debug callbacks

89-137: LGTM! Worker lifecycle properly manages per-worker BE connection pools.

The worker init/exit callbacks correctly:

  • Create a TLS hash table for each worker's BE connection pool
  • Clean up by destroying all upstreams in the pool before destroying the hash table
  • Properly iterate with mk_list_foreach_safe for safe deletion during iteration

This design cleanly isolates connection pools per worker thread.


273-326: LGTM! Response parsing properly guards against failures.

The HTTP 200 response handling correctly:

  • Bails out early if flb_pack_json fails (line 277-280)
  • Uses goto labels for proper cleanup (free_buf, parse_done)
  • Parses the Status field from the response
  • Treats "Success" and "Publish Timeout" as success
  • Properly cleans up msgpack resources

This addresses previous review concerns about using uninitialized buffers.


356-386: LGTM! Payload composition is straightforward.

The function correctly converts msgpack to JSON format with proper error handling and logging based on the log_request configuration.


388-431: LGTM! Flush callback properly orchestrates delivery and tracks progress.

The flush implementation correctly:

  • Composes the payload from event chunk data
  • Generates unique labels when enabled (with timestamp and UUID)
  • Calls http_put to deliver the data
  • Updates progress counters atomically using the sync_fetch_and_add wrapper
  • Tracks both successful and failed rows appropriately
  • Properly cleans up the payload buffer

442-506: LGTM! Configuration map provides comprehensive options.

The config map exposes all necessary parameters for the Doris output plugin with sensible defaults:

  • Required fields: endpoint_type, user, database, table
  • Optional fields with defaults: password (""), label_prefix ("fluentbit"), time_key ("date")
  • Behavioral controls: log_request (true), log_progress_interval (10)
  • Multiple custom headers supported via FLB_CONFIG_MAP_MULT

529-545: LGTM! Plugin descriptor correctly configured.

The plugin registration specifies:

  • Lifecycle callbacks (init, flush, exit, worker_init, worker_exit)
  • Test formatter for runtime validation
  • Network and TLS capability flags
  • 2 workers for concurrent processing

This properly exposes the Doris output plugin to the Fluent Bit engine.

@joker-star-l
Copy link
Author

@joker-star-l are you able to resolve the conflicts to move this forward?

ready for ci and review

@leonardo-albertovich
Copy link
Contributor

Hey folks, please excuse the intromission but I noticed the __sync_fetch_and_add / InterlockedAdd conversation and I'm having some second thoughts on it.

It seems to me that those are used to track some metrics accross instance workers (that's ok) but I can't see a reason not to use a cmetrics context for it since those are clearly counters and that means we'd be reusing existing code which is good both in terms of dog-fooding and not repeating code.

If using a cmetrics context is not viable for any reason I thing we should at least use the cmt_atomic functions which do not expose single operation addition but it could be easily added which would be much preferable in contrast to adding platform specific code in plugins.

@leonardo-albertovich
Copy link
Contributor

Please don't merge this PR, I've noticed issues that need to be fixed and I'll submit a formal review today.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
plugins/out_doris/doris.c (2)

259-272: CRITICAL: Unsafe redirect parsing with multiple NULL pointer dereference risks.

The redirect handling code has severe safety issues that will cause crashes in common scenarios:

  1. No NULL checks: If the Location: header is missing, location will be NULL and the subsequent strstr(location, "@") will crash. Similarly, missing @, :, or /api will cause NULL pointer dereferences.
  2. Assumes userinfo: The code always looks for @ to skip credentials, but the Location header may not contain userinfo (e.g., http://host:port/api/...).
  3. No bounds checking: The memcpy operations don't validate that mid - start or end - (mid + 1) are positive or fit within the destination buffers.
  4. No IPv6 support: IPv6 addresses in brackets ([::1]) will break the : parsing.
  5. No redirect loop prevention: Recursive calls without a hop counter can infinite-loop if the server returns circular redirects.

Replace the unsafe string parsing with robust header extraction and URL parsing:

         if (c->resp.status == 307) { // redirect
-            // example: Location: http://admin:[email protected]:8040/api/d_fb/t_fb/_stream_load?
-            char* location = strstr(c->resp.data, "Location:");
-            char* start = strstr(location, "@") + 1;
-            char* mid = strstr(start, ":");
-            char* end = strstr(mid, "/api");
-            char redirect_host[1024] = {0};
-            memcpy(redirect_host, start, mid - start);
-            char redirect_port[10] = {0};
-            memcpy(redirect_port, mid + 1, end - (mid + 1));
-            
-            out_ret = http_put(ctx, redirect_host, atoi(redirect_port), 
-                               body, body_len, tag, tag_len, label, label_len, "be");
+            /* Extract Location header safely */
+            char redirect_host[256] = {0};
+            int redirect_port = 0;
+            char *location = strstr(c->resp.data, "Location:");
+            
+            if (!location) {
+                flb_plg_error(ctx->ins, "307 redirect missing Location header");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            
+            location += 9; /* skip "Location:" */
+            while (*location == ' ' || *location == '\t') location++;
+            
+            /* Parse URL: find host and port after scheme and optional userinfo */
+            char *scheme_end = strstr(location, "://");
+            if (!scheme_end) {
+                flb_plg_error(ctx->ins, "invalid Location URL format");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            
+            char *host_start = scheme_end + 3;
+            /* Skip optional userinfo (user:pass@) */
+            char *at_sign = strchr(host_start, '@');
+            char *slash = strchr(host_start, '/');
+            if (at_sign && (!slash || at_sign < slash)) {
+                host_start = at_sign + 1;
+            }
+            
+            /* Extract host and port */
+            char *port_start = NULL;
+            char *host_end = NULL;
+            
+            if (*host_start == '[') { /* IPv6 */
+                host_end = strchr(host_start, ']');
+                if (!host_end) {
+                    flb_plg_error(ctx->ins, "malformed IPv6 address in Location");
+                    out_ret = FLB_RETRY;
+                    goto cleanup;
+                }
+                host_start++; /* skip '[' */
+                if (host_end[1] == ':') {
+                    port_start = host_end + 2;
+                }
+            } else { /* IPv4 or hostname */
+                char *colon = strchr(host_start, ':');
+                slash = strchr(host_start, '/');
+                if (colon && (!slash || colon < slash)) {
+                    host_end = colon;
+                    port_start = colon + 1;
+                } else {
+                    host_end = slash ? slash : host_start + strlen(host_start);
+                }
+            }
+            
+            size_t host_len = host_end - host_start;
+            if (host_len >= sizeof(redirect_host)) {
+                flb_plg_error(ctx->ins, "redirect host too long");
+                out_ret = FLB_RETRY;
+                goto cleanup;
+            }
+            memcpy(redirect_host, host_start, host_len);
+            redirect_host[host_len] = '\0';
+            
+            if (port_start) {
+                redirect_port = atoi(port_start);
+                if (redirect_port <= 0 || redirect_port > 65535) {
+                    flb_plg_error(ctx->ins, "invalid redirect port: %d", redirect_port);
+                    out_ret = FLB_RETRY;
+                    goto cleanup;
+                }
+            } else {
+                redirect_port = 80; /* default HTTP port */
+            }
+            
+            flb_plg_debug(ctx->ins, "redirect to %s:%d", redirect_host, redirect_port);
+            out_ret = http_put(ctx, redirect_host, redirect_port,
+                               body, body_len, tag, tag_len, label, label_len, "be");
+cleanup:;
         }

Additionally, consider adding a redirect hop counter (pass as parameter, max 5) to prevent infinite loops.


45-59: Use cmt_atomic functions instead of platform-specific atomics.

Based on comments from leonardo-albertovich in the PR discussion, you should use the existing cmt_atomic functions from the vendored cmetrics library rather than implementing platform-specific atomic operations here. This avoids spreading #ifdef blocks throughout the plugin code and provides a portable atomic API across all platforms.

Replace the custom sync_fetch_and_add with cmt_atomic APIs:

-#ifdef FLB_SYSTEM_WINDOWS
-#include <windows.h>
-#endif
-
-static inline void sync_fetch_and_add(size_t *dest, size_t value) {
-#ifdef FLB_SYSTEM_WINDOWS
-    #ifdef _WIN64
-        InterlockedAdd64((LONG64 volatile *) dest, (LONG64) value);
-    #else
-        InterlockedAdd((LONG volatile *) dest, (LONG) value);
-    #endif
-#else
-    __sync_fetch_and_add(dest, value);
-#endif
-}
+#include <cmetrics/cmt_atomic.h>

Then update the call sites (lines 408, 425-426, 428) to use cmt_atomic_fetch_add or the appropriate cmt_atomic function.

Based on learnings.

🧹 Nitpick comments (1)
plugins/out_doris/doris.c (1)

225-227: Consider making the "Expect: 100-continue" header configurable.

Based on earlier feedback from yunsur, the Expect: 100-continue header can cause log duplication in Doris group commit mode with Duplicate Key Model due to retry/retransmission behavior. While you indicated this header is necessary for the Doris HTTP stream load API, consider adding a configuration option to allow users to disable it when it causes issues in their specific Doris setup.

Add a boolean config option (e.g., use_100_continue) defaulting to true for backwards compatibility, and conditionally add the header:

     flb_http_add_header(c, "format", 6, "json", 4);
     flb_http_add_header(c, "read_json_by_line", 17, "true", 4);
-    if (strcasecmp(endpoint_type, "fe") == 0) {
+    if (strcasecmp(endpoint_type, "fe") == 0 && ctx->use_100_continue) {
         flb_http_add_header(c, "Expect", 6, "100-continue", 12);
     }
     flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10);

And add to config_map:

{
 FLB_CONFIG_MAP_BOOL, "use_100_continue", "true",
 0, FLB_TRUE, offsetof(struct flb_out_doris, use_100_continue),
 "Use 'Expect: 100-continue' header for FE requests (may cause duplicates in some Doris configurations)"
},
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b2d9ef and 9ff1399.

📒 Files selected for processing (1)
  • plugins/out_doris/doris.c (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-04T12:32:46.030Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10825
File: plugins/out_s3/s3.c:0-0
Timestamp: 2025-09-04T12:32:46.030Z
Learning: In Fluent Bit plugins, avoid creating plugin-local config_map entries that duplicate core functionality. The core already provides Retry_Limit parsed into ins->retry_limit, so plugins should use that directly rather than defining their own retry_limit configuration option.

Applied to files:

  • plugins/out_doris/doris.c
📚 Learning: 2025-09-08T11:21:33.975Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 10851
File: include/fluent-bit/flb_simd.h:60-66
Timestamp: 2025-09-08T11:21:33.975Z
Learning: Fluent Bit currently only supports MSVC compiler on Windows, so additional compiler compatibility guards may be unnecessary for Windows-specific code paths.

Applied to files:

  • plugins/out_doris/doris.c
🧬 Code graph analysis (1)
plugins/out_doris/doris.c (6)
plugins/out_doris/doris_conf.c (2)
  • flb_doris_conf_create (91-222)
  • flb_doris_conf_destroy (224-241)
src/flb_hash_table.c (4)
  • flb_hash_table_create (99-137)
  • flb_hash_table_destroy (197-215)
  • flb_hash_table_get_ptr (591-603)
  • flb_hash_table_add (401-494)
src/flb_upstream.c (4)
  • flb_upstream_destroy (656-698)
  • flb_upstream_create (290-363)
  • flb_upstream_conn_get (711-844)
  • flb_upstream_conn_release (862-947)
src/flb_http_client.c (5)
  • flb_http_client (814-859)
  • flb_http_add_header (963-995)
  • flb_http_basic_auth (1323-1327)
  • flb_http_do (1572-1632)
  • flb_http_client_destroy (1688-1695)
src/flb_pack.c (1)
  • flb_pack_msgpack_to_json_format (1169-1450)
src/flb_sds.c (1)
  • flb_sds_destroy (389-399)

Comment on lines +185 to +196
u = flb_upstream_create(ctx->u->base.config,
host,
port,
ctx->u->base.flags,
ctx->u->base.tls_context);
if (u) {
flb_hash_table_add(be_pool, address, len, u, 0);
} else {
flb_plg_error(ctx->ins, "no doris be connections available to %s:%i",
host, port);
return FLB_RETRY;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix potential upstream leak when hash table insertion fails.

If flb_hash_table_add fails (returns -1), the newly created upstream u is leaked because it's neither stored in the pool nor destroyed. Check the return value and destroy the upstream on failure.

Apply this fix:

             u = flb_upstream_create(ctx->u->base.config,
                                     host,
                                     port,
                                     ctx->u->base.flags,
                                     ctx->u->base.tls_context);
             if (u) {
-                flb_hash_table_add(be_pool, address, len, u, 0);
+                ret = flb_hash_table_add(be_pool, address, len, u, 0);
+                if (ret == -1) {
+                    flb_upstream_destroy(u);
+                    flb_plg_error(ctx->ins, "failed to add upstream to BE pool for %s:%i",
+                                  host, port);
+                    return FLB_RETRY;
+                }
             } else {
                 flb_plg_error(ctx->ins, "no doris be connections available to %s:%i",
                               host, port);
                 return FLB_RETRY;
             }
🤖 Prompt for AI Agents
In plugins/out_doris/doris.c around lines 185 to 196, the code creates a new
upstream u and calls flb_hash_table_add without checking its return value, which
can leak u on insertion failure; update the code to check flb_hash_table_add's
return value, and if it returns -1, call flb_upstream_destroy(u) to free the
upstream, log the error, and return FLB_RETRY (instead of leaving u alive),
otherwise proceed as before when insertion succeeds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-required ok-package-test Run PR packaging tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants