Skip to content

fix(es): key existing documents on _id instead of _source.id - #4523

Merged
Jan-Kazlouski-elastic merged 2 commits into
elastic:mainfrom
ShivamSharma43:fix-2776-use-es-id-for-existing-docs
Oct 6, 2026
Merged

Jan-Kazlouski-elastic merged 2 commits into
elastic:mainfrom
ShivamSharma43:fix-2776-use-es-id-for-existing-docs

Conversation

@ShivamSharma43

Copy link
Copy Markdown
Contributor

Closes #2776

When the sink loads the documents already in an index, yield_existing_documents_metadata keyed each one on _source.id and only fell back to _id when id was missing. Everything that consumes that map treats the key as the Elasticsearch _id: get_docs and get_access_control_docs look up each incoming doc by the _id they are about to write, and enqueue_docs_to_delete issues bulk deletes by _id.

The connector itself always writes id equal to _id, so the two only diverge when something else changes id, for example an ingest pipeline. When they do, no incoming doc matches an existing one: every doc is counted as a create, skip_unchanged_documents never skips anything, and the deletes at the end of a full sync target _id values that don't exist, so docs removed from the source are left in the index.

This change keys the map on _id and drops id from the scan's _source, since it is no longer read. The id field the connector writes into documents is unchanged.

This changes behaviour for indices already written where id differs from _id. The first full or access control sync after this change will delete documents that were orphaned by the old behaviour, so document counts may drop. Existing docs will be counted as updates rather than creates, and unchanged docs will be skipped when skip_unchanged_documents is enabled. Indices where id equals _id, or where id is absent, are unaffected.

Tests: test_management_client.py gets a case where _source.id differs from _id and asserts the yielded keys are the _ids. test_sink.py gets a case that runs get_docs through the real yield_existing_documents_metadata (with async_scan mocked) and asserts the matching doc is queued as an update and the stale doc is deleted by its _id. Both fail without the fix.

Checklists

Pre-Review Checklist

  • this PR does NOT contain credentials of any kind, such as API keys or username/passwords (double check config.yml.example)
  • this PR has a meaningful title
  • this PR links to all relevant github issues that it fixes or partially addresses
  • Covered the changes with automated tests
  • Tested the changes locally (ran make lint and make test; not tested against a live cluster)
  • Added a label for each target release version (example: v7.13.2, v7.14.0, v8.0.0)
  • For bugfixes: backport safely to all minor branches still receiving patch releases

Release Note

Fixes syncs failing to delete stale documents, and treating existing documents as new, when an ingest pipeline changes a document's id field so that it no longer matches its _id.

Generated with Claude Code

@ShivamSharma43
ShivamSharma43 requested a review from a team as a code owner September 27, 2026 12:15
Copilot AI lite review requested due to automatic review settings September 27, 2026 12:15

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cla-checker-service

cla-checker-service Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

💚 CLA has been signed

yield_existing_documents_metadata preferred _source.id over _id, but
every consumer in the sink matches incoming docs and issues deletes by
_id. When the two differ (e.g. an ingest pipeline rewrote id), existing
docs were never matched and stale docs were never deleted.

Closes elastic#2776

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Jan-Kazlouski-elastic

Copy link
Copy Markdown
Contributor

buildkite test this

@Jan-Kazlouski-elastic

Copy link
Copy Markdown
Contributor

Thank you for your contribution @ShivamSharma43
Taking a look.

@Jan-Kazlouski-elastic

Copy link
Copy Markdown
Contributor

buildkite test this

@Jan-Kazlouski-elastic Jan-Kazlouski-elastic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

💚 Backport PR(s) successfully created

Status Branch Result
✅ 8.19 #4572
✅ 9.5 #4573
✅ 9.4 #4574

The backport PRs will be merged automatically after passing CI.

Jan-Kazlouski-elastic added a commit that referenced this pull request Oct 7, 2026
…4523) (#4573)

Backports the following commits to 9.5:
 - fix(es): key existing documents on _id instead of _source.id (#4523)

Co-authored-by: Shivam Sharma <192242476+ShivamSharma43@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jan-Kazlouski-elastic <jan.kazlouski@elastic.co>
Jan-Kazlouski-elastic added a commit that referenced this pull request Oct 7, 2026
…4523) (#4574)

Backports the following commits to 9.4:
 - fix(es): key existing documents on _id instead of _source.id (#4523)

Co-authored-by: Shivam Sharma <192242476+ShivamSharma43@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jan-Kazlouski-elastic <jan.kazlouski@elastic.co>
Jan-Kazlouski-elastic added a commit that referenced this pull request Oct 7, 2026
…4523) (#4572)

Backports the following commits to 8.19:
 - fix(es): key existing documents on _id instead of _source.id (#4523)

Co-authored-by: Shivam Sharma <192242476+ShivamSharma43@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jan-Kazlouski-elastic <jan.kazlouski@elastic.co>
Jan-Kazlouski-elastic pushed a commit that referenced this pull request Oct 7, 2026
## Part of #2990

#2989 removed `_update_native_connector_authentication()`, the only
place the framework read a connector secret, and set
`native_connector_api_keys_enabled` to False. Several pieces it relied
on were left behind with no remaining callers. This PR removes those:

- `ESManagementClient.get_connector_secret()`
- the `Connector.api_key_secret_id` property
- `ApiKeyNotFoundError` in `sync_job_runner.py`
- `Features.native_connector_api_keys_enabled()` and the
`Features.NATIVE_CONNECTOR_API_KEYS` constant in `connectors_sdk`

Their tests are removed with them, along with a leftover
`native_connector_api_keys_enabled` mock in `test_sync_job_runner.py`.

Nothing here changes what is written to Elasticsearch or what Kibana
sees. The following are deliberately left in place because removing them
would be observable outside the framework, and are for a separate PR if
that is wanted:

- the `native_connector_api_keys` entry in `BaseDataSource.features()`,
which is written into the connector doc
- `create_connector_secret()`, which `connectors connector create
--native` still uses to store an API key and set `api_key_secret_id` on
the connector doc
- `api_key_secret_id` in `docs/CONNECTOR_PROTOCOL.md`

`Features.native_connector_api_keys_enabled()` and
`NATIVE_CONNECTOR_API_KEYS` are public in the published `connectors_sdk`
package. Nothing in this repo uses them, but external code calling them
would break.

Tests: `make lint` and `make test` pass in both `app/connectors_service`
(2504 passed, 92.01% coverage) and `libs/connectors_sdk` (343 passed,
84.21% coverage).

## Checklists

#### Pre-Review Checklist
- [x] this PR does NOT contain credentials of any kind, such as API keys
or username/passwords (double check `config.yml.example`)
- [x] this PR has a meaningful title
- [x] this PR links to all relevant github issues that it fixes or
partially addresses
- [x] Covered the changes with automated tests
- [ ] Tested the changes locally (ran `make lint` and `make test`; not
tested against a live cluster)

## Related Pull Requests

- #2989, which removed the code path these were used by.
- #4523 adds a test next to the ones removed here in
`test_management_client.py`, so whichever merges second will need a
small rebase.

Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

Connectors interchangeably use id and _id

3 participants