Skip to content

in_forward: batch Forward mode worker ingress - #12163

Merged
edsiper merged 3 commits into
masterfrom
in-forward-batch-worker-ingress
Jul 29, 2026
Merged

in_forward: batch Forward mode worker ingress#12163
edsiper merged 3 commits into
masterfrom
in-forward-batch-worker-ingress

Conversation

@edsiper

@edsiper edsiper commented Jul 27, 2026

Copy link
Copy Markdown
Member

Problem

Forward array mode processed and submitted every record independently. With listener workers, a 100-record Forward frame therefore produced 100 deferred-ingress allocations, payload copies, queue lock operations, and main-thread append calls. The listener threads were balanced, but the main ingestion thread saturated and four-worker throughput barely exceeded one worker.

Change

  • Encode all entries from one Forward-mode frame into the connection's reusable log encoder.
  • Submit the encoded frame through the ingress queue once.
  • Apply TCP backpressure while the worker ingress queue is temporarily full instead of dropping the claimed batch and resetting the connection.
  • Preserve existing valid-prefix behavior for malformed frames.
  • Preserve chunk ACK ordering: ACK is sent only after successful ingestion.

Message mode, PackedForward, gzip/zstd PackedForward, TLS, Unix sockets, tags, metadata, and secure-forward negotiation remain on their existing paths.

Performance

On the same 10-million-record, 16-client benchmark with 100 records per Forward frame:

  • Fluent Bit 5.0, one worker: 476,161 end-to-end records/s, 19.52 CPU seconds.
  • Fluent Bit 5.1, four workers with this change: 2,498,897 end-to-end records/s, 7.20 CPU seconds.

That is a 5.25x throughput increase while using 63% less total CPU time for the workload.

Validation

  • Full build: cmake --build build -j8
  • Selected Forward integration matrix covering Message, Forward, PackedForward, gzip, zstd, ACK, TLS, Unix socket, secure-forward, and workers: 13 passed
  • Same matrix with VALGRIND=1 VALGRIND_STRICT=1: 13 passed, zero Valgrind errors
  • Final batching and malformed-prefix tests: 2 passed normally
  • Final batching and malformed-prefix tests with strict Valgrind: 2 passed, zero Valgrind errors
  • GITHUB_EVENT_NAME=pull_request GITHUB_BASE_REF=master python .github/scripts/commit_prefix_check.py
  • git diff --check

Summary by CodeRabbit

  • Improvements
    • Enhanced forward-mode processing for whole frames with improved encode/ingest behavior and safer handling of partial results.
    • Improved handling of large forwarded payloads using chunking/batching, including respect for ingress queue byte limits.
    • Improved reliability of forwarded event acknowledgement behavior.
  • Bug Fixes
    • Fixed edge cases to preserve valid first records when encoding/decoding fails.
  • Tests
    • Added integration tests covering large forward-mode batches, ingress queue byte-limit behavior, and valid-prefix preservation.
    • Added a dedicated tiny ingress-queue scenario configuration for the above coverage.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70ce6c6b-e40f-4a9d-b38e-fd3ca8db9eda

📥 Commits

Reviewing files that changed from the base of the PR and between 6e8119e and 0a847d9.

📒 Files selected for processing (3)
  • plugins/in_forward/fw_prot.c
  • tests/integration/scenarios/in_forward/config/in_forward_workers_tiny_ingress_queue.yaml
  • tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/integration/scenarios/in_forward/config/in_forward_workers_tiny_ingress_queue.yaml
  • tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
  • plugins/in_forward/fw_prot.c

📝 Walkthrough

Walkthrough

Forward-mode processing now encodes entries through a queue-aware batch pathway, preserves partial output on malformed entries, delegates complete arrays from frame parsing, and adds worker integration coverage for large batches, ingress queue limits, acknowledgements, ordering, and valid-prefix handling.

Changes

Forward-mode batch processing

Layer / File(s) Summary
Entry encoding and queue-aware ingestion
plugins/in_forward/fw_prot.c
Forward-mode entries are decoded into the log encoder, accumulated output is ingested in queue-bounded batches, and partial-frame output is preserved when encoding fails.
Frame delegation and worker validation
plugins/in_forward/fw_prot.c, tests/integration/scenarios/in_forward/config/in_forward_workers_tiny_ingress_queue.yaml, tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
Frame processing delegates complete arrays to the refactored processor, while worker tests validate partial reads, batch ordering, acknowledgements, ingress queue byte limits, and valid-prefix handling.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant fw_prot_process
  participant fw_process_forward_mode
  participant fw_encode_forward_mode_entry
  participant fw_ingest_forward_mode_batch
  fw_prot_process->>fw_process_forward_mode: pass complete Forward-mode array
  fw_process_forward_mode->>fw_encode_forward_mode_entry: encode entries
  fw_process_forward_mode->>fw_ingest_forward_mode_batch: submit encoded batch
  fw_ingest_forward_mode_batch-->>fw_prot_process: return processing result
