Skip to content

Feat/hunspell ref path - #20792

Closed
shayush622 wants to merge 11 commits into
opensearch-project:mainfrom
shayush622:feat/hunspell-ref-path
Closed

Feat/hunspell ref path#20792
shayush622 wants to merge 11 commits into
opensearch-project:mainfrom
shayush622:feat/hunspell-ref-path

Conversation

@shayush622

Copy link
Copy Markdown
Contributor
  • Add INDEX_REF_PATH_SETTING for package-based hunspell dictionaries
  • Add RestHunspellCacheInvalidateAction for cache invalidation endpoint
  • Update HunspellService with cache management methods
  • Add ref_path validation in MetadataCreateIndexService

Description

This PR adds support for loading Hunspell dictionaries from package-based directories using a new ref_path parameter, enabling multi-tenant dictionary isolation and hot-reload capabilities.

Related Issues

Resolves #[20712]
Link to #20712 (comment).

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

shayush622 and others added 7 commits February 27, 2026 03:29
- Add INDEX_REF_PATH_SETTING for package-based hunspell dictionaries
- Add RestHunspellCacheInvalidateAction for cache invalidation endpoint
- Update HunspellService with cache management methods
- Add ref_path validation in MetadataCreateIndexService

Signed-off-by: shayush622 <ayush5267@gmail.com>
- Add ref_path parameter to hunspell token filter for package-based dictionaries
- Load dictionaries from config/packages/{packageId}/hunspell/{locale}/
- Add cache invalidation REST API endpoints:
  - GET /_hunspell/cache (view cached dictionaries)
  - POST /_hunspell/cache/_invalidate (invalidate by package_id, locale, or cache_key)
  - POST /_hunspell/cache/_invalidate_all (clear all cached dictionaries)
- Add TransportAction with cluster:admin/hunspell/cache/clear permission
- Add path traversal security validation for packageId and locale
- Add updateable flag support for hot-reload via _reload_search_analyzers
- Add comprehensive test coverage for HunspellTokenFilterFactory and REST endpoint
- Remove unused index-level ref_path setting

Addresses PR feedback:
- Removed mise.toml from commit (local dev config)
- Added TransportAction authorization pattern
- Added 21 unit tests for REST endpoint
- Fixed security validation for path traversal attacks
- Documented race condition in invalidateAllDictionaries

Signed-off-by: shayush622 <ayush5267@gmail.com>
- Add ref_path parameter for package-based dictionary loading
- Load from config/packages/{packageId}/hunspell/{locale}/
- Add cache invalidation REST API (GET/POST /_hunspell/cache/_invalidate)
- Add TransportAction with cluster:admin permission
- Add comprehensive security validation (path traversal, separators, cache-key injection)
- Add updateable flag for hot-reload via _reload_search_analyzers
- Add comprehensive test coverage

PR feedback addressed:
- Stricter validate() to reject conflicting params
- Path traversal checks now use config/packages/ as base
- ref_path/locale validation rejects ., .., /, \, : characters

Signed-off-by: shayush622 <ayush5267@gmail.com>
Signed-off-by: shayush622 <ayush5267@gmail.com>
- Add ref_path parameter for package-based dictionary loading
- Load from config/packages/{packageId}/hunspell/{locale}/
- Add cache info API: GET /_hunspell/cache (cluster:monitor/hunspell/cache)
- Add cache invalidation API: POST /_hunspell/cache/_invalidate (cluster:admin/hunspell/cache/invalidate)
- Support invalidation by package_id, locale, cache_key, or invalidate_all
- Add security validation (path traversal, separator injection, null bytes)
- Add updateable flag for hot-reload via _reload_search_analyzers
- Use Strings.hasText() and Strings.isNullOrEmpty() for validation consistency
- Consistent response schema with all fields always present
- Add unit tests, REST handler tests, and integration tests

Signed-off-by: shayush622 <ayush5267@gmail.com>
@github-actions

github-actions Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit 3917262.

'Diff too large, requires skip by maintainers after manual review'


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@github-actions

github-actions Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 33f4a54

@github-actions

github-actions Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 33f4a54: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@shayush622
shayush622 force-pushed the feat/hunspell-ref-path branch from 33f4a54 to dbc150a Compare March 9, 2026 08:29
@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit dbc150a

@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

❌ Gradle check result for dbc150a: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@cwperks

cwperks commented Mar 9, 2026

Copy link
Copy Markdown
Member

Not sure if its related to the changes in this PR, but this is showing backwards compatibility failures:

» ERROR][o.o.g.r.RemoteClusterStateService] [v2.19.5-remote-2] Failure in downloading full cluster state. 
»  org.opensearch.gateway.remote.RemoteStateTransferException: Exception during reading cluster state from remote
»  	at org.opensearch.gateway.remote.RemoteClusterStateService.readClusterStateInParallel(RemoteClusterStateService.java:1391)
»  	at org.opensearch.gateway.remote.RemoteClusterStateService.getClusterStateForManifest(RemoteClusterStateService.java:1497)
»  	at org.opensearch.cluster.coordination.PublicationTransportHandler.handleIncomingRemotePublishRequest(PublicationTransportHandler.java:269)
»  	at org.opensearch.cluster.coordination.PublicationTransportHandler.lambda$new$1(PublicationTransportHandler.java:136)
»  	at org.opensearch.wlm.WorkloadManagementTransportInterceptor$RequestHandler.messageReceived(WorkloadManagementTransportInterceptor.java:63)
»  	at org.opensearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:108)
»  	at org.opensearch.transport.NativeMessageHandler$RequestHandler.doRun(NativeMessageHandler.java:487)
»  	at org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:1014)
»  	at org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)
»  	at java.****/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
»  	at java.****/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
»  	at java.****/java.lang.Thread.run(Thread.java:1583)
»  	Suppressed: org.opensearch.gateway.remote.RemoteStateTransferException: Download failed for nodes
»  		at org.opensearch.gateway.remote.RemoteClusterStateAttributesManager.lambda$getWrappedReadListener$3(RemoteClusterStateAttributesManager.java:103)
»  		at org.opensearch.core.action.ActionListener$1.onFailure(ActionListener.java:90)
»  		at org.opensearch.common.remote.RemoteWriteableEntityBlobStore.lambda$readAsync$0(RemoteWriteableEntityBlobStore.java:87)
»  		at org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:955)
»  		... 3 more
»  	Caused by: java.lang.IllegalStateException: unexpected byte [0x1d]
»  		at org.opensearch.core.common.io.stream.StreamInput.readBoolean(StreamInput.java:596)
»  		at org.opensearch.core.common.io.stream.StreamInput.readBoolean(StreamInput.java:586)
»  		at org.opensearch.cluster.node.DiscoveryNode.<init>(DiscoveryNode.java:344)
»  		at org.opensearch.cluster.node.DiscoveryNodes.readFrom(DiscoveryNodes.java:777)
»  		at org.opensearch.gateway.remote.model.RemoteDiscoveryNodes.lambda$static$0(RemoteDiscoveryNodes.java:37)
»  		at org.opensearch.repositories.blobstore.ChecksumWritableBlobStoreFormat.deserialize(ChecksumWritableBlobStoreFormat.java:105)
»  		at org.opensearch.gateway.remote.model.RemoteDiscoveryNodes.deserialize(RemoteDiscoveryNodes.java:101)
»  		at org.opensearch.gateway.remote.model.RemoteDiscoveryNodes.deserialize(RemoteDiscoveryNodes.java:32)
»  		at org.opensearch.common.remote.RemoteWriteableEntityBlobStore.read(RemoteWriteableEntityBlobStore.java:77)
»  		at org.opensearch.common.remote.RemoteWriteableEntityBlobStore.lambda$readAsync$0(RemoteWriteableEntityBlobStore.java:85)
»  		... 4 more
»   ↑ repeated 44 times ↑

@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

❌ Gradle check result for dbc150a: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

shayush622 and others added 2 commits March 11, 2026 10:15
- Add ref_path parameter for package-based dictionary loading
- Load from config/packages/{packageId}/hunspell/{locale}/
- Add cache info API: GET /_hunspell/cache (cluster:monitor/hunspell/cache)
- Add cache invalidation API: POST /_hunspell/cache/_invalidate (cluster:admin/hunspell/cache/invalidate)
- Support invalidation by package_id, locale, cache_key, or invalidate_all
- Add security validation (path traversal, separator injection, null bytes)
- Add updateable flag for hot-reload via _reload_search_analyzers
- Use Strings.hasText() and Strings.isNullOrEmpty() for validation consistency
- Consistent response schema with all fields always present
- Add unit tests, REST handler tests, and integration tests

Signed-off-by: shayush622 <ayush5267@gmail.com>
@shayush622
shayush622 force-pushed the feat/hunspell-ref-path branch from dbc150a to 190bfd1 Compare March 11, 2026 04:47
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 190bfd1

@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 190bfd1: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

- Add ref_path parameter for package-based dictionary loading
- Load from config/packages/{packageId}/hunspell/{locale}/
- Add cache info API: GET /_hunspell/cache (cluster:monitor/hunspell/cache)
- Add cache invalidation API: POST /_hunspell/cache/_invalidate (cluster:admin/hunspell/cache/invalidate)
- Support invalidation by package_id, locale, cache_key, or invalidate_all
- Add security validation (path traversal, separator injection, null bytes)
- Add updateable flag for hot-reload via _reload_search_analyzers
- Use Strings.hasText() and Strings.isNullOrEmpty() for validation consistency
- Consistent response schema with all fields always present
- Add unit tests, REST handler tests, and integration tests

Signed-off-by: shayush622 <ayush5267@gmail.com>
@shayush622
shayush622 force-pushed the feat/hunspell-ref-path branch from 190bfd1 to 385793b Compare March 11, 2026 11:48
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 385793b

@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 385793b: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@shayush622

Copy link
Copy Markdown
Contributor Author

Breaking down the PR into two parts -> #20840 && #20841; thus closing this one

@shayush622 shayush622 closed this Mar 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for 385793b: SUCCESS

@codecov

codecov Bot commented Mar 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 43.60465% with 194 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.27%. Comparing base (8f8f7b5) to head (385793b).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...g/opensearch/indices/analysis/HunspellService.java 41.05% 44 Missing and 12 partials ⚠️
...ices/cache/hunspell/HunspellCacheInfoResponse.java 0.00% 33 Missing ⚠️
...rch/index/analysis/HunspellTokenFilterFactory.java 41.46% 10 Missing and 14 partials ⚠️
...nspell/TransportHunspellCacheInvalidateAction.java 11.53% 23 Missing ⚠️
...cache/hunspell/HunspellCacheInvalidateRequest.java 64.15% 13 Missing and 6 partials ⚠️
...che/hunspell/TransportHunspellCacheInfoAction.java 15.00% 17 Missing ⚠️
...min/indices/RestHunspellCacheInvalidateAction.java 37.50% 15 Missing ⚠️
...dices/cache/hunspell/HunspellCacheInfoRequest.java 0.00% 6 Missing ⚠️
.../main/java/org/opensearch/action/ActionModule.java 83.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #20792      +/-   ##
============================================
- Coverage     73.31%   73.27%   -0.05%     
- Complexity    72248    72308      +60     
============================================
  Files          5795     5804       +9     
  Lines        330044   330395     +351     
  Branches      47641    47696      +55     
============================================
+ Hits         241975   242092     +117     
- Misses        68609    68853     +244     
+ Partials      19460    19450      -10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

skip-diff-analyzer Maintainer to skip code-diff-analyzer check, after reviewing issues in AI analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants