-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Batched per-db _index_info endpoint #6103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nickva
wants to merge
1
commit into
main
Choose a base branch
from
index-info-2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,5 +44,6 @@ Where ``{db}`` is the name of any database. | |
| changes | ||
| compact | ||
| cleanup | ||
| index_info | ||
| security | ||
| misc | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,224 @@ | ||
| .. Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
| .. use this file except in compliance with the License. You may obtain a copy of | ||
| .. the License at | ||
| .. | ||
| .. http://www.apache.org/licenses/LICENSE-2.0 | ||
| .. | ||
| .. Unless required by applicable law or agreed to in writing, software | ||
| .. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
| .. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
| .. License for the specific language governing permissions and limitations under | ||
| .. the License. | ||
|
|
||
| .. _api/db/index_info: | ||
|
|
||
| ===================== | ||
| ``/{db}/_index_info`` | ||
| ===================== | ||
|
|
||
| .. versionadded:: 3.6 | ||
|
|
||
| .. http:get:: /{db}/_index_info | ||
| :synopsis: Returns status all the indexes in the database | ||
|
|
||
| Index info objects have the same fields as the ones returned by | ||
| :get:`/{db}/_design/{ddoc}/_info`, | ||
| :get:`/{db}/_design/{ddoc}/_search_info/{index}` and | ||
| :get:`/{db}/_design/{ddoc}/_nouveau_info/{index}`, with an | ||
| ``updates_pending`` object with the index build pending bounds across all | ||
| copies of the database. See :ref:`api/db/index_info/structure`. | ||
|
|
||
| This endpoint may be used when one needs to know whether a database's | ||
| indexes are fully built, for example before switching traffic to a replica. | ||
|
|
||
| :param db: Database name | ||
| :query string type: Filter response to the given index types. Can be one of | ||
| these values: ``view``, ``search`` and ``nouveau``, comma separated. | ||
| *Optional*, default: all types. | ||
| :<header Accept: - :mimetype:`application/json` | ||
| - :mimetype:`text/plain` | ||
| :>header Content-Type: - :mimetype:`application/json` | ||
| - :mimetype:`text/plain; charset=utf-8` | ||
| :>json string name: Database name | ||
| :>json number copies_expected: The number of shard copies of the database | ||
| (Q*N) Compare with the ``copies`` count of each ``updates_pending`` | ||
| object. | ||
| :>json object indexes: Index information keyed by design doc ID. | ||
| See :ref:`api/db/index_info/structure`. | ||
| :code 200: Request completed successfully | ||
| :code 400: Invalid database name or ``type`` value | ||
| :code 401: Unauthorized request to a protected API | ||
| :code 403: Insufficient permissions / :ref:`Too many requests with invalid credentials<error/403>` | ||
| :code 404: Database doesn't exist | ||
|
|
||
| **Request**: | ||
|
|
||
| .. code-block:: http | ||
|
|
||
| GET /recipes/_index_info HTTP/1.1 | ||
| Accept: application/json | ||
| Host: localhost:5984 | ||
|
|
||
| **Response**: | ||
|
|
||
| .. code-block:: http | ||
|
|
||
| HTTP/1.1 200 OK | ||
| Cache-Control: must-revalidate | ||
| Content-Type: application/json | ||
| Date: Mon, 01 Sep 2025 15:42:11 GMT | ||
| Server: CouchDB (Erlang/OTP) | ||
|
|
||
| { | ||
| "name": "recipes", | ||
| "copies_expected": 6, | ||
| "indexes": { | ||
| "_design/cookbook": { | ||
| "view_index": { | ||
| "collator_versions": [ | ||
| "153.136" | ||
| ], | ||
| "compact_running": false, | ||
| "language": "javascript", | ||
| "purge_seq": 0, | ||
| "signature": "a6d97b0199e54a1eb56e4becb1322587", | ||
| "sizes": { | ||
| "active": 1825, | ||
| "external": 1355, | ||
| "file": 16750 | ||
| }, | ||
| "update_seq": 54, | ||
| "updater_running": false, | ||
| "waiting_clients": 0, | ||
| "waiting_commit": false, | ||
| "updates_pending": { | ||
| "minimum": 0, | ||
| "maximum": 0, | ||
| "copies": 6 | ||
| } | ||
| }, | ||
| "search_indexes": { | ||
| "ingredients": { | ||
| "committed_seq": 54, | ||
| "disk_size": 3960, | ||
| "doc_count": 50, | ||
| "doc_del_count": 0, | ||
| "pending_seq": 54, | ||
| "signature": "0b4ba635d5eb4fcbb2f6c9c2247460ec", | ||
| "updates_pending": { | ||
| "minimum": 0, | ||
| "maximum": 0, | ||
| "copies": 6 | ||
| } | ||
| } | ||
| }, | ||
| "nouveau_indexes": { | ||
| "ingredients": { | ||
| "disk_size": 6324, | ||
| "num_docs": 50, | ||
| "purge_seq": 0, | ||
| "signature": "ea87fe8f9517403691850f51d0a1ce3e5afaf89347204dd79430252a0591e503", | ||
| "update_seq": 54, | ||
| "updates_pending": { | ||
| "minimum": 0, | ||
| "maximum": 0, | ||
| "copies": 6 | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "_design/8c2a4caf8ea1b581ac43a062fd43a876dee1382d": { | ||
| "view_index": { | ||
| "collator_versions": [ | ||
| "153.136" | ||
| ], | ||
| "compact_running": false, | ||
| "language": "query", | ||
| "purge_seq": 0, | ||
| "signature": "b77547252cb8b19ff12831973b576c0f", | ||
| "sizes": { | ||
| "active": 0, | ||
| "external": 10, | ||
| "file": 102 | ||
| }, | ||
| "update_seq": 0, | ||
| "updater_running": false, | ||
| "waiting_clients": 0, | ||
| "waiting_commit": false, | ||
| "updates_pending": { | ||
| "minimum": 54, | ||
| "maximum": 54, | ||
| "copies": 6 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| In this example the ``cookbook`` design document has a view group, a | ||
| search index and a nouveau index, all fully built on all six copies. The | ||
| second design document is a Mango index which has not been built on | ||
| any copy yet: every copy is 54 updates behind. | ||
|
|
||
| .. _api/db/index_info/structure: | ||
|
|
||
| Index Information | ||
| ================= | ||
|
|
||
| The ``indexes`` object of the :get:`/{db}/_index_info` response has one entry | ||
| per design document with at least one index, keyed by design doc ID. Each entry | ||
| may contain: | ||
|
|
||
| * **view_index** (*object*): The design doc's view group, with the fields | ||
| described in :ref:`api/ddoc/view_index_info` and ``updates_pending``. A design | ||
| document has one view group for all of its views. | ||
|
|
||
| * **search_indexes** (*object*): One entry per search index of the design | ||
| document, keyed by index name, with the fields of the ``search_index`` object | ||
| returned by :get:`/{db}/_design/{ddoc}/_search_info/{index}` plus | ||
| ``updates_pending``. | ||
| * **nouveau_indexes** (*object*): One entry per nouveau index of the design | ||
| document, keyed by index name, with the fields of the ``search_index`` object | ||
| returned by :get:`/{db}/_design/{ddoc}/_nouveau_info/{index}` plus | ||
| ``updates_pending``. | ||
|
|
||
| Pending stats | ||
| -------------- | ||
|
|
||
| Every index object contains an ``updates_pending`` object which shows the | ||
| number of pending changes for that index. | ||
|
|
||
| * **minimum** (*number*): Backlog of the most up to date copy of each | ||
| range. ``0`` means at least one fully built copy of the index exists for | ||
| every range. | ||
| * **maximum** (*number*): Backlog of the least up to date copy of each range. | ||
| ``0`` means the index is fully built on all returned shard copies. | ||
| * **copies** (*number*): The number of shard copies with returned a response. | ||
| Copies which are unreachable, in maintenance mode, or which did not answer | ||
| before the request timed out are skipped. When this is much smaller than | ||
| ``copies_expected`` the bounds are partial and ``maximum`` may underestimate | ||
| the true pending backlog. | ||
|
|
||
| Errors | ||
| ------ | ||
|
|
||
| If an index cannot be inspected it will return an error for that index only. | ||
| For example is Closeau is not available search indexes will return: | ||
|
|
||
| .. code-block:: javascript | ||
|
|
||
| "search_indexes": { | ||
| "ingredients": { | ||
| "error": "service unavailable", | ||
| "reason": "Search is not available" | ||
| } | ||
| } | ||
|
|
||
| Invalid ``type`` values return a ``400 Bad Request``: | ||
|
|
||
| .. code-block:: javascript | ||
|
|
||
| { | ||
| "error": "query_parse_error", | ||
| "reason": "Invalid index type: foo. Must be view, search or nouveau" | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this example correct?
It suggests that the API will list the same error for each search index in defined in the ddoc if search is unavailable. I suppose this is covering the case of other possible errors too? I'm trying to understand if the idea is to present the error/reason at the top-level or for each defined index.
To my mind the problem with this approach to errors is that it makes reusing existing models of the search (or view or query) index information impossible because it introduces new
errorandreasonfields into those models (that I think are invalid in the existing case).Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's for the case when we couldn't get any information for any copy of the index on any shards. It would be either a cluster is very unhealthy (really partitioned) or an index type is disabled. If we get at least some copies as a response we'll return those stats with a
copiesvalues.For the search case or nouveau case it makes sense to consider those services disabled as a real possibility. And yeah, it would list that error for any search index and for every nouveau index if we have those defined but index service is not available.
I guess we could hide those index types if the services are disabled but then we'd be hiding indexes form users and that could be confusing, too. If we do hide them if index types are disabled we'd still have to see what to return if no copies return an info object. We could crash the whole response, or maybe remove all the fields except
"copies": 0perhaps?But that seems a kind of odd too...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it a bit more another pain point with the proposed approach is that the key for view indexes is dynamic (the ddoc name) which makes it harder to model the response type vs the static keys for
search_indexesandnouveau_indexes.How about something like:
I think this kind of structure would make the types from the existing info endpoints reusable under the
view_indexandsearch_indexkeys as well as making room for success/error information.The existing info responses are objects pairing e.g. a
nameandview_indexso potentially even better alignment to those would be possible by using arrays rather than dictionaries e.g.but that gets us back to the place where those existing info responses don't have
ok/error/reason. Another way around that would be splitting success/error at a higher level e.g.Food for thought anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I should also have said re-using the existing structures depends on
updates_pendingmatching in both places, the existing one forview_indexhasminimum,preferred,total- IIUCmaximumandcopiesare new and not renames of these existing values, but is there any reason not to include them in the existing endpoints so that the schema is the same between the*_infoand this bulk version?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I like using arrays rather than dictionaries a bit better. Excellent point @ricellis
The issue is with the data they return today. It's simply broken. We don't actually wait for all the shards in those endpoints to properly report min/max values. We could fix those I suppose, too but that's a slightly bigger change.
I'll try to get a list of objects shape first going and we can see how it looks