Loading

Possibly related PRs

Suggested reviewers: cosmo0920

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: batching Forward-mode worker ingress in in_forward.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch in-forward-batch-worker-ingress

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79fbda3930

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1011 to +1012
(ins->ingress_queue_byte_limit == 0 ||
length <= ins->ingress_queue_byte_limit));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split batches before applying the ingress byte limit

When listener workers are enabled and Mem_Buf_Limit or http_server.ingress_queue_byte_limit is smaller than the encoded Forward frame—even though every constituent record fits—flb_input_ingress_enqueue() always returns FLB_INPUT_INGRESS_BUSY because the event itself exceeds the limit; this condition then declines to retry, and the caller closes the connection without an ACK or ingesting any records. Before this change, the records were queued separately and the same valid frame succeeded, so oversized frames need to be split at record boundaries before submission.

AGENTS.md reference: AGENTS.md:L230-L236

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/integration/scenarios/in_forward/tests/test_in_forward_001.py (1)

874-906: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strengthen the assertion to catch duplicate ingestion.

This test validates ordering/content of the first 256 records but never asserts the total count. Since this test exists specifically to validate the new batch-ingest path (and the batch path includes a busy-retry loop around ingestion), also assert len(records) == total_records to catch any accidental double-ingestion.

✅ Proposed addition
     assert ack == {"ack": chunk}
+    assert len(records) == total_records
     assert [record["value"] for record in records[:total_records]] == list(
         range(total_records)
     )

As per path instructions for tests/**: "Add or update tests for behavior changes, especially protocol parsing and encoder/decoder paths."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration/scenarios/in_forward/tests/test_in_forward_001.py` around
lines 874 - 906, Strengthen test_in_forward_workers_forward_mode_batch by
asserting that the total number of returned records equals total_records, in
addition to the existing ordering/content assertion. Place the count assertion
after records are collected so duplicate ingestion is detected.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/in_forward/fw_prot.c`:
- Around line 985-989: Update the warning in the result-checking block of the
forward-processing flow to avoid labeling every failure as an event decoder
failure. Use wording that accurately covers failures returned by both the
decoder and the encoder operations, while preserving the existing result value
and return behavior.

---

Nitpick comments:
In `@tests/integration/scenarios/in_forward/tests/test_in_forward_001.py`:
- Around line 874-906: Strengthen test_in_forward_workers_forward_mode_batch by
asserting that the total number of returned records equals total_records, in
addition to the existing ordering/content assertion. Place the count assertion
after records are collected so duplicate ingestion is detected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d0d3dc8-c1be-4217-a551-242728178a03

📥 Commits

Reviewing files that changed from the base of the PR and between cb7256c and 79fbda3.

📒 Files selected for processing (2)
  • plugins/in_forward/fw_prot.c
  • tests/integration/scenarios/in_forward/tests/test_in_forward_001.py

Comment thread plugins/in_forward/fw_prot.c

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/integration/scenarios/in_forward/tests/test_in_forward_001.py`:
- Around line 1050-1055: Update the test around service.wait_for_record_count
and the final assertion to synchronize processing after the malformed entry,
then verify the service’s final record collection contains exactly one record.
Preserve the existing assertion that the surviving record’s message is
"valid-prefix", ensuring the malformed [TEST_TS] entry cannot produce an
additional record.
- Around line 988-993: Update the shared _recv_msgpack_value() helper used by
both tests to accumulate TCP reads in a buffer and continue reading until a
complete MessagePack value can be decoded, rather than assuming one recv returns
the full ACK. Preserve the existing decoded-value return behavior and timeout
handling while correctly handling fragmented responses.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: abd86463-64cb-4ee2-ad0f-a07bb2b94baa

📥 Commits

Reviewing files that changed from the base of the PR and between 79fbda3 and 97789a5.

📒 Files selected for processing (3)
  • plugins/in_forward/fw_prot.c
  • tests/integration/scenarios/in_forward/config/in_forward_workers_tiny_ingress_queue.yaml
  • tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/in_forward/fw_prot.c

Comment thread tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
Comment thread tests/integration/scenarios/in_forward/tests/test_in_forward_001.py
edsiper added 3 commits July 29, 2026 11:44
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
@edsiper
edsiper force-pushed the in-forward-batch-worker-ingress branch from 6e8119e to 0a847d9 Compare July 29, 2026 17:47
@edsiper
edsiper merged commit 39ee78e into master Jul 29, 2026
52 of 53 checks passed
@edsiper
edsiper deleted the in-forward-batch-worker-ingress branch July 29, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants